|
Darryl Gove |
|
들어가는글
성능 분석은 어플리케이션의 구동 속도와 해당 구동 속도의 이유를 분석해 보고, 그에 따라 퍼포먼스를 향상시킬 수 있는 방법을 찾는 과정입니다. 성능이 최대한도로 향상된 시점을 아는 것이 좀 더 복잡한 과정이라고 할 수 있겠습니다.
어플리케이션의 성능은 하드웨어와 소프트웨어의 요소들의 결합에 따라 달려 있습니다. 예를 들어 하드웨어가 어떠한 이벤트를 다루어야 하는지 그리고 어플리케이션을 컴파일 할때 어느정도의 최적화가 되어 있는지 같은 것들입니다. 이러한 정보를 추출할 수 있는 여러가지 툴이 있지만 특정 어플리케이션에 어떤 툴을 사용해야 할지 결정하는 것은 쉬운 일은 아닙니다.
이 글은 성능 분석의 과정을 간단하게 만들어 주는 새로울 툴을 소개합니다. 우리는 이 툴을 SPOT(Simple Performance Optimisation Tool)이라고 부릅니다. Spot은 썬 스튜디오11에 새로 추가된 패키지로써 UltraSPARC 기반 시스템에서만 사용이 가능합니다. Spot은 Cool Tools 프로젝트의 일환으로 배포 되었습니다. 이 툴에 대한 자세한 정보는 다음 사이트에서 찾으실 수 있습니다.
spot이란?
spot의 기본적인 아이디어는 주어진 어플리케이션의 성능에 대한 보고서를 최대한 간단하게 만드는 것이라고 할 수 있습니다. spot을 이용하여 이러한 작업을 하는 방법에는 두가지가 있는데, 이 두가지 중 대부분의 데이타를 생성하는 방법은 복합적으로(multiple) 수행 될 수 있는 어플리케이션을 위한 방법입니다. 이 경우 어플리케이션이 구동되는동안 spot은 포괄적인 툴들 하에 애플리케이션을 구동하고 각 툴에 대한 데이타를 수집하게 됩니다. 한편, 연속적으로(continously)으로 구동되는 어플리케이션의 경우에는 spot은 현재 구동되고 있는 어플리케이션에 부착되어 각 툴을 이용하여 짧은 시간 동안 데이타를 수집 할 수 있습니다.
spot의 유용한 기능 중 하나는 하이퍼링크 되어 있는 웹페이지 형태로 어플리케이션의 성능을 보고한다는 것입니다. 이에 따라 몇가지 풀기 힘든 문제를 해결할 수 있습니다. 첫번째로 spot-보고서는 주어진 작업 하에서 어플리케이션의 퍼포먼스에 대한 스냅샷을 기록 합니다. 또한 빌드 플래그와 시간이 소요된 어플리케이션 부분에서의 소스 코드 등도 보여 줍니다(이러한 정보가 사용 가능하다는 가정 하에). 두번째로 spot-보고서는 하이퍼텍스트 문서이기 때문에 URL을 이용해서 정확하게 특정 부분을 집어 낼 수 있습니다. - 이 기능은 원격 머신에서 작업하거나 원격의 동료들과 협업을 하고 있을때 매우 유용 합니다.
spot의 아키텍쳐는 다음의 그림과 같습니다.

