ヒーププロファイラでメモリ使用状況を解析する

google-perftoolsのヒーププロファイラは、ヒープチェッカと同様にTCMallocの一部として提供されている機能である。これを使うことで、プログラムのメモリ使用状況を容易に調べることが可能となる。

ヒーププロファイラを利用するためにプログラムのソースコードに変更を加える必要はない。TCMallocと同様に、コンパイル時に-ltcmallocオプションを指定してlibtcmalloc.soをリンクするだけでよい。例えばlibtcmalloc.soが/usr/local/lib/ディレクトリに配置されている場合に、heapsample.ccというプログラムをコンパイルするには次のようにする。

-ltcmallocオプションを指定してheapsample.ccをコンパイル

$ gcc -o heapsample -L/usr/local/lib/ -ltcmalloc -I/usr/local/include/ heapsample.cc

また、TCMallocやヒープチェッカーと同様に、実行時にLD_PRELOAD環境変数を指定して利用することもできる。もちろん、この場合はソースコードの再コンパイルは必要ない。

実行時にはHEAPPROFILE環境変数にプロファイル結果の出力先を設定する。例えば以下のようにした場合、結果は/tmp/myprofile.0001.heapというファイルに出力される。

LD_PRELOADにプロファイル結果の出力先を指定して実行

$ HEAPPROFILE=/tmp/myprofile ./heapsample 
Starting tracking the heap
Dumping heap profile to /tmp/myprofile.0001.heap (Exiting)

/tmp/myprofile.0001.heapの中身を見るには、ヒープチェッカーのときにも使用したpprofコマンドを利用する。pprofを、第1引数にプログラム実行時のコマンドを、第2引数にプロファイル結果のファイルを指定して実行する。すると以下のようにpprofの対話モードになる。

pprofコマンドで解析結果を読む

$ pprof ./heapsample /tmp/myprofile.0001.heap
Welcome to pprof!  For help, type 'help'.
(pprof)

ここで"help"とタイプすればこの対話モードの利用方法が表示される。"top"とタイプすると、以下のようにオブジェクトやメソッドのメモリ使用量が一覧表示される。ちなみにheapsample.ccはFuncA()とFincB()というメソッドを持ち、それぞれは単にmallocで若干のメモリを確保しているだけである。

pprofで'top'とタイプ

(pprof) top
Total: 7.0 MB
     6.0  85.7%  85.7%      6.0  85.7% FuncA
     1.0  14.3% 100.0%      3.0  42.9% FuncB
     0.0   0.0% 100.0%      7.0 100.0% main
     0.0   0.0% 100.0%      7.0 100.0% _start
     0.0   0.0% 100.0%      7.0 100.0% _init

pprofの対話モードで"gv"とタイプすると、メモリの使用状況がPostscript形式で可視化され、以下のようにgvによって表示される。各ノードにはクラス名(もしあれば)、メソッド名、メモリ使用量と全体に対する使用率が記載されている。メモリ使用量の上段はそのノード内のみでのサイズであり、下段は呼び出し先のメモリも含めたサイズとなっている。

メモリ使用状況をグラフで表示

pprofを終了させるには"quit"とタイプする。なお、対話モードに入らなくても--textおよび--gvオプションを付けてpprofを実行することでも上記と同じ処理が行える。次のようにすればよい。

対話モードを使用せずにプロファイル結果を表示する

$ pprof --text ./heapsample /tmp/myprofile.0001.heap
$ pprof --gv ./heapsample /tmp/myprofile.0001.heap