blogこの広告は、90日以上更新していないブログに表示しています。2013-08-16PythonコードのプロファイリングPython普段、Pythonのコードは何となく速かろうという、言ってみれば勘で書いているのだけど、その勘とやらは往々にしてウンコードを生むものである。そこで、プロファイラを使っていきたいと思う。使えそうなツールそういうわけで、いくつか使えそうなツールをリストアップした。物は試しということで、ざっくり使ってみた。pymplerあたりが良いかなーという感じがしている。経過時間のプロファイラ実験用の適当な関数を用意した。documentationビルトインの決定論的プロファイラ。プロファイラの拡張を考えていないならオーバーヘッドの少ないcProfileを使う。profileとcProfileのインターフェースはほぼ共通とのこと。プロファイリングの結果は、pstatsモジュールを介して操作する。cPofileでプロファイルするには、以下のようにrunメソッドに文字列で計測したいコードを渡すだけで良い。objects}第二引数にファイル名を指定すればファイルに出力できる。{time.sleep}というように、本質的に悪いのは従業員ではないことも分かる。以下のような書き方も出来る。#クリアしない場合は、結果が追加されていく。ファイル全体をプロファイルするには以下のようにする。objects}結果の操作はpstatsを使う。objects}ちなみに、IPythonなら%prunマジックでショートカットできる。objects}line_profilerhttp://pythonhosted.org/line_profiler/line_profilerは行単位でプロファイルしてくれる。pipでインストールするとkernprof.pyがコマンドとして使えるようになる。プロファイル対象の関数に@profileデコレータを付しておく。)これで、kernprof.pyを実行すると、__builtins__空間にprofileを挿入して、プロファイルを開始する。fibsあるいは、cProfileと同様にインスタンスを取得して操作することも出来る。APIは親切にもcProfileとほとんど同じ。#インスタンスに複数の関数を与えても良い。fib.lprofへ結果を出力IPythonを使うときは、以下の設定をする。#QtConsole用これで、%lprunマジックが使えるようになる。fibsどうもその場で定義した関数をプロファイルするのは出来ないらしい。Plophttps://github.com/bdarnell/plopPlopは統計的プロファイラで、Dropboxのワークショップとやらで開発が始まったらしい。プロファイル結果は、D3というJavascriptの可視化ライブラリを介して確認する。部分的にサンプリングしたいときは、以下のようにCollector.startとstopで囲む。c.stop()あるいは、全体を対象にするには以下のようにする。test.py結果は付属のtornado製のツールで確認する。結果ファイルはデフォルトだと/tmpに入る。#これでサーバが起動するので、localhost:8888へ。一覧の中からファイル(plop.out)を選択すると、こんな感じのグラフが出現する。ノードの色は、ファイルごとに分けられる。ノードの大きさは、消費時間を表している。リンクの太さが、呼び出し回数に比例するようになっている。Webアプリケーション向けですね。statprofhttps://pypi.python.org/pypi/statprof/これも統計的プロファイラ。)statprof.stop()statprof.display()このコードを実行すると、以下のような出力が得られる。secondsyephttps://pypi.python.org/pypi/yepC/C++/Fortran拡張モジュールのための統計的プロファイラ。yepはgperftoolsを使って拡張モジュールをプロファイリングする。開発中にCのプロファイラを忍ばせておけば良いので、どういうときに使うのか分からない。いえ、見つけてしまったので、試してみた。ここでフィボナッチアゲイン。)この洗練された拡張モジュールは、見ての通りgmpの関数をやたらと呼び出している。手っ取り早くオーバーフローを防ごうとしたらこのザマである。(実は、この拡張モジュールはピュアPythonよりも遅い!)実行は、以下のようにする。file:////tmp/pprof34359.0.svg出力されたコールグラフはこんな感じあるいは、標準出力に表示するには以下のようにする。_reallocなるほどそういう感じね;;メモリのプロファイラメモリのプロファイラには、行単位でスナップショットを撮るものと、指定された時間にオブジェクトごとのスナップショットを撮るものがある。memory_profilerhttps://github.com/fabianp/memory_profilerPythonインタプリタのプロセスのメモリ消費を監視してて、行単位でその差分を記録してくれる。裏でpsutilモジュールを使う。画像を読めばメモリ食うだろうということで、試しに画像のガンマ補正をしてみる。)結果は以下のとおり。時間間隔で計測することも出来る。89.796875,(略)IPythonで使うときは、例によって設定ファイルに以下を追加する。]これで%mprunマジックが使えるようになる。fibsこれもファイルからインポートした関数しか渡せない。Heapyhttp://guppy-pe.sourceforge.net/#Heapyこれが一番有名なのだろうか。Heapyはスナップショットを撮ってオブジェクト毎のメモリ消費量を記録してくれる。以後、これ以前のデータセットを差し引く。hp.heap()これを実行すると、以下のような結果が得られる。guppy.etc.Glue.Owner出力の書式は、いろいろ指定できる。view.>さらに、個別要素の参照をたどるとかいうことも出来る。owner)正直まだよく分かっていない。Pymplerhttps://github.com/pympler/pympler概ねHeapyと同じようなもので、オブジェクトごとのメモリ消費量を知らせてくれる。オブジェクトのサイズを得るにはasizeofを使う。)440存在するオブジェクトを取得したり、サマリーしたりするにはmuppyやsummaryを使う。B>このような、差分を追跡する処理には、専用のモジュールがあって以下のようにも書ける。B>それから、特定のクラスのインスタンスを追跡する謎モジュールがあって、これが意外に便利っぽい。)trckr.create_snapshot()trckr.stats.print_summary()こんな感じでパンダをケージにぶち込んでいく様子は以下のように観察できる。0%-------------------------------------------------------------------------------特定のパンダの様子を観察したければ、以下のようにすれば良い。)可視化ツールそろそろ飽きてきたので、簡単に可視化ツールを見て終わりにする。RunSnakeRunhttp://www.vrplumber.com/programming/runsnakerun/これはcProfileおよびProfileの結果をグラフィカルに表示するためのツール。インストールは若干面倒だけど頑張って入れる。実行は、runsnakeコマンドにプロファイラの出力ファイルを渡すだけ。test.prfこんな感じのが起動する。cProfileの出力をGraphvizを使って可視化してくれる。以下のコマンドで、プロファイラの出力ファイルを渡して画像を生成する。test.jpgこんなのが出来る。cProfileの出力に相違ない。PyCallGraphhttp://pycallgraph.slowchop.com/Graphvizを使って、コールグラフを出力してくれる。描画対象のコードを、pycallgraph.strt_traceとpycallgraph.make_dot_graphで囲むだけ。pycallgraph.make_dot_graph('test.png')ガンマ補正するコードで試してみたのが以下メモプロファイリングには方法論的に以下の2種類がある。決定論的プロファイリング統計的プロファイリング決定論的プロファイリングは、関数の呼び出しなどのイベントにフックして経過時間を計測する方法で、統計的プロファイリングはプロフラムの何処を実行しているかをランダムにサンプリングして推定する方法である。そのため、決定論的プロファイリングは正確さがウリで、統計的プロファイリングはオーバーヘッドの小ささがウリである。Webアプリケーションなどで、動作中にプロファイリングをしたい場合は、統計的プロファイリングが良いらしい。それから、プロファイリングの粒度によって、以下の2種類がある。マクロ・プロファイリングマイクロ・プロファイリングマクロ・プロファイリングとは、モジュールとか関数、ブロックのような、まとまり毎に経過時間を計測するやり方。一方の、マイクロ・プロファイリングは、関数の特定の範囲とか、プログラムの行レベルで経過時間を計測するやり方である。最初にマクロ・プロファイリングをして的を絞ってからマイクロ・プロファイリング、というように徐々に粒度を小さくしていくのが良いらしい。2012の動画を見てたら面白いもの見つけたのでメモ。(1)はてなブログをはじめよう!shkhさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。