利用linux系統命令分析PHP程式

loophome發表於2015-09-28

除了使用xdebug或者xhprof等PHP擴充套件分析PHP程式之外,我們還可以使用linux的命令對PHP程式進行分析。當然,這樣也有一定缺陷,就是隻能分析CLI執行的PHP程式。

以下是將要分析的PHP指令碼

<?php
$num="1800";
$arr = array();
for($i=0;$i<20000;$i++){
        $arr[]= "{$i}";
}
sleep(5);
for($i=0;$i<3000;$i++){
        if(in_array($num,$arr)){
                continue;
        }
}


第一個命令:time

解析:linux下time命令可以獲取到一個程式的執行時間,包括程式的實際執行時間(real time),以及程式執行在使用者態的時間(user time)和核心態的時間(sys time)。

-bash-4.1# time php test.php 

real   0m5.675s    #實際時間(real time): 從command命令列開始執行到執行終止的消逝時間;
user    0m0.665s    #使用者CPU時間(user CPU time): 命令執行完成花費的使用者CPU時間,即命令在使用者態中執行時間總和;
sys     0m0.007s    #系統CPU時間(system CPU time): 命令執行完成花費的系統CPU時間,即命令在核心態中執行時間總和。

可以看到,sleep的5秒並沒有佔用到user和sys,也就是說,sleep並不佔用cpu

第二個命令:strace

解析:strace常用來跟蹤程式執行時的系統呼叫和所接收的訊號。 在Linux世界,程式不能直接訪問硬體裝置,當程式需要訪問硬體裝置(比如讀取磁碟檔案,接收網路資料等等)時,必須由使用者態模式切換至核心態模式,通 過系統呼叫訪問硬體裝置。strace可以跟蹤到一個程式產生的系統呼叫,包括引數,返回值,執行消耗的時間。

執行命令:

strace -ttt -o strace_result  php test.php

-ttt  參數列示微秒級輸出,以秒了表示時間

-o   參數列示將結果輸出到檔案中

1443442345.373206 munmap(0x3915200000, 2276448) = 0
1443442345.373250 munmap(0x7f24a0f34000, 2347568) = 0
1443442345.373291 munmap(0x7f24a0bf6000, 3397480) = 0
1443442345.373334 munmap(0x3914600000, 2275920) = 0
1443442345.373374 munmap(0x7f24a07ed000, 2113912) = 0
1443442345.373434 munmap(0x7f24a09f2000, 2109776) = 0
1443442345.373474 munmap(0x3914a00000, 2346240) = 0
1443442345.373516 munmap(0x3917e00000, 2201520) = 0
1443442345.374489 munmap(0x7f24a158a000, 323584) = 0
1443442345.374622 exit_group(0)         = ?
輸出結果中,每一行都是一個系統呼叫。

第三個命令:ltrace

解析:ltrace命令用來跟蹤程式呼叫庫函式的情況

-bash-4.1# ltrace -c php test.php
^C% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 55.32   97.979893         233    419223 strtol
 30.04   53.213711    53213711         1 __libc_start_main
  9.19   16.272251         305     53287 memcpy
  3.17    5.621030         279     20107 __ctype_b_loc
  1.74    3.074011         229     13392 malloc
  0.12    0.217684          83      2618 strlen
  0.12    0.205593       18690        11 dlopen
  0.11    0.194501          79      2445 __ctype_tolower_loc
  0.06    0.111315          82      1351 strrchr
  0.02    0.043957          80       545 calloc
  0.02    0.042310          81       521 free
  0.02    0.039427          83       475 strcasecmp
  0.01    0.025975          79       327 realloc
  0.01    0.022132       11066         2 getprotobyname
  0.01    0.016168          81       199 memset
  0.00    0.006055          82        73 strncasecmp
  0.00    0.004099          87        47 strchr
  0.00    0.003631          80        45 fileno
上面列出系統函式的呼叫次數和執行時間,其中發現strtol呼叫了40w多次。進行優化時,可以考慮從這方向去入手。

strtol是將字串轉化成long型,在程式碼中,僅有in_array這個函式實現這個操作(由於使用非嚴格匹配,in_array如果引數可以轉化成int型別,會使用int型別進行比較)

簡單修改了一下程式碼:if(in_array($num,$arr,true)){

再次執行:

% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 29.58   11.395604    11395604         1 __libc_start_main
 26.64   10.263876         192     53293 memcpy
 19.79    7.623026         379     20108 __ctype_b_loc
 13.17    5.075651         378     13393 malloc
  8.12    3.129727         223     14009 free
  0.83    0.319670          83      3832 strlen
  0.53    0.203854       18532        11 dlopen
  0.50    0.194224          79      2445 __ctype_tolower_loc
可以看到程式執行的時間大大縮短了。




相關文章