デコレータのプロファイリング:ツールとテクニック
By khoanc, at: 2025年4月19日19:48
Estimated Reading Time: __READING_TIME__ minutes


Python デコレーター は、祝福にも呪いにもなり得ます。DRYでモジュール化されたコードを書くのに役立つ一方で、特にチェーン化したり、本番システムで盲目的に適用したりすると、パフォーマンスの問題 を隠してしまう可能性があります。
この記事では、デコレーターのプロファイリング方法、使用するツール、探すべきシグナルについて説明します。これにより、Pythonアプリケーションでのデコレーターによる速度低下を回避できます。
プロファイリング デコレーターが重要な理由
単一のデコレーターは、ほんの数マイクロ秒のオーバーヘッドしか追加しない可能性があります。しかし、以下の場合:
-
複数のデコレーターをチェーンする
-
1秒間に数千回も関数を呼び出す
-
ロギング、トレース、再試行、メトリクスなどを追加する
…影響は急速に大きくなります。
データベースやCPUのせいにする前に、デコレーターを確認してください。それがサイレントボトルネックになっている可能性があります。すべてがこの記事で詳しく説明されています。
使用できるツール
1. timeit:迅速で簡単なベンチマーク
マイクロベンチマークに最適です。
import timeit
def raw():
return 42
@my_custom_decorator
def decorated():
return 42
print("Raw:", timeit.timeit(raw, number=100000))
print("Decorated:",
timeit.timeit(decorated, number=100000))
2. cProfile + Snakeviz:時間がどこで使われているかを確認する
python -m cProfile -o output.prof myscript.py
snakeviz output.prof
関数呼び出しのタイミングの視覚的な内訳が表示されます。デコレーターが高価な場合は、呼び出しツリーに表示されます。
3. line_profiler:特定の行を詳細に調べる
pipでインストールします。
pip install line_profiler
@profile
を使用して関数をマークします。
@profile
@log_execution
def process_data(): ...
次に実行します。
kernprof -l -v myscript.py
デコレートされた関数内の遅い行を特定するのに最適です。
4. Py-Spy:非侵入型のリアルタイムプロファイリング
アプリケーションを実行して、以下を使用します。
py-spy top --pid
または、フレームグラフを生成します。
py-spy record -o profile.svg --pid
デコレーターがオーバーヘッドを追加するが、コードベースに直接表示されない場合(メタプログラミングなど)に役立ちます。
注意すべき危険信号
-
I/O、ロギング、またはデータベースへのアクセスを実行するデコレーター。
-
大きなキャッシュサイズで
functools.lru_cache
を過剰に使用すること。
-
例外をサイレントに無視するtry/exceptを持つデコレーター。
-
タイムアウトが切れるのを待って実行をブロックする
@retry
または@timeout
デコレーター。
-
*args, **kwargs
を効率的に渡さないラッパー。
プロのヒント
-
ホットパス(HTTPハンドラーやタイトループなど)でのデコレーターを最小限に抑えます。
-
デコレーターの有無でテストして、実際のオーバーヘッドを確認します。
-
ローカルと本番環境で、実際のトラフィックパターンを使用してプロファイルします。