我在寻找途径,以了解哪些系统调用或子系统进程或线程花费时间等待的,即阻止,没有安排一个CPU上运行。
具体来说,如果我有一些未知的过程,还是一个过程,我们所知道的是“它的速度慢”我希望能够学习的东西,如:
sys_write()
上FD 13是/一些/文件”换句话说,当我的程序的CPU,它正在做什么上没有运行?
这是一个惊人很难与perf
回答,因为它不会出现有任何的方式来记录从sys_enter系统调用的持续时间sys_exit或以其他方式跟踪的事件有多长。这可能是由于它的采样性质。
我知道有一些eBPF试点工作为Linux 4.6及以上的,可以帮助,与布伦丹·格雷格的off-cpu work的。但在悲伤的世界运营,并支持4.6内核是一种罕见的麒麟珍惜。
什么是现实世界的选择吗?
不要ftrace内部,SystemTap等提供任何见解吗?
您可以使用strace。首先,你可能希望得到每种类型的系统调用的成本的高度概括。您可以通过运行strace -c
获得本摘要。例如,一个可能的输出是下面的:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
90.07 0.000263 26 10 getdents
3.42 0.000010 0 1572 read
3.42 0.000010 0 762 1 stat
3.08 0.000009 0 1574 6 open
0.00 0.000000 0 11 write
0.00 0.000000 0 1569 close
0.00 0.000000 0 48 fstat
所述% time
值是相对于总内核时间,不总执行时间(内核+用户)。本摘要告诉你最昂贵的系统调用是什么。但是,如果您需要确定哪些系统调用的具体实例是最昂贵的,并且传递给他们什么样的参数,你可以运行strace -i -T
。该-i
选项显示的是执行系统调用和-T
选项,在系统调用花费的时间指令的指令地址。输出可能是这样的:
[00007f97f1b37367] open("myfile", O_RDONLY|O_CLOEXEC) = 3 <0.000020>
[00007f97f1b372f4] fstat(3, {st_mode=S_IFREG|0644, st_size=159776, ...}) = 0 <0.000018>
[00007f97f1b374ba] mmap(NULL, 159776, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f97f1d19000 <0.000019>
[00007f97f1b37467] close(3) = 0 <0.000018>
第一列显示指令地址,第二列显示了他们的论据系统调用,第三列显示返回值,最后一列显示了在系统调用花费的时间。这份名单是由系统调用的动态发生有序。您可以使用过滤或者grep
或-e
选项此输出。该指令的地址可以帮助定位在源代码中,这些系统调用制成。例如,如果系统调用的长序列具有相同的地址,再有就是您在包含系统调用的代码有一个循环的地方一个很好的机会。如果你的可执行的二进制不PIE,动态地址是相同的,通过objdump
显示的静态地址。不过,即使PIE,动态地址的相对顺序是一样的。我不知道是否有映射这些系统调用行源代码的简单方法。
如果你想了解的东西一样,那么你需要编写一个脚本,首先提取所有open
调用的返回值和相应的“它SYS_WRITE在FD 13是/一些/文件花费其80%的时间()”文件名参数,然后总结sys_write
要求其fd
参数等于某个值的所有时间。