💻
詳解 システム・パフォーマンス - 第6章:CPU分析
CPU使用率・スケジューラ・CPI・フレームグラフ・キャッシュミス分析の完全ガイド。perfコマンドを使った実践的なCPUボトルネック調査手順。
CPU の性能指標
| 指標 | 意味 | 確認コマンド |
|---|---|---|
| 使用率(%) | CPUがビジー状態の割合 | mpstat, top |
| runキュー長 | 実行待ちプロセス数(> コア数で飽和) | vmstat r列 |
| CPI | Cycles Per Instruction(低いほど効率的) | perf stat |
| コンテキストスイッチ | CPU切り替え回数(多すぎると問題) | vmstat cs列 |
| キャッシュミス率 | L1/L2/LLC ミスの割合 | perf stat -d |
CPU 分析のフロー
1. 全体の CPU 使用率を確認
vmstat 1 / mpstat -P ALL 1
↓
2. プロセス別に絞り込む
pidstat 1 / top
↓
3. プロファイリングで「どの関数が重いか」を特定
perf record -F 99 -g -p <PID> sleep 30
perf report
↓
4. フレームグラフで視覚化
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg
↓
5. CPU ハードウェアカウンタで効率を評価
perf stat -d -p <PID>
基本コマンド
全体の CPU 状況
# 仮想メモリ統計(CPU の大まかな状況)
vmstat 1 5
# us: ユーザーCPU / sy: システムCPU
# id: アイドル / wa: I/O待ちアイドル
# r: runキュー(コア数超えたら飽和)
# コア別の CPU 使用率(どのコアが偏っているか)
mpstat -P ALL 1 5
# %usr + %sys: 実質的な使用率
# %iowait: ディスクI/O待ちで CPU がアイドル → ディスクボトルネック
# %soft: ソフト割り込み(NIC処理が多いと高くなる)
# プロセス別の CPU 使用率(犯人特定)
pidstat 1 5
# %CPU 列を時系列で追う
perf によるプロファイリング
# システム全体の CPU サンプリング(99Hz、30秒)
sudo perf record -F 99 -a -g sleep 30
# 特定プロセスのプロファイリング
perf record -F 99 -g -p <PID> sleep 30
# 結果の確認
perf report
# → キー操作:Enter で展開、a でソースアノテーション
# CPU 使用率の高い関数 TOP 10(テキスト出力)
perf report --stdio --sort=symbol | head -30
フレームグラフ(Flame Graph)
CPU プロファイルを視覚的に表現する最強のツール。幅の広い箱 = CPU消費が多い関数。
生成手順
# 1. FlameGraph ツールをクローン
git clone https://github.com/brendangregg/FlameGraph
# 2. perf でスタックを収集(60秒)
sudo perf record -F 99 -a -g -- sleep 60
# 3. スクリプト展開
perf script > out.perf
# 4. スタック折り畳み
./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
# 5. SVG 生成
./FlameGraph/flamegraph.pl out.folded > flame.svg
open flame.svg # ブラウザで開く
# 2〜5を一行で
perf script | ./FlameGraph/stackcollapse-perf.pl | \
./FlameGraph/flamegraph.pl --colors=hot --title="CPU Profile" > flame.svg
フレームグラフの読み方
[main] ← エントリーポイント(下)
[http_handler]
[db_query] [json_serialize]
[pg_exec] [marshal] [strconv]
[socket_write]
- 下から上に呼び出し関係(下が呼び出し元)
- 幅が広いほど CPU を多く使っている
- **一番上(葉)**が実際に CPU 時間を消費している関数
- 細長い塔:深い再帰や深いコールチェーン
- 広くて浅い:特定の関数が直接 CPU を使い切っている
CPU ハードウェアカウンタ
CPU 内部の実行効率を測定する。チューニング効果の評価に使う。
# 主要カウンタの一括取得
perf stat -d -p <PID> sleep 10
# 出力例:
# 10,000,000,000 cycles # 実行クロック数
# 5,000,000,000 instructions # 命令数
# 0.50 insn per cycle # IPC(1以下は非効率)
# 100,000,000 cache-references
# 50,000,000 cache-misses # 50%ミス率は非常に高い
# 500,000,000 branches
# 5,000,000 branch-misses # 1%の分岐予測ミス
# 特定カウンタの指定
perf stat -e cycles,instructions,cache-references,cache-misses,\
L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses \
-p <PID> sleep 10
CPI(Cycles Per Instruction)の解釈
CPI = cycles / instructions
CPI < 1.0 → 効率的(スーパースカラで並列実行)
CPI 1〜2 → 通常の範囲
CPI 2〜4 → やや非効率(キャッシュミスや分岐予測ミスが多い可能性)
CPI > 4 → 非効率(メモリアクセス待ちやストールが多い)
CPU 関連の問題パターンと対処
① CPU 使用率が高い
# 犯人プロセスを特定
pidstat 1 10
# どの関数が重いか
perf record -F 99 -g -p <PID> sleep 30
perf report --stdio | head -30
# フレームグラフで全体像を把握
perf script | ./FlameGraph/stackcollapse-perf.pl | ./FlameGraph/flamegraph.pl > flame.svg
② 特定コアだけ高い(偏り)
mpstat -P ALL 1
# 1コアだけ 100% = シングルスレッドのボトルネック
# マルチスレッド化が必要、または IRQ アフィニティの問題
# NIC の割り込みが1コアに集中していないか
cat /proc/interrupts | grep eth
③ iowait が高い(I/O待ちでCPUがアイドル)
# これは CPU 問題ではなくディスク問題
iostat -xz 1
# → ch09(ディスク分析)へ
④ コンテキストスイッチが多い
vmstat 1 5 # cs 列
pidstat -w 1 5 # cswch/s(自発的)/ nvcswch/s(非自発的)
# 非自発的が多い → CPU が足りずに奪われている
# 自発的が多い → I/O 待ちやロック待ちが多い
⑤ steal time が高い(仮想化環境)
vmstat 1 5 # st 列
# st > 5〜10% → ホストの CPU 過負荷(ノイジーネイバー)
# → ch11(クラウド)へ - 1. 📊詳解 システム・パフォーマンス - 概要・読み方ガイド
- 2. 🔍詳解 システム・パフォーマンス - 第16章:ケーススタディ
- 3. 🧭詳解 システム・パフォーマンス - 第2章:メソドロジ
- 4. 🐧詳解 システム・パフォーマンス - 第3章:オペレーティングシステム
- 5. 🔭詳解 システム・パフォーマンス - 第4章:可観測性ツール
- 6. ⚙️詳解 システム・パフォーマンス - 第5章:アプリケーション
- 7. 💻詳解 システム・パフォーマンス - 第6章:CPU分析
- 8. 🧠詳解 システム・パフォーマンス - 第7章:メモリ分析
- 9. 📁詳解 システム・パフォーマンス - 第8章:ファイルシステム分析
- 10. 💾詳解 システム・パフォーマンス - 第9章:ディスク分析
- 11. 🌐詳解 システム・パフォーマンス - 第10章:ネットワーク分析
- 12. ☁️詳解 システム・パフォーマンス - 第11章:クラウドコンピューティング
- 13. 📏詳解 システム・パフォーマンス - 第12章:ベンチマーキング
- 14. 🔥詳解 システム・パフォーマンス - 第13章:perf
- 15. 🔬詳解 システム・パフォーマンス - 第14章:Ftrace
- 16. ⚡詳解 システム・パフォーマンス - 第15章:BPF/eBPF
出典: 詳解 システム・パフォーマンス 第2版 Brendan Gregg著