perf 实战案例集:cpu_demo 三模式深度解读
本文档是 perf-advanced 的实战姊妹篇,所有案例基于本仓库
demos/cpu-demo/main.cpp的三个场景,逐行拆解perf stat输出。 阅读前置条件:已读完 perf-advanced.md §一~§十,了解基本命令和事件含义。
推荐阅读路径(六案例形成完整叙事链)
- 案例一:模式 1 Debug 版 (-O0) — 建立"理想对照组"基准(0 切换、0 缺页、IPC 0.61)
- 案例二:模式 1 Release 版 (-O2) — O2 对照实验,cycles 跌 4.7×、IPC 涨 2.75×,但 wall-clock 不变
- 案例三:模式 2 Debug 版 (-O0) — 核心转折:模式 2 O0 的
:u数据竟与案例二 O2 一模一样!揭示:u陷阱 - 案例四:模式 2 Release 版 (-O2) — 实测验证案例三预测,发现 O2 让 CPU 利用率从 0.85 升到 0.99
- 案例五:模式 2 Debug 版 (-O0) 完整视角 — 高潮:
:u+:k完整视角实测,"真实 cycles 12.28G, 频率 4.09 GHz" - 案例六:模式 2 Release 版 (-O2) 完整视角 — 终章:O2 完整视角实测,量化结论:O0 vs O2 仅差 1.4%
案例速查
| 案例 | 模式 | 编译 | 视角 | 核心发现 |
|---|---|---|---|---|
| 一 | 1(纯计算) | -O0 | :u | IPC 0.61, cycles 12G, 理想对照组 |
| 二 | 1(纯计算) | -O2 | :u | IPC 1.68, cycles 2.5G, 优化 4.7x |
| 三 | 2(syscall) | -O0 | :u | 和模式1 O2 一模一样, :u 陷阱 |
| 四 | 2(syscall) | -O2 | :u | CPU 利用率 0.99, 频率 0.85 GHz 假象 |
| 五 | 2(syscall) | -O0 | :u+:k | 真实 cycles 12.28G, 频率 4.09 GHz |
| 六 | 2(syscall) | -O2 | :u+:k | O0 vs O2 仅差 1.4%, 验证结论 |
叙事主线回顾
bash
案例一(理想对照)──→ 案例二(O2 优化 4.7×)
│
├─ 数字对比:cycles 2.5G, IPC 1.68 ← 这是案例二的"真高效"
│
案例三(:u 陷阱)←────────┘ 数字对比:cycles 2.5G, IPC 1.69 ← 这是案例三的"假高效"
│ ↑
│ 理论推断"真实 cycles ~12G" │
│ │
├──→ 案例四(O2 :u 实测验证案例三预测)──────────────────────┘
│ │ 相同数字,天壤之别
│ │ 预测"真实 cycles ~11.5G"
│ │
├──→ 案例五(O0 :u+:k 完整视角,实测 12.28G)── 验证案例三推断
│ │
└──→ 案例六(O2 :u+:k 完整视角,实测 12.11G)── 验证案例四推断
O0 vs O2 = 1.4% 差异三大核心对比线
| 对比线 | 涉及章节 | 核心问题 | 答案 |
|---|---|---|---|
| O0 → O2(模式 1) | 案例一 vs 案例二 | 编译器能优化多少? | cycles 12G→2.5G,4.7× 加速 |
模式 1 O2 vs 模式 2 O0 :u | 案例二 vs 案例三 | 为什么数字一模一样? | 案例二是真高效,案例三是 :u 假象 |
| O0 → O2(模式 2) | 案例五 vs 案例六 | 编译器对 syscall 程序有用吗? | 仅 1.4% 差异,几乎无效 |
总结
六个案例形成完整教学闭环——从建立理想对照组的"真高效",到揭露
:u后缀的"假高效",再到用:u+:k四字段完整视角的"真相大白",最终量化证明:syscall-heavy 程序的优化重点在减少 syscall 次数,而非编译优化。