👋
Pythonのプロファイラ cProfile でコードのボトルネックを調べる際に使うコマンド集
リファレンス:
- 構文
python -m cProfile [-o output_file] [-s sort_order] (-m module | myscript.py)
<sort_order>に指定できる値
引数 | enum 引数 | 意味 |
---|---|---|
'calls' |
SortKey.CALLS |
呼び出し回数 |
'cumulative' |
SortKey.CUMULATIVE |
累積時間 |
'cumtime' |
— | 累積時間 |
'file' |
— | ファイル名 |
'filename' |
SortKey.FILENAME |
ファイル名 |
'module' |
— | ファイル名 |
'ncalls' |
— | 呼び出し回数 |
'pcalls' |
SortKey.PCALLS |
プリミティブ呼び出し回数 |
'line' |
SortKey.LINE |
行番号 |
'name' |
SortKey.NAME |
関数名 |
'nfl' |
SortKey.NFL |
名前/ファイル/行番号 |
'stdname' |
SortKey.STDNAME |
標準名 |
'time' |
SortKey.TIME |
内部時間 |
'tottime' |
— | 内部時間 |
- 累積時間順に表示
python -m cProfile -s cumtime main.py
- 呼び出し回数順に表示(どの関数が何回呼ばれてるか確認)
python -m cProfile -s calls main.py
- ファイル名順でソート(特定ファイルのプロファイリング結果を俯瞰)
python -m cProfile -s filename main.py
- 関数名順でソート(アルファベット順でざっと見るときに)
python -m cProfile -s name main.py
- プリミティブ呼び出し回数順でソート(再帰やラッパー除外して純粋な呼び出し回数把握)
python -m cProfile -s pcalls main.py
- 結果をファイルに保存する
python -m cProfile -o out.prof main.py
- モジュールを直接プロファイリング(スクリプトじゃなくモジュールを測りたいとき)
python -m cProfile -s tottime -m your_module_name
-
pstats
を使って分析
# 先頭20件を表示する
python - <<EOF
import pstats
ps = pstats.Stats('out.prof')
ps.strip_dirs().sort_stats('time').print_stats(20)
EOF
# 主要関数だけピンポイントで見る(正規表現でフィルタリング)
python -m cProfile -o out.prof main.py
python - <<EOF
import pstats
ps = pstats.Stats('out.prof')
ps.strip_dirs().sort_stats('cumtime').print_stats('<your_function>')
EOF
# リストに挙げた関数だけを、呼び出し回数順に表示する
python - <<'EOF'
import pstats
ps = pstats.Stats('out.prof')
ps.strip_dirs() \
.sort_stats('calls') \
.print_stats(('funcA', 'funcB', 'Class.method'))
EOF
# Callers: 関数 my_module.my_func をどこから呼んでいるかを調べる
python - <<'EOF'
import pstats
ps = pstats.Stats('out.prof')
ps.strip_dirs() \
.sort_stats('time') \
.print_callers('my_module.my_func')
EOF
# Callees: 関数 my_module.my_func の内部でさらにどの関数を呼んでいるか調べる
python - <<'EOF'
import pstats
ps = pstats.Stats('out.prof')
ps.strip_dirs() \
.sort_stats('time') \
.print_callees('my_module.my_func')
EOF
# 再帰呼び出しの除外
python - <<'EOF'
import pstats
ps = pstats.Stats('out.prof').strip_dirs()
ps.sort_stats('cumtime', 'ncalls')
ps.print_stats(50)
EOF
- プロファイルをCSV/TSV 形式でエクスポートする
python - <<'EOF' > stats.tsv
import pstats, csv
ps = pstats.Stats('out.prof').strip_dirs().sort_stats('cumulative')
writer = csv.writer(open('stats.tsv','w',newline=''), delimiter='\t')
writer.writerow(['func','ncalls','tottime','cumtime'])
for func, (nc, pn, tt, ct, callers) in ps.stats.items():
writer.writerow([f"{func[1]}:{func[2]}", nc, f"{tt:.6f}", f"{ct:.6f}"])
EOF
- ワンライナー引数対応スクリプト
python - <<'EOF'
import sys, pstats
key = sys.argv[1] if len(sys.argv) > 1 else 'cumtime'
n = int(sys.argv[2]) if len(sys.argv) > 2 else 20
ps = pstats.Stats('out.prof').strip_dirs().sort_stats(key)
ps.print_stats(n)
EOF cumtime 30
-
snakeviz
を使ってブラウザUIでプロファイリング結果を可視化する
# poetry add --dev snakeviz # 標準モジュールではないので追加が必要
snakeviz out.prof
以上です。
Discussion