Pythonのプロファイル結果をGUIで解析する
久しぶりのエキスパートPythonプログラミング補足記事です。今回はプロファイリングの補足です。
Pythonは標準ライブラリにプロファイラ(profile/cProfileモジュールのProfileクラス)を持っていて、 その結果を格納しているpstats.Statsクラスにはプロファイル結果を解析するのに必要な機能(実行時間でのソートや、呼び出し元/呼び出し先の表示など)が一通りそろっています。これらのクラスについてはエキスパートPythonプログラミングで使い方を解説してあります。
コマンドラインで作業するときにはIPythonからStatsオブジェクトを直接操作してプロファイル結果を調べられるのですが、やはりプロファイル結果はグラフィカルに表示してくれた方が見やすいものです。特に「エキスパートPythonプログラミング」の中でも言及されているKCacheGrindというGUIツールは非常に強力で、一度使うと手放せません。
KCacheGrindが対応しているcallgrind形式は、元々はValgrindのツールの一つであるCallgrindのものでしたが、 最近はプロファイル結果を保存するフォーマットとして広く用いられています。callgrind形式ファイルのブラウザとしてはKCacheGrind以外にも、Windowsで動くWinCacheGrind、PHP製でブラウザ上で表示するwebgrind 等がありますし、PHPのxdebugに含まれるプロファイラもcallgrind形式でプロファイル結果を保存します。
弊社でも日常的にcallgrind形式のプロファイル結果を共有していて、そのために社内のWebツールまで用意しています。(紹介記事: PHP Xdebug のProfileの手軽な共有ツールを作ったよ)
しかし、Statsクラスはcallgrind形式には対応しておらず、プロファイル結果を保存するときのファイルフォーマットは独自フォーマット(Statsの内部変数をmarshal形式で保存したもの)になっています。このままでは、Pythonのプロファイル結果をKCacheGrindで表示することができません。 そこで、Statsオブジェクトをcallgrind形式で保存するためにlsprofcalltree.pyを利用します。
lsprofcalltree.pyは、コマンドラインツールとして $ lsprofcalltree.py スクリプトファイル
という使い方もできますし、アプリケーションに組み込んで使うこともできます。例えばBazaarでは $ bzr --lsprof-file callgrind.out status
のように実行するとプロファイル結果をcallgrind形式で出力するようになっています。
プロファイル結果を見やすくビジュアライズできる環境が整うと、アプリケーションのチューニングが楽しくなります。 KCacheGrind等のGUIツールとcallgrind形式のファイルを出力するプロファイラは、Pythonプログラマに限らずみんな常備しておくといいと思います。