大家好,我是程栩,一个专注于性能的大厂程序员,分享包括但不限于计算机体系结构、性能优化、云原生的知识。
今天我们来聊一聊perf的相关命令,更进一步的了解perf。本文是perf系列的第四篇文章,后续会继续介绍perf,包括用法、原理和相关的经典文章。
引
输入perf
,我们可以看到有非常多的二级命令,这些二级命令是干什么的,都该怎么用?今天我们就尝试对这些命令做一次较为完整的介绍和分类。
本文基于perf version 4.18.0-348.7.1.el8_5.x86_64
版本完成。本文不会将每个指令的用法都做逐个说明,用户可以自行阅读文档;也不会讲的太深入,后续会进行深入讲解。
perf命令
自身相关
perf config
perf config可以让我们管理perf相关的一些变量。这些变量分为用户态和系统态变量,分别在用户HOME/.perconfig和(sysconfdir)/perfconfig 文件内。我们给出一个配置的样例:
代码语言:javascript复制# # This is the config file, and # a # and ; character indicates
a comment #
[colors]
# Color variables
top = red, default
medium = green, default
normal = lightgray, default
selected = white, lightgray
jump_arrows = blue, default
addr = magenta, default
root = white, blue
此外,我们可以通过perf config [section.name[=value]]
的方式修改配置项。例如:perf config colors.top=red
perf list
perf list
我们已经在前面的文章中介绍过,可以让我们知道perf
支持的事件都有哪些。
perf version
perf version
则更为简单,就是查看perf
当前的版本,我们可以通过添加--build-options
选项来查看当时的编译选项:
[root@VM-16-2-centos ~]# perf version --build-options
perf version 4.18.0-348.7.1.el8_5.x86_64
dwarf: [ on ] # HAVE_DWARF_SUPPORT
dwarf_getlocations: [ on ] # HAVE_DWARF_GETLOCATIONS_SUPPORT
glibc: [ on ] # HAVE_GLIBC_SUPPORT
syscall_table: [ on ] # HAVE_SYSCALL_TABLE_SUPPORT
libbfd: [ on ] # HAVE_LIBBFD_SUPPORT
libelf: [ on ] # HAVE_LIBELF_SUPPORT
libnuma: [ on ] # HAVE_LIBNUMA_SUPPORT
numa_num_possible_cpus: [ on ] # HAVE_LIBNUMA_SUPPORT
libperl: [ on ] # HAVE_LIBPERL_SUPPORT
libpython: [ on ] # HAVE_LIBPYTHON_SUPPORT
libslang: [ on ] # HAVE_SLANG_SUPPORT
libcrypto: [ on ] # HAVE_LIBCRYPTO_SUPPORT
libunwind: [ OFF ] # HAVE_LIBUNWIND_SUPPORT
libdw-dwarf-unwind: [ on ] # HAVE_DWARF_SUPPORT
zlib: [ on ] # HAVE_ZLIB_SUPPORT
lzma: [ on ] # HAVE_LZMA_SUPPORT
get_cpuid: [ on ] # HAVE_AUXTRACE_SUPPORT
bpf: [ on ] # HAVE_LIBBPF_SUPPORT
aio: [ on ] # HAVE_AIO_SUPPORT
zstd: [ on ] # HAVE_ZSTD_SUPPORT
libpfm4: [ OFF ] # HAVE_LIBPFM
此外,perf
作为内核的一部分,高版本的perf
往往是兼容低版本的。
perf test
perf test
是一个健全性测试,可以通过执行perf test
看看能执行哪些命令。这个执行的命令取决于我们的机器是否支持这些特性。
# 执行第83个测试
[root@VM-16-2-centos ~]# perf test 83
83: Use vfs_getname probe to get syscall args filenames : FAILED!
计数
perf stat
在前面我们也介绍过perf stat
,可以通过perf stat
来进行计数操作:
[root@VM-16-2-centos ~]# perf stat sleep 1
Performance counter stats for 'sleep 1':
0.58 msec task-clock # 0.001 CPUs utilized
1 context-switches # 0.002 M/sec
0 cpu-migrations # 0.000 K/sec
80 page-faults # 0.138 M/sec
<not supported> cycles
<not supported> instructions
<not supported> branches
<not supported> branch-misses
1.001128627 seconds time elapsed
0.000000000 seconds user
0.001138000 seconds sys
采样剖析
perf record
我们的老朋友了,通过perf record
我们可以记录他的剖析信息到perf.data
文件中,便于我们以后进行分析。
perf record
的默认频率是4000。
[root@VM-16-2-centos ~]# perf record -ag
^C[ perf record: Woken up 8 times to write data ]
[ perf record: Captured and wrote 2.351 MB perf.data (16239 samples) ]
perf top
perf top
可以帮助我们进行系统级的采样剖析:
perf top
我们可以通过h
来调出帮助菜单:
值得一提的是,a
键可以切换到当前的符号对应的汇编,并且看到对应的耗时:
按a展示对应汇编
不过这里的耗时并不是百分百精确的,可能耗时是在前后的指令,需要我们仔细考虑。如果我们能够确定热点并且优化这条指令,就可以带来一定的提升。
追踪
perf ftrace
perf ftrace
是内核ftrace
能力的一个包装工具,可以帮助我们使用ftrace
的相关能力。具体可以先了解ftrace
相关。
perf probe
perf probe
可以定义新的tracepoint,不过需要我们能够找到对应的符号或者相关信息才可以。
perf trace
perf trace
是一款受到strace
启发的追踪工具,可以帮助我们查看某个事件、命令、进程等相关的事件。最开始是设计给系统调用用的,但是后续逐渐添加了诸如page-fault
这样的系统事件:
[root@VM-16-2-centos ~]# perf trace node
? ( ): node/3378861 ... [continued]: execve()) = 0
0.028 ( 0.005 ms): node/3378861 brk() = 0x6240000
0.057 ( 0.003 ms): node/3378861 arch_prctl(option: 0x3001, arg2: 0x7ffefe7f40c0) = -1 EINVAL (Invalid argument)
0.082 ( 0.006 ms): node/3378861 access(filename: 0x3245cb0, mode: R) = 0
0.092 ( 0.004 ms): node/3378861 openat(dfd: CWD, filename: 0x3245cb0, flags: RDONLY|CLOEXEC) = 3
特定目标工具
这里的工具大部分遵循record
到report
的工作流程。如果想要使用,可以参考使用文档。
perf c2c
c2c
的意思是cache to cache
,也即很明显这是一个有关cacheline
的工具。这个功能是需要硬件支持的,在某一些硬件上可能并没有这个能力,比如AMD
的Zen3
就不支持该能力。工具可以帮助我们查看访问的地址,访问的类型和相关的延时以及最高争用的cache
信息。
perf kvm
perf kvm
可以对虚拟机做剖析,也可以同时对母机做剖析,这取决于我们的用法。具体用法可以参照其文档。
perf kmem
perf kmem
可以帮助我们衡量内核的内存特性,比如slab
的相关情况。
perf lock
perf lock
可以帮助我们分析锁相关的内容,需要优先开启tracepoint lock:lock_acquire
:
[root@VM-16-2-centos ~]# perf lock record
tracepoint lock:lock_acquire is not enabled. Are CONFIG_LOCKDEP and CONFIG_LOCK_STAT enabled?
perf mem
可以帮助我们对内存访问做剖析,通过perf mem record
来收集内存相关的操作并且放到perf.data
文件中,然后我们可以使用perf report
去查看结果。值得注意的是,它也需要硬件支持,否则:
[root@VM-16-2-centos ~]# perf mem record
failed: memory events not supported
perf sched
perf sched
可以衡量调度的延迟,也遵循record
到report
的流程。
perf timechart
perf timechart
可以通过perf timechart record
来记录某个时间段内系统级别的事件发生情况。默认会记录调度和CPU相关的事件,比如运行时间、任务切换等,我们也可以通过选项来查看磁盘IO和网络IO事件。
接着,我们可以通过perf timechart
将perf.data
文件转换成图片文件:
perf timechart结果
辅助功能
perf script
perf script
可以帮助读取perf.data
的内容,并且结合build-id
的信息,将数据转换成我们可以看懂的形式:
[root@VM-16-2-centos ~]# perf script
perf 3376223 [000] 13088049.893744: sched:sched_stat_runtime: comm=perf pid=3376223 runtime=25348 [ns] vruntime=22835234754203 [ns]
perf 3376223 [000] 13088049.893747: sched:sched_waking: comm=migration/0 pid=12 prio=0 target_cpu=000
perf 3376223 [000] 13088049.893748: sched:sched_stat_runtime: comm=perf pid=3376223 runtime=4759 [ns] vruntime=22835234758962 [ns]
perf 3376223 [000] 13088049.893748: sched:sched_switch: prev_comm=perf prev_pid=3376223 prev_prio=120 prev_state=R ==> next_comm=migration/0 next_pid=12 next_prio=0
migration/0 12 [000] 13088049.893750: sched:sched_migrate_task: comm=perf pid=3376223 prio=120 orig_cpu=0 dest_cpu=1
perf report
perf report
可以读取perf.data
的内容,并且图形化的展示:
perf report
页面和perf top
类似,只不过是基于文件,而不是实时采样的。同样,perf top
也可以使用h
、a
等选项。
perf annotate
perf annotate
可以读取由perf record
生成的perf.data
,展示解释版本。如果目标文件有对应的debug
文件,代码就会展示汇编代码和源代码;如果没有的话,就只会展示汇编。
perf annotate
perf buildid-list
perf buildid-list
可以展示perf.data
中发现的二进制文件名,以便于其他的工具(例如perf archive
、perf report
)可以来获取这些符号表从而更好地展示。
此外,我们也可以用这个工具来展示正在运行的内核或者ELF文件对应的二进制文件名。
perf buildid-cache
perf buildid-cache
可以帮助我们管理build-id
的cache
,包括添加、移除、更新等操作。
perf archive
如果我们收集了perf.data
,想换一台机器分析可以吗?当然是可以的,不过需要带上其他的一些文件。perf archive
就可以帮助我们,它会运行perf buildid-list -with-hits
然后把这些文件都打包起来,这样我们把这个文件和perf.data
移到别的机器上就可以进行分析了。
perf data
perf data
提供了更多的文件类型支持,可以帮助我们把perf.data
转换成其他格式,比如CTF
、JSON
格式等。
perf evlist
perf evlist
就是event list
,可以展示在一个perf.data
文件中的事件名:
[root@VM-16-2-centos ~]# perf evlist -i perf.data
cpu-clock:pppH
dummy:HG
perf diff
这个命令就和它的名字一样让人一看就懂,可以帮助我们比较两个采样文件:
代码语言:javascript复制[root@VM-16-2-centos ~]# perf diff perf.data perf.data.old
在比较的时候,它只会比较两个相同的事件。由于我们通常在采样的时候使用cpu-clock
,所以比较都是可以用的。
perf inject
perf inject
可以读取perf data
相关的内容,并且侵入该内容,基于传入的buildid
进行修改。在采样中,如果出现了unknown
,就是因为找不到对应的符号表而导致的,我们可以通过perf inject
带上对应的信息从而重新生成perf.data
。值得注意的是,它会修改原数据。
perf kallsyms
perf
中k
开头的大部分都和内核有关,kallsyms
可以帮助我们去寻找运行着的内核的符号表,并且打印出来:
[root@VM-16-2-centos ~]# perf kallsyms syscall_slow_exit_work
syscall_slow_exit_work: [kernel] [kernel.kallsyms] 0xffffffff87c03880-0xffffffff87c039b0 (0xffffffff87c03880-0xffffffff87c039b0)
perf daemon
perf daemon
允许我们运行一个守护进程来获取监控相关的信息,需要我们先配置好相关文件。
其他
perf bench
perf bench
是一个benchmark
框架套件,可以帮助我们测试sched
、syscall
、mem
、numa
、futex
、epoll
、internals
等方面的内容。具体可以查看文档
小结
今天,我们对非常多的perf
命令做了简单的介绍和分类。可以这么说,perf
包含的内容实在是太多了,我们很难完全记住,可能真正用上的只有百分之20,但是分析的模式(record
到report
)、分析的方式(profiling
、tracing
)都是值得我们学习的。
此外,大部分的命令都会生成perf.data
,我们可以用辅助功能来协助操作该文件。
perf命令
小结
关注我,和我一起一起攀登性能之巅。
参考文件
- perf man7(https://man7.org/linux/man-pages/man1/perf.1.html)