Spot은 여러가지 툴들을 사용하고 각 툴들은 리포트의 부분들을 생성합니다. spot이 사용하고 있는 주요 툴들은 다음과 같습니다.
-
썬 스튜디오 퍼포먼스 분석기의 'collect' 커맨드. 이 커맨드는 어플리케이션에서 시간이 소비된 곳의 프로파일이나 이벤트가 발생한 곳에 대한 자료를 수집해 줍니다.
-
'ripc' 커맨드는 프로세서가 지연(stall)되고 있는 곳에서 얼마나 시간이 소비 됐는지에 대한 정보를 수집해 주고 문제를 일으킨 지연의 종류들에 따라 정보를 수집해 줍니다. 예를 들어 예를 들어 메모리상에 있는 데이타를 기다리는데 소비된 시간을 보고해주고 (이것을 위한 카운터의 이름은 Re_EC_miss 임. 카운터의 이름들은 프로세서 유저 가이드에서 찾을 수 있음). 이 커맨드는 정확하게 프로그램에 어떤 부분에서 특정한 이벤트가 발생했는지 결정하기 위해 'collect'를 이용하여 프로파일할 가치가 있는 카운터들을 결정해 줍니다. ripc 툴은 gnuplot이 유저 패스상에서 존재 할 경우 몇가지 종류의 그래프를 생성해 줍니다.
-
BIT 툴은 어플리케이션에 부착 되고(어플리케이션이 올바르게 컴파일 됐을 경우) 각 루틴과 명령어들이 몇번 수행 됐는지 세어 줍니다. 이러한 정보를 이용하면 특정한 루프의 수행속도 혹은 비교 조건들이 얼마나 자주 참 혹은 거짓이 되는지 알아 낼 수 있습니다.
-
'collect' 커맨드와 BIT 의 출력은 er_html 이라 불리는 툴에 전달 되게 됩니다. er_html 는 퍼포먼스 분석기의 er_print 를 이용하여 데이타를 하이퍼링크 웹페이지 형태로 전환 하도록 해 줍니다. 이러한 페이지들은 소스를 보여주고(만약 어플리케이션이 디버깅 옵션으로 컴파일 되었다면) 시간이 소비된 곳에서의 코드 부분을 디스어셈블해 줍니다.
-
툴 'bw'는 전체 어플리케이션이 돌아가는 상태에서 시스템 전체의 활용율 대역폭을 보고해 줍니다. 툴 'traps'는 시스템 전체의 트랩 통계를 보고해 줍니다. 이러한 툴들은 수행되기 위해 루트 권한이 필요 합니다. 이 툴은 snuplot이 사용자 경로상에 있을 경우 그래프를 생성해 줄 것입니다.
spot 구동하기
Spot 은 썬 스튜디오11 기반 위에서 설치 됩니다. 만약 썬 스튜디오가 기본 경로인 /opt/SUNWspro 에 설치되었다면 spot은 /opt/SUNWspro/extra/bin.에 위치하게 됩니다.
Spot은 다음의 두가지 방법중 하나의 방법으로 실행 가능합니다:
/opt/SUNWspro/extra/bin/spot <어플리케이션> <파라미터> 의 방법으로 실행된다면
각각의 새로운 툴 하에서 여러번 타켓 어플리케이션이 수행될 것입니다.
/opt/SUNWspro/extra/bin/spot -P <pid> 의 방법으로 실행된다면
현재 수행중인 프로세스에 부착되고 짧은 시간 동안 각각의 툴들이 돌아가면서 분석을 수행합니다. 이 두 경우 모두 리포트는 거의 같습니다.
기본적으로 spot은 어플리케이션의 성능에 대한 간략한 보고서를 생성합니다. 그러나 spot이 -X 플래그에 의해 실행 된다면 좀 더 디테일한 데이타를 제공해주게 될 것입니다. (적당한 권한을 가지고 있다는 가정 하에).
spot을 이용해 좀 더 많은 데이타를 얻기 위한 어플리케이션 컴파일
spot에서 최대한의 이점을 얻기 위해서 어플리케이션은 썬 스튜디오 11 컴파일러에 의해 컴파일 되어야 합니다. 다음의 플래그들이 요구 됩니다:
-
C 혹은 포트란을 위해 -g 디버깅 정보 옵션을 활성화 시킵니다. -g0 는 C++ 을 위한 옵션입니다. 이것은 spot이 단순히 어셈블리 언어로 출력해 주는 대신에 각 소스 라인 별로의 시간을 보고 할 수 있도록 해줍니다.
-
spot이 BIT를 이용해서 명령어와 함수 별로 데이타를 수집하기 위해서는 어플리케이션을 -O, -fast, 혹은 최소한-xO1 옵션을 사용하고 그리고 -xbinopt=prepare 플래그를 사용해야 합니다. 이러한 플래그들은 BIT 툴이 바이너리에 충분한 정보를 저장할 수 있도록 도와 줍니다.
예제
test.c 코드는 spot-보고서의 중요한 기능들을 보여줄 것입니다. 이 테스트 코드는 다음에 대해 보여줍니다.
-
메모리 대역폭 소비
-
캐쉬 미싱 유발
-
TLB 미싱 유발
툴의 효과적인 데모를 위해서 코드는 최소한의 최적화 플래그를 이용해서 컴파일 되어야 하고 올바른 컴파일러 플래그를 이용해야 합니다
cc -g -O -xbinopt=prepare -o test test.c
이제 다음의 명령을 이용해 spot 하에서 구동될 수 있습니다.
spot -X test
시스템과 빌드 정보 기록하기
spot이 테스트 베드에서 가장 처음 하는 일은 데이타를 수집 하기 위해 정보를 기록하는 일입니다. 그리고 어플리케이션 빌드에 사용된 플래그들을 저장합니다. 다음의 그림을 참고 바랍니다.

