perf stat、perf record、perf top——这些命令背后是内核的
perf_event 子系统,一个统一的性能事件框架。
一、先看图
flowchart TD
USER[perf 工具] -->|perf_event_open| KERNEL[perf_event 子系统]
KERNEL --> HW[硬件 PMU<br/>cycles, cache-misses]
KERNEL --> SW[软件事件<br/>context-switches, page-faults]
KERNEL --> TP[Tracepoints<br/>sched, block, net]
KERNEL --> RB[Ring Buffer<br/>per-CPU mmap]
RB --> USER
classDef hw fill:#388bfd22,stroke:#388bfd,color:#adbac7;
classDef sw fill:#3fb95022,stroke:#3fb950,color:#adbac7;
class HW hw
class SW,TP sw
class USER,KERNEL,RB hw
二、perf_event_open
int fd = perf_event_open(&attr, pid, cpu, group_fd, flags);核心系统调用 → 创建性能事件 → 返回 fd。
attr 指定事件类型、采样周期、输出格式。
三、事件类型
3.1 硬件事件
perf stat -e cycles,instructions,cache-misses ./my_app通过 PMU(Performance Monitoring Unit)硬件计数器。
3.2 软件事件
perf stat -e context-switches,page-faults ./my_app内核在关键路径上计数。
3.3 Tracepoints
perf stat -e sched:sched_switch ./my_app
perf record -e block:block_rq_issue -a sleep 5四、Sampling vs Counting
| 模式 | 用途 | 开销 |
|---|---|---|
| counting | perf stat — 精确计数 |
极低 |
| sampling | perf record — 每 N 事件采样一次 |
低-中 |
采样:PMU 每 N 个 cycles 触发 NMI → 记录 IP(instruction pointer)→ 事后分析热点。
五、Ring Buffer
void *mmap_addr = mmap(NULL, size, PROT_READ, MAP_SHARED, perf_fd, 0);perf 通过 mmap 共享 ring buffer → 内核写、用户态读 → 零拷贝。
六、perf record / report
perf record -g -F 99 ./my_app # 采样 + 调用栈
perf report # 交互式分析
perf annotate # 源码级热点6.1 调用栈
perf record --call-graph dwarf ./my_app # DWARF unwind
perf record --call-graph fp ./my_app # frame pointer
perf record --call-graph lbr ./my_app # Last Branch Record七、Processor Trace(Intel PT)
perf record -e intel_pt// ./my_app
perf script --itrace=i0ns硬件记录完整的指令流 → 精确重放执行路径 → overhead 低于采样。
八、cgroup perf
perf stat -e cycles -G my_cgroup ./my_app限定只统计特定 cgroup 内的事件 → 容器级性能分析。
九、观察
perf list # 可用事件
perf top # 实时热点
perf stat -d ./my_app # 详细统计
perf bench sched all # 内置 benchmark
# 火焰图
perf record -g -F 99 -a sleep 10
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg十、小结
- perf_event_open 是统一的性能事件接口
- 硬件 PMU + 软件事件 + tracepoints
- counting 极低开销,sampling 低-中开销
- ring buffer mmap 零拷贝
- Intel PT 提供完整指令流记录
参考文献
kernel/events/core.cman 2 perf_event_open- Brendan Gregg, “perf Examples.” 2015
Documentation/admin-guide/perf-security.rst
工具
perf stat/record/report/top/annotateperf script- FlameGraph
文章导航
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
CPU 调度:CFS 的虚拟运行时间与 EEVDF 的虚拟截止期
从比例份额调度的论文谱系出发,对照 Linux v6.6 与 v6.12 fair.c 源码,解释 CFS 的 vruntime、EEVDF 的 lag/eligible/deadline,并用确定性模拟复现延迟与 lag 的差异。
I/O 调度:在寻道、队列深度与公平性之间取舍
从电梯算法到 blk-mq,解释 Linux I/O 调度器为何在 HDD 上排序、在共享设备上保公平、在 NVMe 上常选择 none,并用确定性模拟展示寻道距离与队列尾延迟的取舍。
用户态内存分配器:size class、线程缓存与碎片边界
从 Wilson 分配器综述到 jemalloc、gperftools tcmalloc 与 mimalloc 的源码路径,解释 size class、线程缓存、跨线程释放和 RSS 碎片;用可复现实验说明不能只凭 allocator 名字下结论。
伙伴系统与 SLUB:Linux 物理页和小对象分配的边界
以 Linux v6.6 源码和确定性模拟为准,解释伙伴系统的 split/coalesce、migratetype 反碎片策略,以及 SLUB 的 per-CPU freelist、partial list 与安全加固。