KCacheGrind (下稱KCG)是一個性能數據分析工具,由德國工程師Josef Weidendorfer, Josef.Weidendorfer@gmx.de 開發並維護,具詳細信息可見: https://kcachegrind.github.io/html/Home.htmlphp
經過PHP-Xdebug擴展,咱們在debug時能夠生成代碼運行時的數據,而經過KCG對這些運行數據進行分析,能夠很直觀地經過各類方式,如圖形,列表等,看到每行代碼每一個函數所耗費的時間和資源,爲代碼性能優化提供依據。廢話很少說,看如何實現。html
1, 安裝KGCmysql
sudo apt-get install kcachegrind
kcachegrind -v Qt:4.8.7 KDE 開發平臺:4.14.16 KCachegrind:0.7.4kde
2, 安裝Xdebug,昨天的文章已經說過了,此處不贅述。git
3, 在PHP中配置Xdebuggithub
;xdebug.profiler_enable=on xdebug.profiler_enable_trigger=on xdebug.trace_output_dir="/home/c80k2/xdebug" xdebug.profiler_output_dir="/home/c80k2/xdebug/" xdebug.profiler_append=1 #append one file
和昨天同樣,咱們逐項地分析各配置的含義:sql
①xdebug.profiler_enable=on性能優化
Type: integer, Default value: 0bash
Enables Xdebug's profiler which creates files in the profile output directory. Those files can be read by KCacheGrind to visualize your data. This setting can not be set in your script with ini_set(). If you want to selectively enable the profiler, please set xdebug.profiler_enable_trigger to 1 instead of using this setting.cookie
容許Xdebug profiler會在指定的檔案輸出目錄中生成檔案文件. 那些檔案文件能夠用KCG來讀取並可視化你的數據。此設置不能夠在你的腳本中用 ini_set()方法進行設置。若是你想有選擇性地容許這個profiler,請將 xdebug.profiler_enable_trigger 設置爲1,而不要用此項設置。(意思是,若是你只想針對特定的php請求或運行生成檔案文件時,用trigger設置。若是你用了本設置,則xdebug會對每個php請求或運行生成檔案文件。)app
②xdebug.profiler_enable_trigger=on
Type: integer, Default value: 0
When this setting is set to 1, you can trigger the generation of profiler files by using the XDEBUG_PROFILE GET/POST parameter, or set a cookie with the name XDEBUG_PROFILE. This will then write the profiler data to defined directory. In order to prevent the profiler to generate profile files for each request, you need to set xdebug.profiler_enable to 0. Access to the trigger itself can be configured through xdebug.profiler_enable_trigger_value.
當此項設爲1時,你能夠經過使用XDEBUG_PROFILE GET/POST請求參數(即在GET/POST請求中加入一個名爲XDEBUG_PROFILE的參數,值爲1)或者經過設置一個名字爲XDEBUG_PROFILE的cookie 來啓動檔案文件的生成。此時將會在預先設置的目錄中生成檔案文件。爲了防止profiler對每個請求都生成檔案文件,你須要將 xdebug.profiler_enable 設置爲0。是否使用triggle自己能夠經過 xdebug.profiler_enable_trigger_value進行配置。
③xdebug.profiler_enable_trigger_value
Type: string, Default value: "", Introduced in Xdebug >= 2.3
This setting can be used to restrict who can make use of the XDEBUG_PROFILE functionality as outlined in xdebug.profiler_enable_trigger. When changed from its default value of an empty string, the value of the cookie, GET or POST argument needs to match the shared secret set with this setting in order for the profiler to start.
此項設置能夠用來約束哪些人可使用 在xdebug.profiler_enable_trigger規劃的 XDEBUG_PROFILE 功能。當將它的空字符串默認值改變以後,此cookie的值,GET或POST須要和此項設置去匹配這個共享的祕密設置,以便讓profiler啓動。
④xdebug.trace_output_dir=''
Type: string, Default value: /tmp
The directory where the tracing files will be written to, make sure that the user who the PHP will be running as has write permissions to that directory.
軌跡文件將被寫入的目錄路徑,確保PHP運行用戶對此目錄擁有寫權限。
⑤xdebug.profiler_output_dir=''
Type: string, Default value: /tmp
The directory where the profiler output will be written to, make sure that the user who the PHP will be running as has write permissions to that directory. This setting can not be set in your script with ini_set().
檔案文件將被寫入的目錄路徑,,確保PHP運行用戶對此目錄擁有寫權限。此設置不能在你的腳本中經過ini_set()方法進行設置。
⑥xdebug.profiler_append=1
Type: integer, Default value: 0
When this setting is set to 1, profiler files will not be overwritten when a new request would map to the same file (depending on the xdebug.profiler_output_name setting. Instead the file will be appended to with the new profile.
當此項設爲1時,當有一個新請求的檔案文件映射到相同的(已存在的)檔案文件時,該檔案文件講不會被重寫(重寫在這裏的意思是:清空文件原來的內容並寫入新的內容),而是會將新內容追加到原文件內容的後面。(這取決於 xdebug.profiler_output_name 配置。相應地 原文件將會附加到新文件。)
⑦xdebug.profiler_output_name
Type: string, Default value: cachegrind.out.%p
This setting determines the name of the file that is used to dump traces into. The setting specifies the format with format specifiers, very similar to sprintf() and strftime(). There are several format specifiers that can be used to format the file name.
See the xdebug.trace_output_name documentation for the supported specifiers.
此項設置決定了寫入運行軌跡的檔案文件的名稱。它用格式生成器規定了文件名稱的格式,和 sprintf()及strftime()方法很是類似。有好幾個格式生成器可用來格式化文件名稱。
以上就是xdebug在php中的配置。完成後,重啓php,咱們就能夠開始用KGC來分析檔案文件了.
5, KGC分析
咱們能夠先用一個請求來生成檔案文件,以下圖:
而後在輸出目錄中能夠看到:
c80k2@c80k2-Vostro-3667❯~/xdebug$ ls -al 總用量 1700 drwxrwxrwx 2 c80k2 c80k2 4096 3月 28 11:38 . drwxr-xr-x 69 c80k2 c80k2 4096 3月 28 11:37 .. -rw-r--r-- 1 www-data www-data 1731090 3月 28 11:38 cachegrind.out.12653
已經生成了一個檔案文件。
打開KGC
kcachegrind
看到如下圖形化界面
打開檔案文件
點 自身 ,能夠看到按照 開銷 進行倒序排列,咱們選擇其中的一個不是系統的方法->所有調用方
能夠看到資源消耗比例以下:
其中的select()方法
咱們再進到代碼中查看
... else if ($echengHasContact) { $param =array(); $param['where']['equal']['uid'] = $uid; $param['where']['equal']['resume_id'] = $resumeId; //$res = array_pop($this->dao('resume/Dao_resume_view_history')->select($param)); $res = array_pop($this->dao('resume/Dao_resume_has_read')->select($param)); ...
從數據表中查詢記錄,一個很普通的DB操做,咱們來分析一下爲何它消耗了不少資源。
第一反應是,索引。查看錶結構。
mysql> show create table resume_has_read; +-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | resume_has_read | CREATE TABLE `resume_has_read` ( `id` int(11) NOT NULL AUTO_INCREMENT, `uid` int(11) NOT NULL DEFAULT '0' COMMENT '用戶UID', `position_id` int(11) NOT NULL DEFAULT '0' COMMENT '職位ID', `resume_id` int(11) NOT NULL DEFAULT '0' COMMENT '簡歷ID', `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '簡歷類型', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=176715 DEFAULT CHARSET=utf8 COMMENT='簡歷是否被查看' |
能夠看到,沒有索引。這固然會消耗不少資源。
從另外一個視角來看,一個很經常使用的接口,兜兜轉轉,居然調用了600+個方法,可是主要的消耗仍是在DB操做和gearman服務中。
這就給咱們進行代碼優化的方向。