“我只想知道这被调用了多少次。”…这是我经常询问内核、设备和应用程序事件的问题,并且有一个有效的方法来回答它们:使用 Linux perf stat。
perf工具(又名 perf_events)具有不同的操作模式。我之前关于CPU 采样、静态跟踪点和热图的示例使用了 perf_events 调用“采样”的模式,其中写入了包含事件数据的二进制 perf.data 文件。另一种模式“计数”在内核中汇总事件并将汇总传递给用户空间。这更有效,在 CPU 和存储方面的开销更少。
进程计数
有多少进程被创建和销毁?使用perf stat计算sched_process 跟踪点 5 秒:
perf stat -e ‘sched:sched_process_*’ -a sleep 5
“系统范围”的性能计数器统计信息:
20 sched:sched_process_free [100.00%]
21 sched:sched_process_exit [100.00%]
37 sched:sched_process_wait [100.00%]
20 sched:sched_process_fork [100.00%]
41 sched:sched_process_exec [100.00%]
0 sched:sched_process_hang
5.001391328 秒时间过去
整洁的。所以在 5 秒内有 20 个 fork() 和 21 个 exit()。我使用 -a 来匹配所有 CPU,并使用sleep 5作为虚拟命令来设置计数持续时间。您可以改用-p PID来匹配进程,并跳过 sleep 命令,以便perf一直运行到 Ctrl-C。
这适用于任何事件(请参阅perf list),包括所有静态和动态跟踪点。
系统调用计数
这是系统调用:
perf stat -e ‘syscalls:sys_enter_*’ -a sleep 5 | awk ‘$1’
开始于 2014 年 7 月 2 日星期三 23:39:50
“系统范围”的性能计数器统计信息:
60 个系统调用:sys_enter_socket [99.95%]
68 个系统调用:sys_enter_connect [99.95%]
148 系统调用:sys_enter_epoll_wait [99.97%]
8 个系统调用:sys_enter_statfs [99.97%]
18 个系统调用:sys_enter_dup2 [99.98%]
18 个系统调用:sys_enter_getcwd [99.98%]
155 系统调用:sys_enter_select [99.98%]
226 系统调用:sys_enter_poll [99.98%]
[…]
我使用 awk 去除了计数为零的系统调用。如果这对您不起作用,请在perf命令中添加“-o /dev/stdout”,旧版本(例如,Linux 3.2)可能需要该命令。我在旧版本中遇到的另一个问题是在匹配这么多探测器时需要增加文件描述符限制(ulimit -n)。
在使用 perf record 进行仔细查看之前,这种单行可以是一种快速确定正在使用的系统调用的方法,例如,使用参数和堆栈跟踪。
间隔摘要
perf stat 还可以在更新的版本中打印间隔摘要,使用 -I 和以毫秒为单位的持续时间。 例如,显示上下文切换的每秒速率:
perf stat -I 1000 -e sched:sched_switch -a sleep 5
time counts unit events
1.000205453 314 sched:sched_switch
2.000456051 290 sched:sched_switch
3.000644420 322 sched:sched_switch
4.000836009 305 sched:sched_switch
5.001022382 198 sched:sched_switch
5.001442140 7 sched:sched_switch
好的。同样,这适用于任何事件。
按 CPU-ID
您还可以通过 CPU id 进行分解:
perf stat -A -e sched:sched_switch -a sleep 5
“系统范围”的性能计数器统计信息:
CPU0 495 sched:sched_switch
CPU1 632 sched:sched_switch
5.001377216 秒时间过去
过滤
最后,可以添加 --filter 以仅根据布尔测试增加计数器。例如,计算请求大小大于 4 KB 的 read() 系统调用:
perf stat -e syscalls:sys_enter_read --filter ‘count > 4096’ -a sleep 5
“系统范围”的性能计数器统计信息:
1 系统调用:sys_enter_read
5.001407932 秒时间过去
请注意,我使用了“计数”变量。那是从哪里来的,还有什么?
您可以通过阅读内核源代码中的静态跟踪点定义来找出许多变量(请参阅我的静态跟踪点帖子中的示例)。另一种方法是打印它们的格式文件:
cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/format
名称:sys_enter_read
编号:509
格式:
字段:无符号短 common_type;偏移量:0;尺寸:2;签名:0;
字段:无符号字符 common_flags;偏移量:2;尺寸:1;签名:0;
字段:无符号字符 common_preempt_count;偏移量:3;尺寸:1;签名:0;
字段:int common_pid;偏移量:4;尺寸:4;签名:1;
字段:int nr;偏移量:8;尺寸:4;签名:1;
字段:无符号整数 fd;偏移量:16;尺寸:8;签名:0;
字段:char * buf;偏移量:24;尺寸:8;签名:0;
字段:size_t 计数;偏移量:32;尺寸:8;签名:0;
print fmt: “fd: 0x%08lx, buf: 0x%08lx, count: 0x%08lx”, ((unsigned long)(REC->fd)), ((unsigned long)(REC->buf)), ( (无符号长)(REC->count))
如果它是动态跟踪点,您可以使用perf probe -V列出可用变量。我希望静态跟踪点也有类似的选项。
以上是基本 perf_events 计数功能的快速浏览。更多是可能的;请参阅我的perf_events页面和perf_events wiki。
转载翻译自: https://www.brendangregg.com