Heng30的博客
搜索 分类 关于 订阅

如何使用perf跟踪调试内核?

2025-02-13

perfLinux系统中的一个性能分析工具,用于监控和分析系统及应用程序的性能。它基于内核的perf_events接口,能够收集硬件(如 CPU 性能计数器)和软件事件(如上下文切换、缺页异常等)的数据。

主要功能

  • CPU 性能分析:

    • 统计函数、指令级别的 CPU 使用情况。
    • 支持硬件性能计数器,如缓存命中率、分支预测等。
  • 系统调用分析:

    • 跟踪系统调用,帮助识别瓶颈。
  • 内存分析:

    • 监控内存访问模式、缺页异常等。
  • 多线程分析:

    • 分析多线程程序的锁争用、线程调度等。
  • 动态追踪:

    • 支持动态追踪内核和用户空间事件。

安装程序

  • sudo apt install linux-tools-$(uname -r)
  • sudo apt install linux-tools-common

常用命令

   annotate        读取 perf.data(由 perf record 创建)并显示带注释的代码
   archive         根据 perf.data 文件中找到的带有构建 ID 的目标文件创建归档
   bench           基准测试套件的通用框架
   buildid-cache   管理构建 ID 缓存
   buildid-list    列出 perf.data 文件中的构建 ID
   c2c             共享数据 C2C/HITM 分析器
   config          获取和设置配置文件中的变量
   daemon          在后台运行记录会话
   data            与数据文件相关的处理
   diff            读取 perf.data 文件并显示差异分析结果
   evlist          列出 perf.data 文件中的事件名称
   ftrace          内核 ftrace 功能的简单包装器
   inject          过滤器,用于在事件流中添加额外信息
   iostat          显示 I/O 性能指标
   kallsyms        在运行的内核中搜索符号
   kvm             用于跟踪/测量 KVM 来宾操作系统的工具
   list            列出所有符号化的事件类型
   mem             分析内存访问情况
   record          运行一个命令并将其性能分析结果记录到 perf.data 中
   report          读取 perf.data(由 perf record 创建)并显示性能分析报告
   script          读取 perf.data(由 perf record 创建)并显示跟踪输出
   stat            运行一个命令并收集性能计数器统计信息
   test            运行健全性测试
   top             系统性能分析工具
   version         显示 perf 二进制文件的版本
   probe           定义新的动态跟踪点
   trace           受 strace 启发的工具
   kmem            用于跟踪/测量内核内存属性的工具
   kwork           用于跟踪/测量内核工作属性(延迟)的工具
   lock            分析锁事件
   sched           用于跟踪/测量调度器属性(延迟)的工具
   timechart       用于可视化工作负载期间整个系统行为的工具

例子

  • 记录数据:perf record

  • 记录特定命令的数据:perf record -g <cmd>

  • 记录特定进程的数据:perf record -p <pid> -a -g -- sleep 10

  • 展示数据:perf report

   96.99%  swapper          [kernel.kallsyms]              [k] pv_native_safe_halt
   0.66%  swapper          [kernel.kallsyms]              [k] handle_softirqs
   0.42%  swapper          [kernel.kallsyms]              [k] vbg_req_perform
   0.07%  swapper          [kernel.kallsyms]              [k] _raw_spin_unlock_irqrestore
   0.04%  swapper          [kernel.kallsyms]              [k] finish_task_switch.isra.0
   0.03%  (udev-worker)    [kernel.kallsyms]              [k] do_syscall_64
   0.03%  (udev-worker)    [kernel.kallsyms]              [k] do_user_addr_fault
   0.03%  swapper          [kernel.kallsyms]              [k] e1000_alloc_rx_buffers
   0.02%  gnome-shell      [kernel.kallsyms]              [k] __fdget
   0.02%  gnome-shell      libglib-2.0.so.0.8000.0        [.] 0x000000000005e0de
   0.02%  gnome-shell      libglib-2.0.so.0.8000.0        [.] 0x000000000005e299
   0.02%  kworker/0:2-eve  [kernel.kallsyms]              [k] get_recent_times
   0.02%  sshd             [kernel.kallsyms]              [k] finish_task_switch.isra.
  • 添加监听事件: perf probe --add kmem_cache_free
Added new event:
  probe:do_sys_open    (on do_sys_open)

You can now use it in all perf tools, such as:
        perf record -e probe:kmem_cache_free -aR sleep 1
  • 查看事件:perf list | grep kmem_cache_free
  probe:kmem_cache_free                                  [Tracepoint event]
  • 查看特定命令系统调用:perf trace ls
         ? (         ): ls/53519  ... [continued]: execve())                                           = 0
     0.131 ( 0.019 ms): ls/53519 brk()                                                                 = 0x59f3a7adf000
     0.476 ( 0.027 ms): ls/53519 mmap(len: 8192, prot: READ|WRITE, flags: PRIVATE|ANONYMOUS)           = 0x7b0ecd003000
     0.533 ( 0.023 ms): ls/53519 access(filename: 0xcd0345b0, mode: R)                                 = -1 ENOENT (No such file or directory)
     0.587 ( 0.028 ms): ls/53519 openat(dfd: CWD, filename: 0xcd03338f, flags: RDONLY|CLOEXEC)         = 3
     0.632 ( 0.018 ms): ls/53519 fstat(fd: 3, statbuf: 0x7ffe08282860)                                 = 0
     0.665 ( 0.025 ms): ls/53519 mmap(len: 63871, prot: READ, flags: PRIVATE, fd: 3)
    ...
  • 查看特定命令统计信息:perf stat ls
 Performance counter stats for 'ls':
              2.61 msec task-clock                       #    0.702 CPUs utilized
                 1      context-switches                 #  383.784 /sec
                 0      cpu-migrations                   #    0.000 /sec
                91      page-faults                      #   34.924 K/sec
   <not supported>      cycles
   <not supported>      instructions
   <not supported>      branches
   <not supported>      branch-misses

       0.003709959 seconds time elapsed

       0.000983000 seconds user
       0.002950000 seconds sys
  • 实时监控热点函数:perf top
Samples: 18K of event 'cpu-clock:ppp', 4000 Hz, Event count (approx.): 4058187458 lost: 0/0 drop: 0/0
Overhead  Shared Object                Symbol
  95.86%  [kernel]                     [k] pv_native_safe_halt
   0.44%  [kernel]                     [k] vbg_req_perform
   0.34%  [kernel]                     [k] handle_softirqs
   0.32%  perf                         [.] io__get_char
   0.25%  [kernel]                     [k] kallsyms_expand_symbol.constprop.0
   0.21%  perf                         [.] kallsyms__parse
   0.12%  [kernel]                     [k] string
   0.12%  perf                         [.] io__get_hex
   0.11%  perf                         [.] map__process_kallsym_symbol
   0.10%  libc.so.6                    [.] _int_malloc
 ...
  • 生成火焰图
# 进行数据采集
sudo perf record -a -g -- sleep 60
sudo perf script > out.perf

# 下载工具
https://github.com/brendangregg/FlameGraph.git

# 生成火焰图
FlameGraph/stackcollapse-perf.pl out.perf > out.folded
FlameGraph/flamegraph.pl out.folded > out.svg
magick out.svg out.png

火焰图

希望上面的内容对你有所帮助。