我有一个测试应用程序,如下所示:

int main()
{
    // calls sched_setaffinity() to set affinity to core 0

    while(true)
    {
    }

    return 0;
}

我在2个物理核心上有4个逻辑核心.

我想看看Perf事件计数器,但只针对我的应用程序使用的CPU内核.

我运行这个perf命令(几秒钟后终止它):

sudo perf stat -e cycles:u --cpu=0 --delay=1000 ./app

四次,每次更改CPU id时,都会显示cycles:u>0.

为什么所有四个CPU都在为固定到内核0的应用程序执行用户空间周期?

肯定有三个核心不应该为我的应用程序执行用户空间周期?

推荐答案

似乎perf stat --cpu=的文档是错误的或具有误导性的,当他们说The 101 option is still necessary to activate system-wide monitoring.

无论有没有-a,它的行为似乎都是一样的,所以计数来自其他进程,如GUI动画,光标闪烁等,或者对于cycles:k,来自任何中断处理程序,无论哪个进程是该核心上的内核current.


我在Arch GNU/Linux系统上用内核和perf 6.5测试了这个. 这里的确凿证据是运行另一个固定在不同核心上的无限循环进程,并且在该核心上看到cycles:u,这与运行来自perf命令行的命令的核心相同.

基线without任何时髦的选项,其中awk 'BEGIN{for(i=0;i<100000000;i++){}}'是要分析的命令.(它使CPU核心忙碌几秒钟,除了在启动和退出时不进行任何系统调用,并且具有很小的缓存占用.)

$ taskset -c 1 perf stat -e task-clock,cycles:u  --delay=1000   awk 'BEGIN{for(i=0;i<100000000;i++){}}'
Events disabled
Events enabled

 Performance counter stats for 'awk BEGIN{for(i=0;i<100000000;i++){}}':

          2,625.29 msec task-clock                       #    1.000 CPUs utilized             
    10,226,974,370      cycles:u                                                              

       2.625290561 seconds time elapsed

--cpu相比,有两个迹象表明它不会局限于awk进程:任务时钟比运行时间长8倍.它打印的标题是:Performance counter stats for 'CPU(s) 0-7':,而不是我们的进程.

taskset -c 1 perf stat -e task-clock,cycles:u --cpu=0-7  --delay=1000   awk 'BEGIN{for(i=0;i<100000000;i++){}}'
Events disabled
Events enabled

 Performance counter stats for 'CPU(s) 0-7':

         23,621.12 msec task-clock                       #    8.000 CPUs utilized             
    12,747,549,694      cycles:u                                                              

       2.952544251 seconds time elapsed

由于-A又称为--no-aggr不是跨CPU聚合,所以每个CPU都有任务时钟在整个时间间隔内运行,即使我们的进程肯定不在上面(因为它和Perf本身开始固定在CPU 1上):

$ taskset -c 1 perf stat -e task-clock,cycles:u --cpu=0-7 -A  --delay=1000   awk 'BEGIN{for(i=0;i<100000000;i++){}}'
Events disabled
Events enabled

 Performance counter stats for 'CPU(s) 0-7':

CPU0             2,605.76 msec task-clock                       #    1.000 CPUs utilized             
CPU1             2,605.75 msec task-clock                       #    1.000 CPUs utilized             
CPU2             2,605.76 msec task-clock                       #    1.000 CPUs utilized             
CPU3             2,605.75 msec task-clock                       #    1.000 CPUs utilized             
CPU4             2,605.78 msec task-clock                       #    1.000 CPUs utilized             
CPU5             2,605.78 msec task-clock                       #    1.000 CPUs utilized             
CPU6             2,605.78 msec task-clock                       #    1.000 CPUs utilized             
CPU7             2,605.78 msec task-clock                       #    1.000 CPUs utilized             
CPU0          162,311,044      cycles:u                                                              
CPU1       10,153,813,410      cycles:u                                                              
CPU2           12,114,460      cycles:u                                                              
CPU3           49,619,566      cycles:u                                                              
CPU4          180,412,777      cycles:u                                                              
CPU5           51,045,799      cycles:u                                                              
CPU6          132,275,644      cycles:u                                                              
CPU7          344,942,273      cycles:u                                                              

       2.605703012 seconds time elapsed

