早些年,若是你知道有个 strace 命令,就很牛了,而如今你们基本都知道 strace 了,若是你遇到性能问题求助别人,十有八九会建议你用 strace 挂上去看看,不过当你挂上去了,看着满屏翻滚的字符,却十有八九看不出个因此然。本文经过一个简单的案例,向你展现一下在用 strace 诊断问题时的一些套路。php
以下真实案例,若有雷同,实属必然!让咱们看一台高负载服务器的 top 结果:shell
top服务器
技巧:运行 top 时,按「1」打开 CPU 列表,按「shift+p」以 CPU 排序。函数
在本例中你们很容易发现 CPU 主要是被若干个 PHP 进程占用了,同时 PHP 进程占用的比较多的内存,不过系统内存尚有结余,SWAP 也不严重,这并非问题主因。工具
不过在 CPU 列表中能看到 CPU 主要消耗在内核态「sy」,而不是用户态「us」,和咱们的经验不符。Linux 操做系统有不少用来跟踪程序行为的工具,内核态的函数调用跟踪用「strace」,用户态的函数调用跟踪用「ltrace」,因此这里咱们应该用「strace」:性能
shell> strace -p <PID>
不过若是直接用 strace 跟踪某个进程的话,那么等待你的每每是满屏翻滚的字符,想从这里看出问题的症结并非一件容易的事情,好在 strace 能够按操做汇总时间:this
shell> strace -cp <PID>
经过「c」选项用来汇总各个操做的总耗时,运行后的结果大概以下图所示:spa
strace -cp操作系统
很明显,咱们能看到 CPU 主要被 clone 操做消耗了,还能够单独跟踪一下 clone:orm
shell> strace -T -e clone -p <PID>
经过「T」选项能够获取操做实际消耗的时间,经过「e」选项能够跟踪某个操做:
strace -T -e clone -p
很明显,一个 clone 操做须要几百毫秒,至于 clone 的含义,参考 man 文档:
clone() creates a new process, in a manner similar to fork(2). It is actually a library function layered on top of the underlying clone() system call, hereinafter referred to as sys_clone. A description of sys_clone is given towards the end of this page.
Unlike fork(2), these calls allow the child process to share parts of its execution context with the calling process, such as the memory space, the table of file descriptors, and the table of signal handlers. (Note that on this manual page, “calling process” normally corresponds to “parent process”. But see the description of CLONE_PARENT below.)
简单来讲,就是建立一个新进程。那么在 PHP 里何时会出现此类系统调用呢?查询业务代码看到了 exec 函数,经过以下命令验证它确实会致使 clone 系统调用:
shell> strace -eclone php -r 'exec("ls");'
最后再考你们一个题:若是咱们用 strace 跟踪一个进程,输出结果不多,是否是说明进程很空闲?其实试试 ltrace,可能会发现别有洞天。记住有内核态和用户态之分。
https://huoding.com/2015/10/16/474