有没有办法在linux中定期读取性能计数器?
perf stat
我正在寻找能够对每个 X 周期进行采样的能力。
基本上,我希望能够在某些程序的每 X 个 cpu 周期中读取指令计数器(执行的指令数)。
好消息:在下一个内核(Linux 3.9)中,perf stat 将有一个选项-I msecs
以定期打印事件增量。
https://patchwork.kernel.org/patch/2004891/
$ perf stat -I 1000 -e cycles noploop 10 noploop for 10 seconds 1.000086918 2385155642 cycles # 0.000 GHz 2.000267937 2392279774 cycles # 0.000 GHz 3.000385400 2390971450 cycles # 0.000 GHz 4.000504408 2390996752 cycles # 0.000 GHz 5.000626878 2390853097 cycles # 0.000 GHz
http://man7.org/linux/man-pages/man1/perf-stat.1.html
-I msecs, --interval-print msecs
每 N 毫秒打印一次计数增量(最小值:10 毫秒)
Linux 中的 perf 工具似乎通过在计数器达到特定值时记录事件来工作,而不是定期采样。
命令perf record -e cycles,instructions -c 10000
每 10000 个周期和每 10000 条指令存储一个事件。它可以针对新命令或现有 pid 运行。它记录perf.data
在当前目录中。
分析数据是另一回事。使用perf script
让你非常接近:
ls 16040 2152149.005813: cycles: c113a068 ([kernel.kallsyms])
ls 16040 2152149.005820: cycles: c1576af0 ([kernel.kallsyms])
ls 16040 2152149.005827: cycles: c10ed6aa ([kernel.kallsyms])
ls 16040 2152149.005831: instructions: c1104b30 ([kernel.kallsyms])
ls 16040 2152149.005835: cycles: c11777c1 ([kernel.kallsyms])
ls 16040 2152149.005842: cycles: c10702a8 ([kernel.kallsyms])
...
您需要编写一个脚本,从该输出中获取一堆行并计算该集合中“循环”和“指令”事件的数量。您可以通过更改-c 10000
录制命令中的参数来调整分辨率。
我通过运行perf stat
和perf record
反对验证了分析ls /
。Stat 报告了 2 634 205 个周期、1 725 255 条指令,而脚本输出有 410 个周期事件和 189 个指令事件。该-c
值越小,循环读数中的开销似乎就越大。
还有一个-F
选项perf record
,它定期采样。但是,使用此选项时,我找不到检索计数器值的方法。
编辑: perf stat
显然也适用于 pid,并在按下 ctrl-c 之前捕获数据。修改源代码应该很容易,使其始终捕获 N 秒,然后循环运行。
您可以轻松修改 perf stat 来执行此操作。
事实上,我已经实施了一个粗略的修改,很高兴与你分享这个变化。
我所做的更改主要在 while(!done) 循环中的 run_perf_stat 函数中
只需将 while(!done) {sleep(1);} 下面的行移动到循环内部,然后将睡眠更改为 nanosleep 并使用您希望采样的时间段
这应该使 perf 在 STDOUT(或 STDERR)上打印输出
如果您希望存储这些值,我建议您创建一个 struct stats 类型的二维数组,用每个样本更新它并定期写入文件