최근 한 프로젝트를 진행중인 프로그램의 프로파일링 작업을 한창 하고있습니다.
프로파일링 하면 딱 떠오르는 프로그램이 Oprofile이나 Valgrind, gprof 들이며 매우 쓸만한 툴들이죠.
이번에 주어진 일에 대해서 이래저래 찾아보니 Valgrind의 Massif 툴을 이용하면 메모리 사용에 관련해서 상당히 구체적이고
쓸만한 정보가 튀어나온다는 사실을 알았습니다.
사용법은 간단합니다.
$ valgrind --tool=massif <App>
끝입니다. 참 쉽죠? ㄱ-
위의 커맨드를 실행하여 프로그램이 실행되면 massif.out.<PID>와 같은 형식으로 결과 파일이 생성됩니다.
만약 출력 파일명을 바꾸고 싶다면
$ valgrind --tool=massif --log-file='<원하는 파일명>' <App>
이런식으로 해주면 원하는 파일로 로그가 생성됩니다..
허나, 그냥 vi로 열어봐도 소용없습니다. 보기 힘들게 되어 있기 때문이죠. 그래서 다음과 같은 명령어를 더 기입합니다.
$ ms_print massif.out.<PID>
즉, 결과파일을 ms_print로 필터링을 해주면 아주(그나마......쿨럭) 보기 좋은 정보로 변환해줍니다. 다음은 출력 예제입니다.
19.63^ ###
| #
| # ::
| # : :::
| :::::::::# : : ::
| : # : : : ::
| : # : : : : :::
| : # : : : : : ::
| ::::::::::: # : : : : : : :::
| : : # : : : : : : : ::
| ::::: : # : : : : : : : : ::
| @@@: : : # : : : : : : : : : @
| ::@ : : : # : : : : : : : : : @
| :::: @ : : : # : : : : : : : : : @
| ::: : @ : : : # : : : : : : : : : @
| ::: : : @ : : : # : : : : : : : : : @
| :::: : : : @ : : : # : : : : : : : : : @
| ::: : : : : @ : : : # : : : : : : : : : @
| :::: : : : : : @ : : : # : : : : : : : : : @
| ::: : : : : : : @ : : : # : : : : : : : : : @
0 +----------------------------------------------------------------------->KB 0 29.48
Number of snapshots: 25
Detailed snapshots: [9, 14 (peak), 24]
상위에는 시간당 메모리 사용량을 그래프로 표시해 줍니다.
프로그램이 실행되면서 점차적으로 메모리 할당 내용을 보여주는 것이죠.
아스키 코드로 되어있지만 그래도 뭔가 눈에 들어옵니다;;
이제 그 다음행으로 가면 각 스냅샷마다의 메모리 사용 정보를 자세히 보여줍니다.
아, 스냅샷이란 개념은 즉 임의(는 아니지만 거의 그렇다고 보면 됩니다)의 지점에서 포인트를 찍고 그 부분에서의 사용량을 저장하는 개념이라 생각하면 됩니다.
--------------------------------------------------------------------------------
n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
15 21,112 19,096 19,000 96 0
16 22,120 18,088 18,000 88 0
17 23,128 17,080 17,000 80 0
18 24,136 16,072 16,000 72 0
19 25,144 15,064 15,000 64 0
20 26,152 14,056 14,000 56 0
21 27,160 13,048 13,000 48 0
22 28,168 12,040 12,000 40 0
23 29,176 11,032 11,000 32 0
24 30,184 10,024 10,000 24 0
99.76% (10,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->79.81% (8,000B) 0x80483C2: g (example.c:5)
| ->39.90% (4,000B) 0x80483E2: f (example.c:11)
| | ->39.90% (4,000B) 0x8048431: main (example.c:23)
| |
| ->39.90% (4,000B) 0x8048436: main (example.c:25)
|
->19.95% (2,000B) 0x80483DA: f (example.c:10)
| ->19.95% (2,000B) 0x8048431: main (example.c:23)
|
->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
위의 정보는 즉 다음과 같습니다.
'총 할당한 메모리에서 79.81%를 g라는 함수에서 사용하고 그 행은 example.c의 5번째 라인에 해당된다.
순차적으로 f와 main을 실행한다.'
여기서 B는 byte를 뜻하면 위 숫자의 용량 단위가 되겠습니다.
따라서 15번 포인트 지점에선 19KB의 메모리를 사용한다는 것을 알 수 있죠.
이런 식으로 해석해 나가면서 자신이 만든 프로그램이 어떻게 메모리가 할당되는지, 어떤 함수에서 많이 발생하는지,
너무 많이 할당하는 것은 어떻게 분해하거나 최적화 할 것인지 분석할 수 있습니다.
자세한 사용법은 http://valgrind.org/docs/manual/ms-manual.html#ms-manual.using에서 확인하세요~