profiling.tracing --- 決定論的プロファイラ¶
Added in version 3.15.
ソースコード: Lib/profiling/tracing/
The profiling.tracing module provides deterministic profiling of Python
programs. It monitors every function call, function return, and exception event,
recording precise timing for each. This approach provides exact call counts and
complete visibility into program execution, making it ideal for development and
testing scenarios.
注釈
後方互換性のため、このモジュールは cProfile としても利用できます。
cProfile という名前は、今後のすべての Python バージョンでも引き続き使えます。
コードベースに合ったインポート方法を使ってください。
# 推奨する新しい形式
import profiling.tracing
profiling.tracing.run('my_function()')
# こちらも動作する (後方互換性あり)
import cProfile
cProfile.run('my_function()')
決定論的プロファイリングとは¶
Deterministic profiling captures every function call, function return, and exception event during program execution. The profiler measures the precise time intervals between these events, providing exact statistics about how the program behaves.
In contrast to statistical profiling, which samples the call stack periodically to estimate where time is spent, deterministic profiling records every event. This means you get exact call counts rather than statistical approximations. The trade-off is that instrumenting every event introduces overhead that can slow down program execution.
Python はインタープリタで実行する言語なので、決定論的プロファイリングを実用的に行えます。 インタープリタは関数の呼び出しとリターンのイベントをすでに通知しているため、プロファイラはコードを変更せずにこの仕組みを利用できます。 インタープリタによる実行自体のコストと比べるとオーバーヘッドは比較的小さく、ほとんどの開発作業に適しています。
決定論的プロファイリングは、次のような疑問への答えを得るのに役立ちます。
この関数は何回呼び出されたか。
プログラム全体の呼び出しグラフはどうなっているか。
ある関数はどの関数を呼び出しているか。
予期しない関数呼び出しが起きていないか。
呼び出し回数の統計は、想定外の回数からバグを見つけたり、回数が多い箇所からインライン展開の候補を見つけたりするのに役立ちます。 関数内部の実行時間の統計は、最適化すべき「ホットループ」を明らかにします。 累積時間の統計は、アルゴリズムの非効率な箇所を見つけるのに役立ちます。 このプロファイラの累積時間の扱い方により、再帰的な実装と反復的な実装を直接比較できます。
コマンドライン・インターフェース¶
profiling.tracing モジュールをスクリプトとして実行し、別のスクリプトやモジュールをプロファイリングできます。
python -m profiling.tracing [-o output_file] [-s sort_order] (-m module | script.py)
指定したスクリプトまたはモジュールをプロファイラの下で実行し、結果を標準出力に表示します (またはファイルに保存します)。
- -s <sort_order>¶
指定したキーで出力をソートします。
cumulative、time、calls、nameなど、pstats.Stats.sort_stats()が認識するすべてのソートキーを指定できます。 このオプションは-oを指定していない場合だけ適用されます。
プログラムからの使用例¶
プロファイリングをより細かく制御するには、モジュールの関数とクラスを直接使います。
基本的なプロファイリング¶
最も簡単なのは run() 関数を使う方法です。
import profiling.tracing
profiling.tracing.run('my_function()')
指定したコード文字列をプロファイリングし、概要を標準出力に表示します。 後で分析するために結果を保存するには、次のようにします。
profiling.tracing.run('my_function()', 'output.prof')
Profile クラスを使う¶
Profile クラスを使うと、細かく制御できます。
import profiling.tracing
import pstats
from io import StringIO
pr = profiling.tracing.Profile()
pr.enable()
# ... プロファイリングするコード ...
pr.disable()
# 結果を表示する。
s = StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(pstats.SortKey.CUMULATIVE)
ps.print_stats()
print(s.getvalue())
Profile クラスはコンテキストマネージャーとしても使えます。
import profiling.tracing
with profiling.tracing.Profile() as pr:
# ... プロファイリングするコード ...
pr.print_stats()
モジュールリファレンス¶
- profiling.tracing.run(command, filename=None, sort=-1)¶
コマンドの実行をプロファイリングし、結果を表示または保存します。
この関数は
exec()を使い、__main__モジュールの名前空間で command 文字列を実行します。exec(command, __main__.__dict__, __main__.__dict__)
filename を指定しない場合、この関数は
pstats.Statsインスタンスを作成して概要を標準出力に表示します。 filename を指定した場合は、生のプロファイリングデータをそのファイルに保存し、後でpstatsを使って分析できます。sort 引数は表示する出力のソート順を指定します。
pstats.Stats.sort_stats()が認識する任意の値を指定できます。
- profiling.tracing.runctx(command, globals, locals, filename=None, sort=-1)¶
名前空間を明示的に指定して、コマンドの実行をプロファイリングします。
run()と同様ですが、__main__モジュールの名前空間の代わりに、指定した globals と locals のマッピングを使ってコマンドを実行します。exec(command, globals, locals)
- class profiling.tracing.Profile(timer=None, timeunit=0.0, subcalls=True, builtins=True)¶
実行統計を収集するプロファイラオブジェクトです。
省略可能な timer 引数は、カスタムの時刻取得用関数を指定します。 指定しない場合、プロファイラはプラットフォームに適したデフォルトのタイマーを使います。 カスタムの時刻取得用関数は、現在時刻を表す単一の数値を返さなければなりません。 整数を返す場合は、timeunit で 1 単位の長さを指定します (例えばミリ秒なら
0.001)。subcalls 引数は、関数間の呼び出し関係を追跡するかどうかを制御します。 builtins 引数は、組み込み関数をプロファイリングするかどうかを制御します。
バージョン 3.8 で変更: コンテキストマネージャーサポートが追加されました。
- enable()¶
プロファイリングデータの収集を開始します。
- disable()¶
プロファイリングデータの収集を停止します。
- create_stats()¶
データの収集を停止し、結果を現在のプロファイルとして内部に記録します。
- print_stats(sort=-1)¶
現在のプロファイルから
pstats.Statsオブジェクトを作成し、結果を標準出力に表示します。sort 引数はソート順を指定します。 単一のキーまたは複数段階のソート用のキータプルを指定でき、値は
pstats.Stats.sort_stats()と同じものを使います。Added in version 3.13: ソートキーのタプルをサポートしました。
- dump_stats(filename)¶
現在のプロファイルデータを filename に書き込みます。 このファイルは
pstats.Statsで読み込み、後から分析できます。
- runcall(func, /, *args, **kwargs)¶
関数呼び出しをプロファイリングします。 func が返す値をそのまま返します。
result = pr.runcall(my_function, arg1, arg2, keyword=value)
注釈
Profiling requires that the profiled code returns normally. If the
interpreter terminates (for example, via sys.exit()) during
profiling, no results will be available.
カスタムな時刻取得用関数を使う¶
Profile クラスはカスタムの時刻取得用関数を受け取れるため、実経過時間や CPU 時間など、実行のさまざまな側面を測定できます。
コンストラクタに時刻取得用関数を渡してください。
pr = profiling.tracing.Profile(my_timer_function)
時刻取得用関数は、現在時刻を表す単一の数値を返さなければなりません。 整数を返す場合は、1 単位の長さを表す timeunit も指定してください。
# 時刻取得用関数はミリ秒単位の時刻を返す。
pr = profiling.tracing.Profile(my_ms_timer, 0.001)
最高の性能を得るには、時刻取得用関数をできるだけ高速にしてください。 プロファイラはこの関数を頻繁に呼び出すため、そのオーバーヘッドはプロファイリングのオーバーヘッドに直接影響します。
time モジュールは、カスタムの時刻取得用関数に適した関数をいくつか提供しています。
time.perf_counter(): 高分解能の実経過時間time.process_time(): CPU 時間 (スリープを除く)time.monotonic(): 単調増加するクロックの時刻
制限事項¶
決定論的プロファイリングには、時間測定の精度に関する本質的な制約があります。
The underlying timer typically has a resolution of about one millisecond. Measurements cannot be more accurate than this resolution. With enough measurements, timing errors tend to average out, but individual measurements may be imprecise.
There is also latency between when an event occurs and when the profiler captures the timestamp. Similarly, there is latency after reading the timestamp before user code resumes. Functions called frequently accumulate this latency, which can make them appear slower than they actually are. This error is typically less than one clock tick per call but can become significant for functions called many times.
profiling.tracing モジュール (およびその別名 cProfile) は、オーバーヘッドの小さい C 拡張として実装されています。
そのため、非推奨の純粋な Python による profile モジュールよりも、こうした時間測定の問題は目立ちません。
参考
profilingPython のプロファイリングツールの概要と、プロファイラの選び方。
profiling.sampling本番環境向けの統計的サンプリングプロファイラ。
pstatsプロファイリングデータの統計分析と書式化。
profile非推奨の純粋な Python によるプロファイラ (補正方法のドキュメントを含む)。