Linux监控&性能调优分析-perf(上)
1 简介
Linux perf一个轻量级命令行工具,用于剖析和监控Linux系统的CPU性能。该工具虽然简单,却能提供有助于分析CPU的丰富信息。该命令包含许多用于收集、跟踪和分析CPU事件数据的子命令。
1.1 安装perf
perf程序并没有预装在Linux系统中
# Ubuntu/Debian
$ sudo apt install linux-tools-$(uname -r) linux-tools-generic
# RHEL/CentOS
$ sudo yum install perf
# Fedora
$ sudo dnf install perf
# 验证
$ perf -v
perf version 5.15.149
1.2 允许普通用户使用perf
perf命令默认需要sudo权限。要允许普通用户使用perf,请执行以下操作:
$ sudo su -
# echo 0 > /proc/sys/kernel/perf_event_paranoid
# nano /etc/sysctl.conf # 添加如下内容
kernel.perf_event_paranoid = 0
Linux perf 命令语法
1.3 perf命令的语法如下
perf <options> subcommand <options/arguments>
perf 工具的工作原理与git类似。它是各种子命令和不同活动的接口。运行不带任何选项或参数的命令会显示可用的子命令列表。
-
perf stat
该命令提供常见性能事件的总体统计数据,包括执行的指令和消耗的时钟周期。除默认测量事件外,还可通过选项选择其他事件。 -
perf record
该命令将性能数据记录到 perf.data 文件中,随后可使用 perf report 命令对其进行分析。 -
perf report
该命令从 perf record 创建的 perf.data 文件中读取并显示性能数据。
-
perf list
该命令列出特定机器上的可用事件。这些事件将根据系统的性能监控硬件和软件配置而有所不同。 -
perf top
该命令执行与 top 工具类似的功能。它会实时生成并显示性能计数器配置文件。 -
perf trace
该命令执行与 strace 工具类似的功能。它监控指定线程或进程使用的系统调用以及该应用程序接收的所有信号。 -
perf help
该命令显示 perf 命令的完整列表。
要显示各个子命令的选项,请运行
perf <subcommand> -h
2 使用perf top实时分析CPU使用
2.1 perf top 的用途
perf top 命令用于实时系统剖析,功能与 top 工具类似。不过,top 工具通常显示某个进程或线程占用了多少 CPU 时间,而 perf top 则显示每个特定函数占用了多少 CPU 时间。在默认状态下,perf top 会告诉你用户空间和内核空间中所有 CPU 正在使用的函数。使用 perf top 需要 root 访问权限。
2.2 使用 perf top 分析 CPU 使用
# perf top
Samples: 8K of event 'cycles', 2000 Hz, Event count (approx.): 4579432780 lost: 0/0 drop: 0/0
Overhead Shared Object Symbol
2.20% [kernel] [k] do_syscall_64
2.17% [kernel] [k] module_get_kallsym
1.49% [kernel] [k] copy_user_enhanced_fast_string
1.37% libpthread-2.29.so [.] pthread_mutex_lock 1.31% [unknown] [.] 0000000000000000 1.07% [kernel] [k] psi_task_change 1.04% [kernel] [k] switch_mm_irqs_off 0.94% [kernel] [k] fget
0.74% [kernel] [k] entry_SYSCALL_64
0.69% [kernel] [k] syscall_return_via_sysret
0.69% libxul.so [.] 0x000000000113f9b0
0.67% [kernel] [k] kallsyms_expand_symbol.constprop.0
0.65% firefox [.] moz_xmalloc
0.65% libpthread-2.29.so [.] __pthread_mutex_unlock_usercnt
0.60% firefox [.] free
0.60% libxul.so [.] 0x000000000241d1cd
0.60% [kernel] [k] do_sys_poll
0.58% [kernel] [k] menu_select
0.56% [kernel] [k] _raw_spin_lock_irqsave
0.55% perf [.] 0x00000000002ae0f3
2.3 perf top 输出的解释
- 开销(Overhead)"列
显示特定函数占用 CPU 的百分比。
- 共享对象(Shared Object)列
显示使用该函数的程序或库的名称。
- 符号(Symbol)列
显示函数名称或符号。在内核空间执行的函数用 [k] 标识,在用户空间执行的函数用 [.]标识。
2.4 为什么 perf 将某些函数名显示为原始函数地址
对于内核函数,perf 使用 /proc/kallsyms 文件中的信息将样本映射到相应的函数名或符号。但对于在用户空间执行的函数,由于二进制文件已被剥离,因此可能会显示原始函数地址。
在这种情况下,必须安装可执行文件的 debuginfo 包,或者,如果可执行文件是本地开发的应用程序,则必须在编译应用程序时打开调试信息(GCC 中的 -g 选项),以显示函数名或符号。
注意: 安装与可执行文件相关的调试信息后,无需重新运行 perf record 命令。只需重新运行 perf report 命令即可。
2.5 启用调试和源代码库
Linux 的标准安装不会启用调试和源代码库。这些资源库包含调试系统组件和衡量其性能所需的信息。
# subscription-manager repos --enable rhel-8-for-$(uname -i)-baseos-debug-rpms
# subscription-manager repos --enable rhel-8-for-$(uname -i)-baseos-source-rpms
# subscription-manager repos --enable rhel-8-for-$(uname -i)-appstream-debug-rpms
# subscription-manager repos --enable rhel-8-for-$(uname -i)-appstream-source-rpms
2.6 使用 GDB 获取应用程序或库的调试信息包
调试代码需要调试信息。对于通过软件包安装的代码,GNU 调试器(GDB)会自动识别缺失的调试信息,解析软件包名称,并提供如何获取软件包的具体建议。
启动连接到要调试的应用程序或库的 GDB。GDB 会自动识别缺失的调试信息,并建议运行一条命令。
$ gdb -q /bin/ls
Reading symbols from /bin/ls...Reading symbols from .gnu_debugdata for /usr/bin/ls...(no debugging symbols found)...done.
(no debugging symbols found)...done.
Missing separate debuginfos, use: dnf debuginfo-install coreutils-8.30-6.el8.x86_64
(gdb)
# dnf debuginfo-install coreutils-8.30-6.el8.x86_64
3 使用 perf stat 统计进程执行过程中的事件
3.1 perf stat 的用途
perf stat 命令执行指定的命令,对命令执行期间发生的硬件和软件事件进行持续计数,并生成这些计数的统计数据。如果不指定任何事件,perf stat 会统计一组常见的硬件和软件事件。
3.2 用 perf stat 统计事件
$ perf stat ls
Desktop Documents Downloads Music Pictures Public Templates Videos
Performance counter stats for 'ls':
1.28 msec task-clock:u # 0.165 CPUs utilized
0 context-switches:u # 0.000 M/sec
0 cpu-migrations:u # 0.000 K/sec
104 page-faults:u # 0.081 M/sec
1,054,302 cycles:u # 0.823 GHz
1,136,989 instructions:u # 1.08 insn per cycle
228,531 branches:u # 178.447 M/sec
11,331 branch-misses:u # 4.96% of all branches
0.007754312 seconds time elapsed
0.000000000 seconds user
0.007717000 seconds sys
如上例所示,当 perf stat 在没有 root 访问权限的情况下运行时,事件名称后跟有 :u,表明这些事件仅在用户空间中计数。
要同时统计用户空间和内核空间的事件,运行 perf stat 时必须有 root 访问权限:
# perf stat ls
Desktop Documents Downloads Music Pictures Public Templates Videos
Performance counter stats for 'ls':
3.09 msec task-clock # 0.119 CPUs utilized
18 context-switches # 0.006 M/sec
3 cpu-migrations # 0.969 K/sec
108 page-faults # 0.035 M/sec
6,576,004 cycles # 2.125 GHz
5,694,223 instructions # 0.87 insn per cycle
1,092,372 branches # 352.960 M/sec
31,515 branch-misses # 2.89% of all branches
0.026020043 seconds time elapsed
0.000000000 seconds user
0.014061000 seconds sys
默认情况下,perf stat 以每线程模式运行。要改用 CPU 范围的事件计数,请在 perf stat 中加入 -a 选项。要计算 CPU 范围内的事件,需要 root 访问权限:
# perf stat -a ls
3.3 perf stat 输出的解释
perf stat 执行指定命令,在命令执行过程中统计事件发生次数,并在三列中显示统计结果:
- 特定事件的发生次数
- 被统计事件的名称
- 如果有相关指标,最右边一列的哈希符号 (#) 后面会显示比率或百分比。
例如,在默认模式下运行时,perf stat 会同时计算周期和指令,因此会在最右边一列计算并显示每个周期的指令数。由于默认情况下这两种事件都被计算在内,因此您可以看到类似的分支错误占所有分支百分比的行为。
3.4 将 perf stat 附加到运行中的进程
您可以将 perf stat 附加到正在运行的进程。这将指示 perf stat 在执行命令期间只计算指定进程中发生的事件。
前提条件
已安装 perf 用户空间工具,如安装 perf 中所述。
操作步骤
将 perf stat 附加到正在运行的进程:
$ perf stat -p ID1,ID2 sleep seconds
上例通过使用 sleep 命令,以秒为单位统计 ID 为 ID1 和 ID2 的进程中的事件。
$ sudo perf stat -p 1913119,4240 sleep 3
Performance counter stats for process id '1913119,4240':
26.17 msec task-clock # 0.009 CPUs utilized
13 context-switches # 0.497 K/sec
1 cpu-migrations # 0.038 K/sec
1 page-faults # 0.038 K/sec
68,245,892 cycles # 2.607 GHz
94,333,646 instructions # 1.38 insn per cycle
<not supported> branches
189,274 branch-misses
3.001225574 seconds time elapsed
4 使用 perf 记录和分析性能曲线
4.1 perf record的目的
perf record 命令对性能数据进行采样,并将其存储在 perf.data 文件中,可以使用其他 perf 命令读取和可视化该文件。perf.data 在当前目录下生成,可以在以后访问。
如果您没有为 perf record 指定要记录的命令,它会一直记录,直到您按下 Ctrl+C 手动停止进程。你可以通过 -p 选项和一个或多个进程 ID,将 perf record 附加到特定进程。你可以在没有 root 访问权限的情况下运行 perf record,但这样做只能在用户空间采样性能数据。在默认模式下,perf record 使用 CPU 周期作为采样事件,并以启用继承模式的每线程模式运行。
4.2 在没有root访问权限的情况下记录性能配置文件
$ perf record command
将 command 替换为要采样数据的命令。如果不指定命令,perf record 将采样数据,直到您按下 Ctrl+C 手动停止。
4.3 使用 root 记录性能配置文件
perf record command
4.4 以per-CPU模式记录性能配置文件
在 per-CPU 模式下,您可以使用 perf record 同时采样和记录受监控 CPU 上所有线程在用户空间和内核空间的性能数据。默认情况下,per-CPU模式监控所有在线 CPU。
# perf record -a command# 所有CPU
$ perf record -C 127,1 # CPU1和127
4.5 使用 perf record 捕捉调用图数据
您可以配置 perf record 工具,使其记录哪个函数正在调用性能配置文件中的其他函数。这有助于在多个进程调用同一函数时识别瓶颈。
$ perf record --call-graph method command
method为展开堆栈的方法,有如下几种:
- fp( frame pointe)
使用帧指针方法。根据编译器优化情况,例如使用 GCC 选项 --fomit-frame-pointer 生成的二进制文件,可能无法解开堆栈。
-
dwarf
使用 DWARF 调用帧信息来展开堆栈。 -
lbr last branch record)
4.6 使用 perf 报告分析 perf.data
如果 perf.data 文件是以 root 访问权限创建的,则也需要以 root 访问权限运行 perf report。
# perf report
Samples: 2K of event 'cycles', Event count (approx.): 235462960
Overhead Command Shared Object Symbol
2.36% kswapd0 [kernel.kallsyms] [k] page_vma_mapped_walk
2.13% sssd_kcm libc-2.28.so [.] memset_avx2_erms 2.13% perf [kernel.kallsyms] [k] smp_call_function_single 1.53% gnome-shell libc-2.28.so [.] strcmp_avx2
1.17% gnome-shell libglib-2.0.so.0.5600.4 [.] g_hash_table_lookup
0.93% Xorg libc-2.28.so [.] memmove_avx_unaligned_erms 0.89% gnome-shell libgobject-2.0.so.0.5600.4 [.] g_object_unref 0.87% kswapd0 [kernel.kallsyms] [k] page_referenced_one 0.86% gnome-shell libc-2.28.so [.] memmove_avx_unaligned_erms
0.83% Xorg [kernel.kallsyms] [k] alloc_vmap_area
0.63% gnome-shell libglib-2.0.so.0.5600.4 [.] g_slice_alloc
0.53% gnome-shell libgirepository-1.0.so.1.0.0 [.] g_base_info_unref
0.53% gnome-shell ld-2.28.so [.] _dl_find_dso_for_object
0.49% kswapd0 [kernel.kallsyms] [k] vma_interval_tree_iter_next
0.48% gnome-shell libpthread-2.28.so [.] pthread_getspecific 0.47% gnome-shell libgirepository-1.0.so.1.0.0 [.] 0x0000000000013b1d 0.45% gnome-shell libglib-2.0.so.0.5600.4 [.] g_slice_free1 0.45% gnome-shell libgobject-2.0.so.0.5600.4 [.] g_type_check_instance_is_fundamentally_a 0.44% gnome-shell libc-2.28.so [.] malloc 0.41% swapper [kernel.kallsyms] [k] apic_timer_interrupt 0.40% gnome-shell ld-2.28.so [.] _dl_lookup_symbol_x 0.39% kswapd0 [kernel.kallsyms] [k] raw_callee_save___pv_queued_spin_unlock
Additional resources
参考资料
- 软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
- 本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
- python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
- Linux精品书籍下载 https://www.cnblogs.com/testing-/p/17438558.html
- 如需技术支持联系钉ding或微信pythontesting , 邮箱: xurongzhong#126.com
4.7 解释 perf 报告输出
- 开销(Overhead)"列
表示在该特定功能中采集的样本占总体样本的百分比。
- 命令(Command)列
告诉你样本是从哪个进程中采集的。
- 共享对象(Shared Object)列
显示样本来自 ELF 映像的名称(样本来自内核时使用 [kernel.kallsyms] 名称)。
- 符号(Symbol)列
显示函数名称或符号。
在默认模式下,函数按降序排序,开销最大的函数显示在最前面。
4.8 生成可在不同设备上读取的 perf.data 文件
您可以使用 perf 工具将性能数据记录到 perf.data 文件中,以便在不同设备上进行分析。
# perf record -a --call-graph fp sleep seconds
此示例将生成整个系统的 perf.data 数据,时间为使用 sleep 命令后的几秒钟。它还将使用帧指针方法捕获调用图数据。
生成一个包含所记录数据的调试符号的归档文件:
# perf archive
Now please run:
$ tar xvf perf.data.tar.bz2 -C ~/.debug
wherever you need to run 'perf report' on.
# ls perf.data*
perf.data perf.data.old perf.data.tar.bz2
4.9 分析在不同设备上创建的 perf.data 文件
# mkdir -p ~/.debug
# tar xf perf.data.tar.bz2 -C ~/.debug
# perf report