据我了解,time
将记录系统调用中花费的总时间。然后我希望 sys 时间的累积总数与报告的time
和strace -fc
相同。但它们截然不同(13.5 对 0.005)。怎么了?
# time php index.php >/dev/null
real 0m16.292s
user 0m2.728s
sys 0m13.548s
# strace -fc php index.php >/dev/null
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
83.72 0.000365 0 54845 munmap
10.09 0.000044 0 36705 mmap
6.19 0.000027 0 18249 madvise
0.00 0.000000 0 289 read
0.00 0.000000 0 119 write
0.00 0.000000 0 118 3 open
0.00 0.000000 0 118 close
0.00 0.000000 0 23 stat
[ cut 0 duration syscalls for brevity ]
100.00 0.000436 110951 82 total
(我已经重新运行这些测试大约 50 次,它们都给出了一致的结果)
一个进程可以花费任何时间不进行任何系统调用。
例如,执行 a 的 shell
while :; do :; done
将花费无限的时间不执行任何系统调用并且不花费任何sys
CPU 时间,只花费user
CPU 时间。strace -c
尝试sys
通过每个系统调用计算 CPU 时间。Ananosleep(1000000000)
将花费接近 0 毫秒的 CPU 时间但 1 秒的挂钟时间。将 sys 时间与 strace 报告的时间进行比较会更有意义,但请注意,并非所有用于进程的 sys CPU 时间都花费在这些系统调用中。例如,访问 mmaped 数据会使进程在不进行任何系统调用的情况下花费大量系统时间。
在这里,那些众多的
mmaps()
调用可能是分配内存。这些是即时的,因为它们只是更新了一些映射。但是,当您第一次写入这些时,需要一些系统时间来支持这些写入与实际内存。或者他们可以映射共享库之类的目标文件(这也是一种可能的可能性,因为数量与 的数量相差不远
open()s
)。再说一遍,这mmap()
很快,但稍后读取内存也意味着一些页面错误和从磁盘读取数据的实际时间,这不计入任何系统调用。更根本的是,如果您
time strace -f your-application
按照问题的早期版本进行操作,time
那么命令和strace
.strace
增加了很多开销。它为跟踪应用程序的每个系统调用执行几个系统调用。正在做
代替
更有可能给你一个更好的匹配。
但我发现,对于
wait*()
进程等待其子进程的系统调用,将strace
这些系统调用报告的时间计wait*()
为系统时间,这意味着子进程(至少是等待的那些)的时间是数了几遍。这与在子进程中运行并等待它一样重要strace -f time cmd
。time
cmd
time
并strace
报告相同的系统时间(由wait4()
系统调用返回),但具有-f
:1.33是一个
wait4()
系统调用报告的时间time
。报告head
(time
的孩子) 的系统时间。但是,除此之外,
strace
它还会尝试为其head
孙子的每个系统调用获取系统时间,这意味着它被计算了两次(不完全)。由于我们得到 1.33 而不是之前的 0.76,因此对孙子的跟踪仍然会产生一些开销,这些开销与跟踪过程有关。如果我强制 strace、time 和 head 在同一个处理器上运行(使用taskset 1
),这将大大减少。