下面这份“性能分析进阶速查清单”力求覆盖 CPU-bound内存/缓存-boundI/O-bound并发 等常见瓶颈场景,兼顾 方法论工具硬件背景知识。你已经有两年基础,以下侧重高阶要点和易被忽视的细节;哪怕是老鸟,也可以作为随手翻的“备忘口袋书”。


0 · 方法论先行:三个黄金原则

  1. 先测量,后修改

    • “感觉慢” ≠ “真正热点”;每一次改动都要有 前后对比
  2. 只改关键 1%

    • 经典 80/20:程序 5 % 的代码通常耗掉 95 % 的时间。
  3. 一次改一个变量

    • 同步记录 githash、编译选项、硬件环境,避免结论漂移。

1 · 底层硬件指标速览

维度常见瓶颈典型硬件计数器 / 指标
指令执行前端卡顿、解码欠饱和idq_uops_not_delivered*, icache_misses
分支预测预测失败、间接跳转branch-misses, bp_late_mispred
流水线停顿结构冲突、寄存器重命名不足cycle_activity.stalls_total, uops_issued.any
缓存层级L1/L2/TLB/LLCL1-dcache-load-misses, L2_RQSTS.*, dTLB-load-misses
内存带宽DRAM 饱和mem_load_uops_retired.*, UNC_M_CAS_COUNT
NUMA远端访问numa_miss, numa_foreign
并发锁自旋、队列冲突sched:sched_switch, cpu-clock + off-CPU flame graph
I/Osyscalls、磁盘/网卡等待biotime, iotime, eBPF block:block_rq_issue/complete
上下文切换过度线程化context-switches, sched:sched_stat*

记忆法:指标可分 取指(Frontend) ➜ 执行(Backend) ➜ 数据(Memory) 三大链路;链路越靠后,单次代价更高。


2 · 工具矩阵(Linux / macOS / Windows)

需求CLIGUI / Web说明
系统级采样perf, perf c2c, ebpf_exporterhotspot, Speedscope基于硬件 PMC,最低噪声
微观指令级Intel vtune -collect uarch-exploration
AMD μProf
VTune GUI / Web看 IPC、port utilization
低开销火焰图perf script + FlameGraphSpeedscope最常用热点定位
锁/调度perf sched, perf lock, off-CPU fgTrace Compass定位自旋、线程睡眠
内存分配jemalloc heap prof, libc malloc_stats, heaptrackmassif-viz判定碎片、泄漏
C/C++ Sanasan, tsan, msanIDE plugin“正确性→性能” 顺序永远没错
eBPF 全家桶bcc, bpftrace, perf_event_openbpfdoor, Inspektor生产环境热点排查神器
语言特定go tool pprof, py-spy, rbspy, node --profpprof web, Speedscope把 flamegraph 养成肌肉记忆
I/O 与网络iostat, fio, tcpdump + wiresharknetdata, GrafanaI/O 就两问:带宽够吗?延迟在哪?

组合拳perf record -e cycles:u -j any,u -- <app>perf scriptstackcollapse-perf.pl | flamegraph.pl > out.svg → 浏览器打开。
养成“不出 flame 图不改代码”的习惯。


3 · 性能瓶颈识别套路

  1. CPU 利用率高?

    • → 看 IPC、分支 mispredict、port 利用率

    • → 大概率 → I/O / lock / 内存带宽 / NUMA

  2. Hotspot 在用户态还是内核态? --call-graph dwarf,fp lbr 区分

  3. L1/L2 命中率好但 L3 坏? 关注 结构体布局、false sharing

  4. TLB miss 飙高? ➜ 分页失配,检查 大页、数据局部性

  5. context-switch 爆炸? ➜ 过度线程化 / 线程争锁 / 频繁 syscalls

  6. Off-CPU 时间多? ➜ I/O wait、mutex wait、GC stop-the-world

  7. NUMA 远程访问多? ➜ 绑核 / 内存亲和;或采用 per-NUMA shard

  8. IOPS vs 带宽:SSD/网卡 性能 = 小包延迟 + _大包吞吐_二元函数

  9. 测评环境可重复:关闭睿频、关虚拟机抢占、设定 CPU 亲和、独占网卡


4 · 典型高级问题 & “老司机招”

症状快速定位常见补救
Branch miss >5 %vtune uarch view → 分支面板将 if-else 改成表驱动;手动 hint __builtin_expect
TLB miss 高perf stat -e dTLB-load-misses开 Transparent HugePages,或 madvise(MADV_HUGEPAGE)
Port 0/1 饱和vtune port analysis重排指令、SIMD 并行、调 GCC -mtune
False sharingperf c2c, vtune false-sharing按 cache line 对齐 alignas(64);每线程 padding
锁竞争perf lock record换无锁队列;或使用 MCS/QSpin
Page-fault 短暂峰值perf trace -e page-faults预分配;将大对象放 mmap 区
Off-CPU >40 %off-CPU flame graph合并系统调用;启用 io_uring / AIO

5 · 测量规范与坑

  • Warm-up:JIT / Cache / Branch predictor 预热,常用 discard 前 N 次结果

  • 固定时钟源:不同 CPU P-state / 睿频会污染基准;可用 taskset + BIOS 固定频率

  • 统计显著性:用 95 % CI;不要只看单次 run

  • 调试符号-fno-omit-frame-pointer -g 可以打开;但正式 run 替换成 minimal symbols

  • Sampling ≠ Tracing:采样开销低、丢事件;跟踪 100 % 捕获但贵。先采样,再必要时跟踪。

  • Benchmark ≠ Production:离线跑分 ≠ 真·线上;线上需要 eBPF/Perf/USDT “黑盒”采样。

  • Profile-Guided Optimization:LLVM -fprofile-{instr,generate,use},GCC -fprofile-use;收数据时输入必须贴近真实负载。


6 · 必读资料 & 社区

  • Brendan Gregg – “Systems Performance (2e)”brendangregg.com

  • Agner Fog – CPU microarchitecture & optimization PDFs

  • Intel® 64/IA-32 SDM 卷 3B 章节 “Performance-Monitoring Events”

  • LLVM “AutoFDO / BOLT” 博客、GCC AutoFDO patches

  • Talks:CPPCon “Cpp Performance Engineering” (Faisal Vali)、Google “BPF Internals”


☑️ 如何使用这张清单

  1. 遇到卡顿 → 查对照表 找对应计数器

  2. 用合适的工具 抓 1 ~ 2 分钟采样 → 出火焰图

  3. 比对 80 / 20:确定 Top N 函数 / 系统调用

  4. 改代码 / 配置再跑一次;直到收益递减明显

  5. 写总结 / 记笔记:把新坑挖进你的“直觉数据库”


愿这张“性能宝典”帮你把每一次 profiling 都练成“升级打怪”。
如果你想针对某一类瓶颈(如 NUMA 或 eBPF tracing)深入做练习,随时告诉我,我可以帮你设计一份 hands-on 练习脚本或提供示例项目。祝调优愉快!