linux性能分析工具——perf

Make tiny progress every day. ——yangnanbei

参考资料:

  1. https://perf.wiki.kernel.org
  2. man手册
  3. https://www.youtube.com/playlist?list=PLx-WakpEO8zFQGRrB4xYAuWjHKqVWlwaD
  4. Perf更详细的介绍 – 陈小欧 – 20210512 – PLCT实验室_哔哩哔哩_bilibili
  5. https://zhuanlan.zhihu.com/p/147875569

前言

还记得我第一份工作刚入职开发的第一个接口,在网络栈入口加了一个对事件A的处理。那时候虚线的+1强调要注意这一块的性能,还反复修改了几次。那时我问为什么?他只说这是处理链路必经的流程,所以性能要着重考虑。

实际上,由“必经链路”推出“性能处理重要”难免有局部过度优化的嫌疑。性能问题也遵循20/80原则,即80%的性能问题是由20%的性能不友好代码造成的,如何定位性能不友好的代码是性能分析中很重要的课题。

perf工具正是我们定位性能问题的好帮手,perf 是 Linux 系统性能分析和优化的基石工具。它最大的价值在于提供了一个高效、低开销、深度集成的途径,让开发者能够跨越硬件、内核、用户应用的界限,精确地定位性能瓶颈的根源(精确到函数、源码行甚至指令)。无论是进行微观的代码优化,还是诊断宏观的系统级问题,perf 都是不可或缺的利器。掌握 perf 是 Linux 开发者和性能工程师的核心技能之一。

让我们请大D老师介绍一下perf吧:

使用 perf 的背景/原因:

  1. 内核集成: 作为内核的一部分(通过 perf_event_open 系统调用),perf 具有极高的权限和低开销,能访问底层硬件计数器和内核内部状态。
  2. 替代传统工具: 它整合并超越了之前分散的工具如 oprofileptrace 的部分功能,提供了更统一、高效的界面。
  3. 硬件支持: 直接利用 CPU(Intel 的 PMU, AMD 的 IBS, ARM 的 PMU 等)提供的硬件性能计数器,精确测量如 CPU 周期、指令数、缓存命中/失效、分支预测错误等底层硬件事件。
  4. 软件抽象: 除了硬件事件,还能访问软件事件(如页面错误、上下文切换、调度事件)和跟踪点(内核中预定义的静态探测点)以及动态探针(kprobes, uprobes)。
  5. 解决性能痛点: 在复杂的现代系统(多核、超线程、NUMA、复杂软件栈)中定位性能瓶颈(CPU、内存、I/O、锁争用等)非常困难,需要深入且全面的工具。

使用 perf 的主要好处:

  1. 功能全面(One Tool to Rule Them All):
    1. CPU 分析: 分析热点函数、指令级开销、CPI 等。
    2. 缓存分析: 定位缓存未命中(L1/L2/L3 dTLB/iTLB)的代码位置。
    3. 内存分析: 分析内存访问模式、带宽、缺页异常。
    4. I/O 分析: 跟踪块设备 I/O、同步开销(虽然不如 bpftrace/eBPF 灵活,但基础支持)。
    5. 调度分析: 分析上下文切换、CPU 迁移、负载均衡问题、调度延迟。
    6. 锁分析: 检测锁争用、自旋锁持有时间。
    7. 调用链分析: 记录并可视化函数调用关系(stack traces)。
    8. 跟踪: 记录内核和用户空间特定事件的发生序列(perf record -e tracepoint)。
    9. 静态/动态探针: 在函数入口/出口或任意指令处插入探测点收集数据。
  2. 低开销:
    1. 利用硬件计数器进行采样,开销通常很低(尤其是采样模式),适合生产环境使用。
    2. 内核级实现避免了频繁的用户/内核态切换。
  3. 深度洞察(从硬件到应用):
    1. 跨越层级: 能将硬件事件(如缓存未命中)直接关联到特定的内核函数甚至用户空间的代码行或指令。这是其最强大的优势之一。
    2. 精确到指令/源码行: 结合调试信息(-g),可以将性能事件定位到源代码行或汇编指令。
  4. 生产环境友好:
    1. 低开销使其能够在真实负载下运行,捕获实际生产环境中的问题,而不仅仅是在测试环境中。
    2. 不需要修改或重启应用程序。
  5. 丰富的报告和可视化:
    1. perf report: 交互式查看采样结果,按函数、源码行、指令排序热点。
    2. perf annotate: 将汇编指令或源码行与事件计数关联显示。
    3. perf script: 导出原始数据供自定义脚本分析(如生成火焰图)。
    4. 火焰图: perf 数据是生成 CPU、内存火焰图(FlameGraph)的标准输入来源,提供直观的性能瓶颈可视化。
  6. 强大的统计功能:
    1. perf stat: 快速运行一个命令并汇总整个执行过程中的各种硬件/软件事件计数,提供宏观性能指标(如 IPC – Instructions Per Cycle)。
  7. 活跃的社区和生态系统:
    1. 作为 Linux 内核的一部分,持续更新,支持新硬件和新特性。
    2. 有大量的教程、博客文章、案例分析和工具(如火焰图生成脚本)围绕它展开。
  8. 相对易用性(相比更底层的工具):
    1. 提供了相对高级的命令行接口,抽象了底层硬件的复杂性。
    2. 常用场景(如 CPU 热点分析)的命令(perf record, perf report)学习曲线相对平缓。

命令

主包在wsl环境实验,部分硬件计数无法采集。

perf list

显示当下环境perf支持的trace point