이번 경우, 어플리케이션은 위와 같이 빌드 되었고 8개의 900Mhz 울트라스팍III+ 프로세서를 가진 시스템에서 구동되었습니다.
하드웨어 성능 카운터 정보
ripc 툴은 어플리케이션을 수행시키고 프로세서에 있는 성능 카운터에 기록된 정보를 바탕으로 데이타를 수집합니다. 성능 카운터에서 수집된 정보들은 이 문서 에서 제안된 대로 올바른 컴파일로 옵션을 선택하는데 사용할 수 있습니다. ripc로 얻은 정보는 다음의 그림 처럼 테이블의 형태로 제공 됩니다.

위의 표에는 3가지 주요 부분이 있습니다. 첫번째 부분은 시스템 지연을 일으키는 다양한 하드웨어 조건에서 소비된 시간을 제공 해 주는 부분입니다. 위의 예제에서는 거의 전체 실행시간에 어플리케이션이 지연 되고 있습니다.
약 14% 의 시간이 데이타 TLB 미싱에 의하여 소비 되었고(DTLB_miss) 이 상황은 보통 -xpagesize=4M 컴파일러 플래그를 사용하여 바르게 고쳐 질 수 있습니다.
~80% 이상의 실행시간이 데이타 캐쉬에 데이타가 없을때 데이타를 기다리는 지연에 의해 소비 되었습니다(Re_DC_miss). 약 60%의 실행시간이 데이타가 외부 캐쉬에 없을때 데이타를 기다리는 데에 소비되었습니다(Re_EC_miss). 이는 수행시간의 약 20% 수행 시간 동안 데이타가 데이타 캐쉬에 있지 않고 외부 캐쉬에 있었음을 의미 합니다.
다음 부분은 프로세서가 각 사이클 마다 얼마나 의미 있는 일을 했는지 측정 해 주는 IPC(Instructions per Cycle)을 보고해 주는 부분입니다. 그룹화된 IPC는 만약 프로세서가 어떠한 지연 조건도 만나지 않고 수행 되었을 경우 얼마나 많은 일을 할 수 있는지 측정하는 것을 나타내 줍니다.
이 부분에서 툴은 또한 수행시에(시스템 전체에서) 발생한 완전히 끝나지 않은 부동소숫점 트랩의 숫자를 보고 해 줍니다. 부동 소숫점 트랩은 거의 일어나지 않습니다. 발생하였을 때, 이 것이 문제라는 것을 발견 하는 것은 매우 어렵습니다.
마지막 부분은 어플리케이션의 메모리 사용량을 보고해주는 부분입니다.
만약 경로 상에 gnuplot이 사용 가능하다면 이 정보는 그래픽 형태로도 보여 집니다.
그림 4 - ripc 출력 프로그램 수행시의 DTLB 미싱
위의 그림에서 데이타 TLB 미싱은 전체 프로그램에서 나타 납니다. 첫번째 수행에서는 매우 소수의 TLB 미싱이 발생하지만 후에는 엄청나게 많이 발생함을 알 수 있습니다.
명령어 사용 빈도
툴 BIT는 몇가지 정보를 제공 합니다. 이중에 가장 유용한 것은 각 루틴이 몇번 불려 졌고 각 명령이 몇번 실행 되었는지 알 수 있다는 것입니다. 이러한 것들은 프로파일 섹션에 의해 다루어지게 될 것입니다. 어쨌든 BIT는 각각 명령의 사용 빈도에 대한 정보도 수집합니다. 예를 들어 벤치마크 수행 중에 얼마나 많은 부동 소숫점 명령이 수행 됐는지도 알 수 있습니다.
BIT에 의한 카운트는 어플리케이션에 한정된 범위 만을 다루므로 라이브러리 호출은 다루지 않습니다. 몇몇 경우(예를 들어 C++의 템플릿 같은) 모든 코드들이 다루어지지 않으므로 결과가 완료 되지 않습니다.
다음의 그림은 테스트 프로그램의 명령어 사용 빈도를 보여 줍니다.

위의 예제에서 53%의 명령어는 작은 부동 소숫점과 관련이 되 있고 40%의 명령어는 부동소숫점의 적재, 저장과 관련이 되 있으므로 13%의 명령어는 부동소숫점의 계산에 관계 되 있다고 말할 수 있습니다.
BIT 는 또한 정확하게 지연된 슬롯과 잘못된 동작들에 존재하는 명령어를 세어 줍니다. 지연된 슬롯이란 브랜치 이후에 있는 명령어를 말합니다. 브랜치가 수락 되었거나 명령어들이 실행되거나 실행되지 않는 것에 달려 있습니다. 만약 실행이 되지 않는 다면 이것을 잘못된 명령(annulled) 명령이라고 합니다.
시간 기반의 프로파일
spot 은 'collect' 커맨드를 사용하여 어플리케이션의 시간 기반 프로파일을 수집합니다. 또한 하이퍼링크된 웹페이지 형식으로 변환 시킵니다. 테스트 코드의 프로파일은 아래와 같습니다:

