python-performance-optimization について
Python 開発者向けに、計測でボトルネックを特定してから実行時間やメモリ使用量を改善する方法を案内するスキルです。アルゴリズムから高速化手法まで扱います。
主な機能
- 01最適化前のプロファイリング
- 02アルゴリズムとデータ構造の改善
- 03ジェネレーターによるメモリ削減
- 04反復処理のキャッシュ
- 05NumPy、Numba、マルチプロセスの活用
活用シーン
- 01本番コードの遅さの調査
- 02データパイプラインのメモリ削減
- 03API応答やバッチ処理の短縮
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ nickcrew/ claude-cortex --skill python-performance-optimizationインストール後、Claude Code で/python-performance-optimizationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/acceleration.mdalgorithms.mdmemory.mdprofiling.mdstring-io.md詳細
Python のパフォーマンス最適化
体系的な分析、アルゴリズムの改善、効率的なデータ構造、アクセラレーション技術を通じて、Python アプリケーションのプロファイリング、最適化、高速化を行うための専門的なガイダンスです。
このスキルを使用するタイミング
- コードの実行速度が本番環境の要件を満たさない場合
- CPU 使用率が高い、またはメモリ消費量に問題がある場合
- API の応答時間やバッチ処理の所要時間を短縮する必要がある場合
- 負荷がかかるとアプリケーションをスケールできない場合
- データ処理パイプラインや科学技術計算を最適化する場合
- 効率化によってクラウドインフラストラクチャのコストを削減する場合
- パフォーマンスのボトルネックを測定した後、プロファイルに基づいて最適化する場合
主な概念
黄金律:まずプロファイリングを行わずに最適化してはいけません。実行時間の 80%はコードの 20%で費やされます。
最適化の優先順位(優先度順):
- アルゴリズムの計算量 - O(n²) → O(n log n) で指数関数的な改善が得られます
- データ構造の選択 - 検索に List ではなく Set を使う(10,000 倍高速)
- 言語機能 - 内包表記、組み込み関数、ジェネレーター
- キャッシュ - 繰り返される計算にメモ化を使う
- コンパイル済み拡張機能 - ホットパスに NumPy、Numba、Cython を使う
- 並列処理 - CPU バウンドの処理にマルチプロセスを使う
重要な原則:アルゴリズムの改善は、マイクロ最適化よりも常に効果があります。
クイックリファレンス
特定の最適化領域について詳しく知るには、該当するガイドを読み込んでください。
| タスク | リファレンスを読み込む |
|---|---|
| コードをプロファイリングしてボトルネックを特定する | skills/python-performance-optimization/references/profiling.md |
| アルゴリズムとデータ構造の最適化 | skills/python-performance-optimization/references/algorithms.md |
| メモリの最適化とジェネレーター | skills/python-performance-optimization/references/memory.md |
| 文字列の連結とファイル I/O | skills/python-performance-optimization/references/string-io.md |
| NumPy、Numba、Cython、マルチプロセス | skills/python-performance-optimization/references/acceleration.md |
最適化のワークフロー
フェーズ 1:測定
- cProfile でプロファイリングする - 遅い関数を特定します
- ホットパスを行単位でプロファイリングする - 遅い行を正確に特定します
- メモリをプロファイリングする - メモリのボトルネックを確認します
- ベースラインをベンチマークする - 現在のパフォーマンスを記録します
フェーズ 2:分析
- アルゴリズムの計算量を確認する - O(n²) 以上になっていませんか?
- データ構造を評価する - 検索にリストを使っていませんか?
- 繰り返される処理を特定する - 結果をキャッシュできますか?
- I/O のボトルネックを見つける - データベースクエリやファイル操作を確認します
フェーズ 3:最適化
- まずアルゴリズムを改善する - 最も大きな効果が得られます
- 適切なデータ構造を使う - O(1) の検索には Set/dict を使います
- キャッシュを適用する - 高コストな関数には
@lru_cacheを使います - ジェネレーターを使う - 大規模なデータセットに適しています
- NumPy/Numba を活用する - 数値計算のコードに適しています
- 並列化する - CPU バウンドのタスクにはマルチプロセスを使います
フェーズ 4:検証
- 再度プロファイリングする - 改善を検証します
- ベンチマークする - 高速化の度合いを定量的に測定します
- 正しさをテストする - 最適化によって機能が壊れていないことを確認します
- 文書化する - 最適化が必要だった理由を説明します
よく使われる最適化パターン
パターン 1:検索に使う List を Set に置き換える
# Slow: O(n) lookup
if item in large_list: # Bad
# Fast: O(1) lookup
if item in large_set: # Good
パターン 2:内包表記を使う
# Slower
result = []
for i in range(n):
result.append(i * 2)
# Faster (35% speedup)
result = [i * 2 for i in range(n)]
パターン 3:高コストな計算をキャッシュする
from functools import lru_cache
@lru_cache(maxsize=None)
def expensive_function(n):
# Result cached automatically
return complex_calculation(n)
パターン 4:大規模なデータにジェネレーターを使う
# Memory inefficient
def read_file(path):
return [line for line in open(path)] # Loads entire file
# Memory efficient
def read_file(path):
for line in open(path): # Streams line by line
yield line.strip()
パターン 5:NumPy でベクトル化する
# Pure Python: ~500ms
result = sum(i**2 for i in range(1000000))
# NumPy: ~5ms (100x faster)
import numpy as np
result = np.sum(np.arange(1000000)**2)
避けるべきよくある間違い
- プロファイリング前に最適化する - 間違ったコードを最適化してしまいます
- メンバーシップテストにリストを使う - 代わりに Set/dict を使います
- ループ内で文字列を連結する -
“”.join()またはStringIOを使います - ファイル全体をメモリに読み込む - ジェネレーターを使います
- N+1 データベースクエリ - JOIN またはバッチクエリを使います
- 組み込み関数を無視する - 組み込み関数は C で最適化されており、高速です
- 時期尚早な最適化 - まずアルゴリズムの改善に注力します
- ベンチマークを行わない - 改善を必ず定量的に測定します
判断フロー
ここから始めます:cProfile でプロファイリングし、ボトルネックを見つけます
ホットパスはアルゴリズムですか?
- はい → 計算量を確認し、アルゴリズムを改善して、より適切なデータ構造を使用します
- いいえ → 続行します
ホットパスは計算ですか?
- 数値ループ → NumPy または Numba
- CPU バウンド → マルチプロセッシング
- すでに十分高速 → 完了です
ホットパスはメモリですか?
- 大規模なデータ → ジェネレーター、ストリーミング
- 大量のオブジェクト →
__slots__、オブジェクトプーリング - キャッシュが必要 →
@lru_cacheまたはカスタムキャッシュ
ホットパスは I/O ですか?
- データベース → クエリのバッチ処理、インデックス、コネクションプーリング
- ファイル → バッファリング、ストリーミング
- ネットワーク → 非同期 I/O、リクエストのバッチ処理
ベストプラクティス
- 最適化の前にプロファイリングする - 測定して実際のボトルネックを見つけます
- まずアルゴリズムを最適化する - O(n²) → O(n) はマイクロ最適化より効果的です
- 適切なデータ構造を使用する - 検索にはリストではなく、Set/dict を使用します
- 組み込み機能を活用する - C で実装された組み込み機能は純粋な Python より高速です
- 時期尚早な最適化を避ける - プロファイリングで特定したホットパスを最適化します
- 大規模なデータにはジェネレーターを使用する - 遅延評価でメモリ使用量を削減します
- 処理をバッチ化する - システムコールやネットワークリクエストのオーバーヘッドを最小限に抑えます
- コストの高い計算をキャッシュする -
@lru_cacheまたはカスタムキャッシュを使用します - NumPy/Numba を検討する - 数値コードにはベクトル化と JIT を使用します
- CPU バウンドの処理を並列化する - マルチプロセッシングを使用して、すべてのコアを活用します
リソース
- Python のパフォーマンス: https://wiki.python.org/moin/PythonSpeed
- cProfile: https://docs.python.org/3/library/profile.html
- NumPy: https://numpy.org/doc/stable/user/absolute_beginners.html
- Numba: https://numba.pydata.org/
- Cython: https://cython.readthedocs.io/
- High Performance Python(Gorelick と Ozsvald による書籍)
コメント
Markdown 対応