mcpField
P
python-performance-optimization

python-performance-optimization

github.com/acaprino開発940 回インストール1 日前に更新
リポジトリ

python-performance-optimization について

Python プログラムの CPU、メモリ、I/O をプロファイルして最適化するスキルです。ボトルネックの測定から、実装、データ構造、キャッシュ、並列化の改善策選択まで開発者を支援します。

主な機能

  1. 01CPU、メモリ、行単位のプロファイリング
  2. 02実行時間とリソース指標
  3. 03アルゴリズムとデータ構造の指針
  4. 04キャッシュと並列化の戦略
  5. 05データベースとメモリの最適化

活用シーン

  1. 01遅い Python 関数の原因調査
  2. 02データ処理のメモリ使用量削減
  3. 03並行処理方式の比較
  4. 04最適化前後の変化を測定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/acaprino/daodan --skill python-performance-optimization

インストール後、Claude Code で/python-performance-optimizationを入力して読み込まれたか確認します。

同梱ファイルreferences/optimization-patterns.mdSKILL.toml

詳細

Python のパフォーマンス最適化

パフォーマンスを向上させるために、Python コードのプロファイリング、分析、最適化を行います。CPU プロファイリング、メモリ最適化、実装のベストプラクティスを扱います。

呼び出すタイミング

  • Python コードの実行が遅いという報告や、実行速度を上げる依頼があった場合
  • Python アプリケーションのプロファイリングやベンチマークを行う場合
  • CPU 時間、メモリ消費量、I/O 待ち時間を削減する場合
  • データベースクエリやデータ処理パイプラインを最適化する場合
  • メモリリークや過剰なメモリ使用をデバッグする場合
  • 並列化の方法(スレッド、マルチプロセス、非同期)の選択を行う場合
  • アルゴリズムレベルと実装レベルの改善を評価する場合

主な概念

プロファイリングの種類
  • CPU プロファイリング:時間のかかる関数を特定します(cProfile、py-spy)
  • メモリプロファイリング:メモリ割り当てやリークを追跡します(tracemalloc、memory_profiler)
  • 行単位プロファイリング:行ごとの粒度でプロファイリングします(line_profiler)
  • 呼び出しグラフ:関数の呼び出し関係を可視化します
パフォーマンス指標
  • 実行時間:処理にかかる時間
  • メモリ使用量:ピーク時および平均のメモリ消費量
  • CPU 使用率:プロセッサの使用状況
  • I/O 待ち時間:I/O 処理に費やす時間
最適化戦略
  • アルゴリズム:より優れたアルゴリズムやデータ構造を使用します
  • 実装:より効率的なコードパターンを使用します
  • 並列化:マルチスレッド/マルチプロセスを使用します
  • キャッシュ:重複する計算を避けます
  • ネイティブ拡張:クリティカルパスには C/Rust を使用します

クイックスタート

import time
import timeit

# Simple timing
start = time.time()
result = sum(range(1000000))
print(f"Execution time: {time.time() - start:.4f} seconds")

# Accurate benchmarking with timeit
execution_time = timeit.timeit("sum(range(1000000))", number=100)
print(f"Average time: {execution_time/100:.6f} seconds")

プロファイリングツールの概要

cProfile - CPU プロファイリング
python -m cProfile -o output.prof script.py
python -m pstats output.prof
line_profiler - 行単位のプロファイリング
uv add --dev line-profiler    # or: uv tool install line-profiler
kernprof -l -v script.py
memory_profiler - メモリ使用量
uv add --dev memory-profiler
python -m memory_profiler script.py
py-spy - 本番環境でのプロファイリング
uv tool install py-spy
py-spy record -o profile.svg -- python script.py
py-spy top --pid 12345

主な最適化パターン

データ構造の選択
  • 検索には Dict/Set:リスト検索の O(n) に対して O(1)
  • 大規模データセットにはジェネレーター:リスト全体を保持する代わりにメモリ使用量を一定に保ちます
  • クラスで __slots__ を使用:インスタンスごとのメモリ使用量を削減します