그림 6 - 테스트 코드의 프로파일
프로파일은 collect와 BIT 두가지의 정보를 결합시킵니다. 각 셀의 항목은 다음과 같습니다:
-
exclusive user time 은 명명된 루틴에서 코드를 실행하는데 소요된 시간을 나타 냅니다.
-
inclusive user time 은 명명된 루틴에서 코드를 수행하는데 소요된 시간과 그것이 호출한 모든 루틴들이 걸린 시간까지 포함합니다.
-
system time 셀은 주어진 루틴이 시스템 코드 상에서 소비한 시간을 나타 냅니다.
-
wall time 셀은 메인 쓰레드의 수행 시간을 나타 냅니다. 싱글 쓰레드 어플리케이션에서 이 프로파일은 유저, 시스템 타임과 비슷 합니다. 멀티 쓰레드 어플리케이션에서 이 프로파일은 마스터 쓰레드가 무엇을 하고 있는지 추적 합니다.
-
exclusive function count 컬럼은 주어진 루틴이 어플리케이션 수행시에 불려진 횟수를 카운트 합니다. 이 정보는 BIT에 의해 제공 되고 올바르게 컴파일된 바이너리에서만 사용 가능 합니다. 카운트 데이타는 라이브러리 안에 루틴에 대해서는 사용이 불가 합니다. 이 것은 _memset 가 절대 호출 되지 않은 것으로 나타난 것을 통해서 관찰 될 수 있습니다.
-
exclusive instructions executed 컬럼은 어플리케이션 수행시에 각 루틴에서 몇개의 명령어가 실행 되었는지를 나타냅니다. 다시한번 말해서 이 정보는 모든 루틴에서 사용 가능하지는 않습니다 - 즉 라이브러리 내의 루틴들은 제외 됩니다.
-
exclusive instructions annulled 컬럼은 annull 된 지연 슬롯에 있는 명령어들의 갯수를 말합니다.(즉 실행되지 않은 것들)
오른쪽 페이지는 다음과 같은 결과들의 하이퍼링크가 있습니다:
-
trimmed link 는 디스어셈블한 결과(만약 가능하다면 소스까지)로 가게 됩니다. 이 결과는 사이즈를 줄이기 위해 코드의 중요한 부분만 보여 주도록 되어 있습니다. 프로파일을 자세히 검사하기 위한 가장 최선의 링크가 이것입니다, 왜냐하면 untrimmed 된 디스어셈블리 결과는 종종 수메가 정도의 사이즈로 크기 때문입니다.
-
name of the routine 은 untrimmed 디스어셈블리로 연결되어 있습니다 (만약 가능하다면 소스까지).
-
src link 는 주어진 루틴의 소스로 가게 되어 있고 소스 코드의 각 라인의 속한 시간과 이벤트들을 보여 줍니다. 이 링크는 오직 특정한 루틴의 소스 코드를 툴이 찾을 수 있을때에만 사용 가능합니다.
-
caller-callee link 는 어떠한 루틴이 어떠한 루틴을 불렀는지 보여주는 페이지로 가게 되어 있습니다.
다음의 그림은 소스코드와 디스어셈블리의 혼합을 예로 보여 주고 있습니다. 즉 각 어셈블리 명령의 수행 시간을 보여주고 있습니다.

그림 7 - 어셈블리 명령어들의 프로파일
셀들은 각 어셈블리 명령어들 마다 소비된 시간과 실행된 횟수를 나타내고 있습니다. 이 정보를 통해서 라인 0x1243c 과 0x12448 에서 루프가 수행된 횟수가 약 170만 번이고 루프는 오직 한번 들어가졌음을 알 수 있습니다.
시간은 0x1243c 에 있는 증가 명령어에 의해 기록 됩니다. 성능 분석기에 의해 사용되어 지는 샘플링 메소드는 실행 되기 위해 기다려 지는 명령들에 의해 소비 되는 시간을 기록 합니다. 즉 이 경우 증가 시키기 전에 명령이 수행 되었는지 확인 하는 것을 필요로 합니다; 즉 0x12448 이 로드 로 밝혀 졌습니다. 즉 이 로드 명령이 거의 대부분의 시간을 차지 함을 나타 냅니다.
디스어셈블리에 여러가지 하이퍼링크들이 있습니다. 사각형 안에 있는 링크들은 어셈블리 명령들이 속한 곳으로 점프 하도록 되어 있습니다. 브랜치 명령어들은 해당 브랜치 타겟으로 점프 하도록 되어 있습니다.
하드웨어 이벤트 프로파일
만약 spot이 -X 옵션으로 실행하면, 대부분의 지연 시간을 기록하는 퍼포먼스 카운터를 이용한 프로파일 정보를 수집하게 됩니다. 다음 그림에서 프로파일은 테스트 프로그램에서 발생한 하드웨어 카운터 이벤트를 보여 줍니다.