对于虚拟加载(就像另一个awk进程,或者在本例中,我运行的程序只在pause条指令上循环,除了使用更少的功率之外,这并不是什么特别的),我们看到它使用的核心CPU 2与CPU 1上的awk一样多.

$ taskset -c 2 timeout 10m ~/src/SO/pauseloop &
    # actually on another terminal
$ taskset -c 1 perf stat -e task-clock,cycles:u --cpu=0-7 -A  --delay=1000   awk 'BEGIN{for(i=0;i<100000000;i++){}}'
Events disabled
Events enabled

 Performance counter stats for 'CPU(s) 0-7':

CPU0             2,721.71 msec task-clock                       #    1.000 CPUs utilized             
CPU1             2,721.71 msec task-clock                       #    1.000 CPUs utilized             
CPU2             2,721.71 msec task-clock                       #    1.000 CPUs utilized             
CPU3             2,721.71 msec task-clock                       #    1.000 CPUs utilized             
CPU4             2,721.70 msec task-clock                       #    1.000 CPUs utilized             
CPU5             2,721.70 msec task-clock                       #    1.000 CPUs utilized             
CPU6             2,721.69 msec task-clock                       #    1.000 CPUs utilized             
CPU7             2,721.69 msec task-clock                       #    1.000 CPUs utilized             
CPU0          861,492,255      cycles:u                                                              
CPU1       10,485,755,009      cycles:u                                                              
CPU2       10,485,655,861      cycles:u                                                              
CPU3          559,708,162      cycles:u                                                              
CPU4        1,207,134,025      cycles:u                                                              
CPU5          556,142,162      cycles:u                                                              
CPU6          623,020,558      cycles:u                                                              
CPU7        3,721,131,901      cycles:u                                                              

       2.721620976 seconds time elapsed

请注意,在内核1和内核2上,cycles:u的计数分别为10,485,755,00910,485,655,861.每10k不超过1个部分也是如此.(在我的i7-6700k上,频率为3.9 GHz,绝对差异约为10,485,755,009万,即约250纳秒,这很容易解释为不同内核的启动/停止计数的差异.)


-a --cpu only changes the header message, not counts

-a加到其中任何一个上(不带--cpu的除外),除了头消息外什么都不会改变,变为Performance counter stats for 'system wide':而不是'CPU(s) 0-7'

我看到的一切都与--cpu一致,实际上计算的是perf stat正在运行的核心上发生的一切,就像-a模式一样.

Linux相关问答推荐

Bash脚本用于在远程工作后关闭用户会话

使用文件名重新打开 linux 管道(仅从一侧)

如何使用 ftrace 过滤查看函数上方的调用堆栈?

从 curl 命令输出中获取值

最小的 x86_64 Hello World ELF 二进制文件是什么?

如何在linux中将2个不同大小的图像(边框,实际图像)合并为1个

如果 bash 中已经存在文件名,则创建新文件但添加数字

为什么 XGrabKey 会生成额外的聚焦和聚焦事件?

在 Ubuntu 中重启 Nginx

如何在不包括可用空间的情况下创建光盘(sd 卡)的 .IMG 映像?

exec 系统调用(如 exec 和 execve)系列的功能有什么区别?

将 $_GET 参数传递给 cron 作业(job)

NGINX:connect() 到 unix:/var/run/php7.0-fpm.sock 失败(2:没有这样的文件或目录)

bash 中的线程?

./studio.sh 之后的 Android Studio 错误

并行运行 shell 脚本

Linux 上真的没有异步块 I/O 吗?

如何在 Linux 中删除早于特定日期的文件?

cat、grep 和 cut - 翻译成 python

在 shell 脚本的 for 循环中迭代行而不是单词