コードレベルの最適化
  • ループよりリスト内包表記を使います(C による実装のため高速です)
  • += による連結より str.join() を使います
  • 高頻度ループではグローバルアクセスよりローカル変数を使います
  • 密なループでは単純な処理をインライン化します
  • 組み込み関数を使います(C で実装されています)
キャッシュ
  • 計算コストの高い純粋関数には functools.lru_cache を使います
  • ガベージコレクションに適したキャッシュには weakref.WeakValueDictionary を使います
並列化
  • multiprocessing:CPU バウンドのタスクに使用し、真の並列処理を実現します
  • threading:共有メモリを使う I/O バウンドのタスクに使用します
  • asyncio:多数の同時処理を伴う I/O バウンドのタスクに使用します
メモリの最適化
  • メモリリークの検出には tracemalloc を使います(スナップショットを比較します)
  • ファイル/ストリーム処理ではリストよりイテレーターを使います
  • ガベージコレクションを可能にするには weakref キャッシュを使います
データベースの最適化
  • executemany() と単一のコミットでバッチ処理します
  • 頻繁にクエリされる列にインデックスを付けます
  • 必要な列だけを選択します(SELECT * は避けます)
  • 分析には EXPLAIN QUERY PLAN を使います

ベンチマーク

from functools import wraps
import time

def benchmark(func):
    """Decorator to benchmark function execution."""
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__} took {elapsed:.6f} seconds")
        return result
    return wrapper

pytest ベースのベンチマークには、pip install pytest-benchmark を実行します。

ベストプラクティス

  1. 最適化の前にプロファイリングする - 実際のボトルネックを見つけるために測定します
  2. 頻繁に実行される処理に注力する - 最も頻繁に実行されるコードを最適化します
  3. 適切なデータ構造を使う - 検索には dict、要素の有無の確認には set を使います
  4. 時期尚早な最適化を避ける - まず明瞭さを優先し、その後に最適化します
  5. 組み込み関数を使う - C で実装されています
  6. 計算コストの高い処理をキャッシュする - lru_cache を使います
  7. I/O 処理をバッチ化する - システムコールを減らします
  8. 大規模なデータセットにはジェネレーターを使います
  9. 数値演算には NumPy を検討します
  10. 本番コードをプロファイリングする - 稼働中のシステムには py-spy を使います

よくある落とし穴

  • プロファイリングをせずに最適化する
  • グローバル変数を不必要に使う
  • 適切なデータ構造を使わない
  • 不要なデータのコピーを作成する
  • データベースに接続プーリングを使わない
  • アルゴリズムの計算量を考慮しない
  • まれにしか実行されないコードパスを過剰に最適化する
  • メモリ使用量を考慮しない

パフォーマンスチェックリスト

  • コードをプロファイリングしてボトルネックを特定しました
  • 適切なデータ構造を使用しました
  • 効果が見込める箇所にキャッシュを実装しました
  • データベースクエリを最適化しました
  • 大規模なデータセットにはジェネレーターを使用しました
  • CPU バウンドのタスクにはマルチプロセスを検討しました
  • I/O バウンドのタスクには非同期 I/O を使用しました
  • ホットループ内の関数呼び出しのオーバーヘッドを最小限に抑えました
  • メモリーリークを確認しました
  • 最適化の前後でベンチマークを実施しました

参考資料

  • references/optimization-patterns.md - すべてのプロファイリングツール、最適化パターン(リスト内包表記、ジェネレーター、文字列連結、辞書検索、ローカル変数、関数呼び出しのオーバーヘッド)の詳細なコード例、高度な最適化(NumPy、lru_cache、slots、マルチプロセス、非同期 I/O)、データベースの最適化、メモリーリークの検出、ベンチマークツール

リソース

  • cProfile:組み込みの CPU プロファイラー
  • memory_profiler:メモリー使用量のプロファイリング
  • line_profiler:行単位のプロファイリング
  • py-spy:本番環境向けサンプリングプロファイラー
  • NumPy:高性能な数値計算
  • Cython:Python を C にコンパイル
  • PyPy:JIT を備えた代替 Python インタープリター

コメント