包罗万象-perf命令介绍

2023-11-01 16:59:50 浏览数 (1)

大家好,我是程栩,一个专注于性能的大厂程序员,分享包括但不限于计算机体系结构、性能优化、云原生的知识。

今天我们来聊一聊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选项来查看当时的编译选项:

代码语言:javascript复制
[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看看能执行哪些命令。这个执行的命令取决于我们的机器是否支持这些特性。

代码语言:javascript复制
# 执行第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来进行计数操作:

代码语言:javascript复制
[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。

代码语言:javascript复制
[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这样的系统事件:

代码语言:javascript复制
[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

特定目标工具

这里的工具大部分遵循recordreport的工作流程。如果想要使用,可以参考使用文档。

perf c2c

c2c的意思是cache to cache,也即很明显这是一个有关cacheline的工具。这个功能是需要硬件支持的,在某一些硬件上可能并没有这个能力,比如AMDZen3就不支持该能力。工具可以帮助我们查看访问的地址,访问的类型和相关的延时以及最高争用的cache信息。

perf kvm

perf kvm可以对虚拟机做剖析,也可以同时对母机做剖析,这取决于我们的用法。具体用法可以参照其文档。

perf kmem

perf kmem可以帮助我们衡量内核的内存特性,比如slab的相关情况。

perf lock

perf lock可以帮助我们分析锁相关的内容,需要优先开启tracepoint lock:lock_acquire

代码语言:javascript复制
[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去查看结果。值得注意的是,它也需要硬件支持,否则:

代码语言:javascript复制
[root@VM-16-2-centos ~]# perf mem record
failed: memory events not supported
perf sched

perf sched可以衡量调度的延迟,也遵循recordreport的流程。

perf timechart

perf timechart可以通过perf timechart record来记录某个时间段内系统级别的事件发生情况。默认会记录调度和CPU相关的事件,比如运行时间、任务切换等,我们也可以通过选项来查看磁盘IO和网络IO事件。

接着,我们可以通过perf timechartperf.data文件转换成图片文件:

perf timechart结果

辅助功能

perf script

perf script可以帮助读取perf.data的内容,并且结合build-id的信息,将数据转换成我们可以看懂的形式:

代码语言:javascript复制
[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也可以使用ha等选项。

perf annotate

perf annotate可以读取由perf record生成的perf.data,展示解释版本。如果目标文件有对应的debug文件,代码就会展示汇编代码和源代码;如果没有的话,就只会展示汇编。

perf annotate

perf buildid-list

perf buildid-list可以展示perf.data中发现的二进制文件名,以便于其他的工具(例如perf archiveperf report)可以来获取这些符号表从而更好地展示。

此外,我们也可以用这个工具来展示正在运行的内核或者ELF文件对应的二进制文件名。

perf buildid-cache

perf buildid-cache可以帮助我们管理build-idcache,包括添加、移除、更新等操作。

perf archive

如果我们收集了perf.data,想换一台机器分析可以吗?当然是可以的,不过需要带上其他的一些文件。perf archive就可以帮助我们,它会运行perf buildid-list -with-hits然后把这些文件都打包起来,这样我们把这个文件和perf.data移到别的机器上就可以进行分析了。

perf data

perf data提供了更多的文件类型支持,可以帮助我们把perf.data转换成其他格式,比如CTFJSON格式等。

perf evlist

perf evlist就是event list,可以展示在一个perf.data文件中的事件名:

代码语言:javascript复制
[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

perfk开头的大部分都和内核有关,kallsyms可以帮助我们去寻找运行着的内核的符号表,并且打印出来:

代码语言:javascript复制
[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框架套件,可以帮助我们测试schedsyscallmemnumafutexepollinternals等方面的内容。具体可以查看文档

小结

今天,我们对非常多的perf命令做了简单的介绍和分类。可以这么说,perf包含的内容实在是太多了,我们很难完全记住,可能真正用上的只有百分之20,但是分析的模式(recordreport)、分析的方式(profilingtracing)都是值得我们学习的。

此外,大部分的命令都会生成perf.data,我们可以用辅助功能来协助操作该文件。

perf命令

小结

关注我,和我一起一起攀登性能之巅。

参考文件

  • perf man7(https://man7.org/linux/man-pages/man1/perf.1.html)

0 人点赞