早些年,若是你知道有個 strace 命令,就很牛了,而如今你們基本都知道 strace 了,若是你遇到性能問題求助別人,十有八九會建議你用 strace 掛上去看看,不過當你掛上去了,看着滿屏翻滾的字符,卻十有八九看不出個因此然。本文經過一個簡單的案例,向你展現一下在用 strace 診斷問題時的一些套路。php
以下真實案例,若有雷同,實屬必然!讓咱們看一臺高負載服務器的 top 結果:shell
技巧:運行 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
很明顯,咱們能看到 CPU 主要被 clone 操做消耗了,還能夠單獨跟蹤一下 clone:orm
shell> strace -T -e clone -p <PID>
經過「T」選項能夠獲取操做實際消耗的時間,經過「e」選項能夠跟蹤某個操做:
很明顯,一個 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