perf list
List of pre-defined events (to be used in -e or -M):

  alignment-faults                                   [Software event]
  bpf-output                                         [Software event]
  cgroup-switches                                    [Software event]
  context-switches OR cs                             [Software event]
  cpu-clock                                          [Software event]
  cpu-migrations OR migrations                       [Software event]
  dummy                                              [Software event]
  emulation-faults                                   [Software event]
  major-faults                                       [Software event]
  minor-faults                                       [Software event]
  page-faults OR faults                              [Software event]
  task-clock                                         [Software event]

tool:
  duration_time
  user_time
  system_time
  msr/pperf/                                         [Kernel PMU event]
  msr/smi/                                           [Kernel PMU event]
  msr/tsc/                                           [Kernel PMU event]
  rNNN                                               [Raw hardware event descriptor]
  ...

统计分类

perf list | awk -F: ‘/Tracepoint event/ { lib[$1]++ } END {

for (l in lib) {printf ” %-16.16s %d\n”, l, lib[l] } } ‘ | sort | column

  • Syscalls: syscall enter and exit
  • Ext4: file system events
  • Block: block device event
  • Sock: socket event
  • Sched: cpu schedule
  • Kmem: kernel memery event

perf stat

统计事件计数

perf stat -h

 usage: perf stat [<options>] [<command>]

    -e, --event <event>   event selector. use 'perf list' to list available events
    -i, --no-inherit      child tasks do not inherit counters
    -p, --pid <n>         stat events on existing process id
    -t, --tid <n>         stat events on existing thread id
    -a, --all-cpus        system-wide collection from all CPUs
    -c, --scale           scale/normalize counters
    -v, --verbose         be more verbose (show counter open errors, etc)
    -r, --repeat <n>      repeat command and print average + stddev (max: 100)
    -n, --null            null run - dont start any counters
    -B, --big-num         print large numbers with thousands' separators

我们可以选择想要统计的事件类型

perf stat -e cycles dd if=/dev/zero of=/dev/null count=100000

  • 默认统计用户态和内核态

perf stat -e cycles:u dd if=/dev/zero of=/dev/null count=100000

  • 只统计用户态

perf stat -e cycles:uk dd if=/dev/zero of=/dev/null count=100000

  • 显示指定统计 用户态+内核态

每1s统计一次

perf stat -a -I 1000 — sleep 3

  • -I 1000:每1000ms统计一次

统计特定事件

perf stat -e cycles,instructions,cache-misses […]

我们可以统计某个事件,或者特定事件

可以重复运行多次

perf stat -e cache-misses -r 5 sleep 1

可以用通配符匹配特定事件

perf stat -e ‘syscalls:sys_enter_*’ -C 1 — sleep 1

匹配后过滤 次数不为0的事件

perf stat -e ‘syscalls:sys_enter_*’ -C 1 — sleep 1 2>&1 | awk ‘$1 != 0’

统计特定核

高性能进程的数据面线程往往是绑定且独占特定的cpu核,我们可以统计某个/某些核的特定事件技术

如:

perf stat -B -e cycles:u,instructions:u -a -C 0,2-3 sleep 5

PMU raw counter

还可以统计一些CPU性能监控(PMU, Performance Monitoring Unit)事件

perf stat -e r003c -a sleep 1

如 003C: UnHalted Core Cycles

perf trace

跟踪事件

跟踪某个核上的锁事件

perf trace -e futex -C 2

perf record

采样事件以供分析

对于事件可分析的数据比起stat更详细,可以跟踪堆栈

perf record -e block:block_rq_complete -a sleep 2

perf script

展示record的信息

perf record -e block:block_rq_complete -a sleep 2

采样结束后使用perf script

以上每列分别代表

command, pid, cpuid, timestamp, event name, storage device major and minor number, type of I/O, block command details, storage device offset + sizeof I/O, errors.

以上是通过经验对照得来的,我们可以使用-F参数来指定想要display的列(man perf-script)。

-F, –fields

Comma separated list of fields to print. Options are: comm, tid, pid, time, cpu, event, trace, ip, sym,

dso, dsoff, addr, symoff, srcline, period, iregs, uregs, brstack, brstacksym, flags, bpf-output,

brstackinsn, brstackinsnlen, brstackoff, callindent, insn, insnlen, synth, phys_addr, metric, misc,

srccode, ipc, data_page_size, code_page_size, ins_lat, machine_pid, vcpu, cgroup, retire_lat. Field list

can be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies.

e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace

perf top

实时动态跟踪事件

perf report

整理报告,将记录的报告整理成进程,事件,堆栈等

perf bench

跑测试

perf lock

跟踪锁事件

Flame Graph

我们可以将perf record记录的数据以火焰图的形式输出,更加的直观,有利于人类的阅读

https://zhuanlan.zhihu.com/p/147875569

火焰图工作调优性能做报告时经常使用,在此不多赘述了

perf record -a -g -F 99 sleep 60
perf script report flamegraph
google-chrome flamegraph.html

实验

环境搭建

由于我在宿舍使用的是WSL ubutnu版本,其对微软魔改内核支持的不够好,按照系统的提示不能成功。此问题可以通过手动编译、换发行版、安装其他软件包的方式解决。

手动编译perf

本方法参考自:Install perf on WSL 2 · GitHub

依次运行如下指令

apt install flex bison
git clone https://github.com/microsoft/WSL2-Linux-Kernel --depth 1
cd WSL2-Linux-Kernel/tools/perf
make -j8
sudo cp perf /usr/local/bin

装了一堆依赖~

但是查看perf list发现,由于WSL2的虚拟化兼容硬件不好,不支持部分硬件采样,如branch-miss,先这样吧。

perf script安装(for flame graph)

https://askubuntu.com/questions/1397419/how-can-i-get-pre-canned-scripts-for-perf-script

评论

  1. 111
    5 月前
    2025-7-30 0:10:23

    你好

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