그림 8 - 하드웨어 카운터를 이용한 프로파일링
처음 두개의 프로파일을 보면 3가지 루틴 모두에서 데이타 케쉬 미스가 발생하여 여러가지의 싸이클이 지연되었음을 알 수 있습니다. 두번째 포로파일을 보면 외부 캐쉬 미스 이벤트가 오직 cache_miss 와 tlb_miss 루틴에서 발생 했음을 알 수 있습니다
시스템 전반의 대역폭 소비와 트랩 데이타
만약 spot의 루트 퍼미션과 함꼐 -X 플래그로 실행된다면, 전체 어플리케이션 수행상에서 발생하는 트랩들과 시스템 전반의 대역폭 소비 정보를 수집하게 됩니다. 만약 다른 어플리케이션이 시스템에서 수행된다면 이러한 통계는 다른 어플리케이션에서 발생하는 대역폭 소비와 트랩들도 같이 포함하게 됩니다.
대역폭 소비와 트랩 정보가 전체 수행 상태를 요약한 테이블 형태로 보여지게 됩니다. 만약 gnuplot 이 유저 경로 상에 존재 한다면 결과는 그래픽 형태로 보여 지게 될 것입니다.
다음의 그림은 어플리케이션 수행시에 대역폭 소비 그래프를 보여 줍니다.
그림 9 - 어플리케이션 수행시의 대역폭 소비 상황
대부분의 대역폭은 데이타가 메모리에서 옮겨지는 첫번째 루틴에서 소비 되었습니다. 후에 루틴들은 메모리 레이턴시를 체크 하는 테스트 이므로 대역폭을 덜 소비합니다.
다음 그림은 어플리케이션이 수행 되는 동안의 데이타 TLB 트랩 을 보여 줍니다.
그림 10 - 어플리케이션 수행 중의 데이타 TLB 트랩
기대 했던대로 트랩 데이타는 같은 이벤트에서 하드웨어 카운터에 의해 보고 됐던것과 비슷하게 나타났습니다.
결론
spot은 유저가 코드의 어느 부분에서 시간이 많이 소비 되는지 알 수 있도록 도와 주는 유용한 툴 입니다. 또한 어플리케이션의 느려짐 현상을 확인 할 수 있도록 도와 주기도 합니다.
spot에 대한 자세한 정보는 다음의 사이트를 참고 바랍니다. http://cooltools.sunsource.net/spot/index.html
"개발자코너" 카테고리의 다른 글
- DTrace를 사용하여 유저가 조정하는 애플리케이션 크래쉬 데이타 정보 모으기 (댓글 1개 / 트랙백 0개) 2006/08/23
- D 스크립트 배우기 (댓글 0개 / 트랙백 0개) 2009/11/23
- C++ 표준 라이브러리인 libCstd와 libstlport 비교하기 (댓글 1개 / 트랙백 0개) 2006/07/23
- 썬 스튜디오: VIS 명령을 사용하여 중요한 루틴의 속도를 향상시키기 (댓글 1개 / 트랙백 0개) 2006/02/23
- 썬 스튜디오 dbx 를 이용한 AMD64 명령어 레벨의 디버깅 (댓글 0개 / 트랙백 0개) 2007/12/14
- 솔라리스에서의 유저 인증: Part 1 (댓글 0개 / 트랙백 0개) 2007/10/21
- C++ ABI의 안정성: 프로그래밍 언어의 진화 (댓글 1개 / 트랙백 0개) 2006/02/23
- 솔라리스 디바이스 드라이버 작성을 원하십니까? (댓글 1개 / 트랙백 0개) 2008/09/18
- DLight 소개 (댓글 0개 / 트랙백 0개) 2009/06/29
- Dmalloc 을 솔라리스, 썬 스튜디오 컴파일러와 사용하기 (댓글 6개 / 트랙백 0개) 2007/06/13
댓글을 달아 주세요
좋은 정보 감사해요~
2007/09/19 04:22