使用XHGui來測試PHP性能的教程
Profiling是一項用來觀察程序性能的技術(shù),非常適用于發(fā)現(xiàn)程序的瓶頸或者緊張的資源。Profiling能夠深入程序的內(nèi)部,展現(xiàn)request處理過程中每一部分代碼的性能;同時,也可以確定有問題的請求(request);對于有問題的請求,我們還可以確定性能問題發(fā)生在請求內(nèi)部的位置。對于PHP,我們有多種Profiling工具,本文主要集中在——XHGui,一款非常優(yōu)秀的工具。XHGui構(gòu)建在XHProf之上(XHProf由Facebook發(fā)布),但是對于剖析結(jié)果增加了更好的存儲,同時增加了更加良好的信息獲取接口。從這方面來說,XHGui更像是一個全新的工具。
XHGui已經(jīng)經(jīng)歷過幾個版本的迭代,但當(dāng)前版本提供了更加漂亮的用戶界面,并且使用MongoDB存儲其剖析結(jié)果。相比于前一版本來說,所有這些方面都是巨大的改進(jìn);因為,前一版本更像是開發(fā)者設(shè)計的,采用文件來保存數(shù)據(jù),使得收集的數(shù)據(jù)非常難以使用。XHGui 2013是一個非常全面的Profiling工具,無論是對管理人員來說還是對于開發(fā)者;與此同時,XHGui 2013被設(shè)計的足夠輕巧以便能夠在生產(chǎn)環(huán)境下運(yùn)行。
本文將一步一步演示程序的安裝,同時向你展現(xiàn)使用該工具可以收集的各方面信息。
第一步:安裝依賴
因為XHGui有一些依賴項,所以我們第一步就是解決這個問題。底下的所有的教程都是基于Ubuntu 13.04平臺的,當(dāng)然,你應(yīng)該可以把它們改編下并適用到到你自己的平臺上。目前而言,我們需要安裝MongoDB, PHP,并有一些安裝PECL拓展的能力。
首先,我們要安裝MongoDB,這邊有一些官方的安裝教程,你可以找到和你系統(tǒng)相關(guān)的細(xì)節(jié),但是現(xiàn)在我將通過簡單的通過APT來安裝:
aptitude install mongodb
通過這個方式獲取的MongoDB的版本可能不是最新的,因為這個產(chǎn)品的更新速度真的很快。但是,如果你想讓它保持一個很新的版本,你可以把MongoDB提供的庫添加到你的包管理器里,這樣你就能得到一個最新的了。
與此同時,我們還需要針對PHP的Mongo 驅(qū)動。在倉庫中該驅(qū)動的版本有點(diǎn)老,為了今天的演示,我們將從Pecl中進(jìn)行獲取。如果你的機(jī)器上沒有pecl命令,你可以通過下面的命令進(jìn)行安裝:
aptitude install php-pear
然后,我們通過下面的命令向PHP添加MongoDB的驅(qū)動程序:
pecl install mongo
為了完成安裝,最后我們需要在php.ini文件中新增加一行。但是,新版本的Ubuntu為配置PHP擴(kuò)展提供了一個新系統(tǒng),該系統(tǒng)更像Apache模塊安裝——將所有的配置保存在一個地方,然后創(chuàng)建一個符號鏈接以啟動配置。首先,我們創(chuàng)建一個文件來保存設(shè)置,盡管在本示例中僅需要在設(shè)置中新增一行以啟動擴(kuò)展。我們將其保存在文件/etc/php5/mods-available/mongo.ini,新增下面一行:
php5enmod mongo
pecl install xhprof-beta
命令行會再一次提示我們在php.ini新增一行。我們采用與上面一樣的方法,創(chuàng)建文件/etc/php5/mods-available/xhprof.ini,并在里面新增如下內(nèi)如:
extension=xhprof.so
安裝XHGui
XHGui本身主要由web頁面組成,它為XHProf擴(kuò)展收集的數(shù)據(jù)提供更加友好的界面。你可以從代碼庫GitHub repo克?。灰部梢灾苯酉螺dzip文件,然后進(jìn)行解壓縮。獲取程序之后,確定緩存目錄有足夠的權(quán)限以便web服務(wù)器有權(quán)限寫入文件。最后,運(yùn)行安裝腳本:
php install.php
這就是程序安裝所需的一切,并且會自動安裝一些依賴程序;如果發(fā)生異常,安裝程序也會給你提示。
我更喜歡將XHGui安裝在虛擬主機(jī)當(dāng)中;這需要.htaccess文件允許,也需要啟動RUL重寫。啟動URL重寫表明需要啟動mod_rewrite模塊,通過下面的命令:
a2enmod rewrite
(不要忘記重啟Apache)。如果一切順利,你可以正常訪問XHGui的URL并且可以看到如下內(nèi)容:
在虛擬主機(jī)中啟動XHGui
此時,我們希望啟動XHGui以便檢驗我們網(wǎng)站的性能。注意,性能測試最好在進(jìn)行任何優(yōu)化之前執(zhí)行一次,以便檢測優(yōu)化的效果。最簡單的方法是在虛擬主機(jī)中增加auto_prepend_file聲明,如下圖所示:
<VirtualHost *:80> ServerName example.local DocumentRoot /var/www/example/htdocs/ php_admin_value auto_prepend_file /var/www/xhgui/external/header.php <Directory /var/www/example/htdocs/> Options FollowSymLinks Indexes AllowOverride All </Directory> </VirtualHost>
一切就緒之后,你可以開始剖析網(wǎng)站的請求。XHGui只會剖析網(wǎng)站請求的1%,所以為了使XHGui獲取有意義的數(shù)據(jù),你需要讓XHGui運(yùn)行一段時間或者使用類似Apache Bench的測試工具批量提交一批請求。為什么在100個請求當(dāng)中XHGui只會剖析一個?因為XHGui的設(shè)計初衷就是足夠的輕巧以便在生產(chǎn)環(huán)境中使用,它不想對每一個請求產(chǎn)生額外的開銷,1%的采樣率已經(jīng)能夠為網(wǎng)站的總體流量提供較為清晰的概覽。
滿足數(shù)據(jù)
我使用測試虛擬機(jī)運(yùn)行本文所有的示例,采用Joind.in API作為測試代碼。為了產(chǎn)生一些流量,我將API測試案例運(yùn)行了幾遍。你也可以在一定負(fù)載的情況下收集數(shù)據(jù),所以你可以在壓力測試時使用XHGui,你甚至可以在上線站點(diǎn)中使用XHGui收集數(shù)據(jù)(聽起來很瘋狂,但是Facebook正式為了此應(yīng)用才開發(fā)了該工具)。在向應(yīng)用發(fā)送了一定的請求之后,重新訪問XHGui,現(xiàn)在它就已經(jīng)保存了一些數(shù)據(jù):
該圖向我們展示了XHGui為我們分析的每一個請求,最新的請求排在第一位,并且為每一個請求展示了一些額外信息。這些信息包括:
- URL:請求所訪問的URL
- Time:請求發(fā)起時間
- wtor: "Wall Time" –請求所經(jīng)歷的所有時間. 這是 "wall clock" time的簡稱,表示用戶等待請求完成所有的時間
- cpu:花費(fèi)在該請求上的CPU時間
- mu:該請求所消耗的內(nèi)存
- pmu:請求處理過程中所消耗的最大內(nèi)存
為了獲取每一遍請求("run")更為詳細(xì)的信息,你可以點(diǎn)擊每一個請求你感興趣的列。你可以點(diǎn)擊URL以便獲取該URL所有請求的詳細(xì)信息。無論哪種方法,你都可以獲取該請求更為詳細(xì)的信息:
這是一個非常長并且非常詳細(xì)的頁面,所以我引用了兩個截圖(如果展示所有的信息將需要5個截圖)。上面一幅圖的左邊部分展示了該請求相關(guān)的一些信息,以便幫助你跟蹤這些統(tǒng)計信息與哪些方面有關(guān);右邊的主要部分展示了最消耗時間的各部分以及在請求過程中每個函數(shù)調(diào)用所消耗的內(nèi)存。在圖的下方有一個主鍵以表明每一欄。
第二幅圖展示了該請求每一個組成部分更為詳細(xì)的信息。我們可以看到每一部分調(diào)用的次數(shù)以及時間消耗,還包括CPU和內(nèi)存信息。無論是inclusive還是exclusive信息都做了詳細(xì)的展示:exclusive表示僅僅是該方法調(diào)用所產(chǎn)生的消耗;inclusive不僅包括本函數(shù)所產(chǎn)生的消耗,還包括本函數(shù)調(diào)用的其他函數(shù)所產(chǎn)生的消耗。
XHGui另一個特性是“調(diào)用圖”(Callgraph),“調(diào)用圖”以生動的虛擬方式展示了時間是如何消耗的:
這很好的展示了函數(shù)調(diào)用的層次。最好的一點(diǎn)是,該圖是可交互的,你可以拖拽以更好的查看連接;你還可以用鼠標(biāo)滑過“圓環(huán)”(blob)以查看更多的信息。當(dāng)你與它交互時,他會很好玩的彈回和移動,這不是一個非常重要的特性但卻讓我感覺非常好玩。
理解數(shù)據(jù)
擁有大量的統(tǒng)計數(shù)據(jù)非常重要,但是你很難知道從哪里下手。對于一個性能不如預(yù)期的頁面采用如下步驟:首先,對每一個函數(shù)的exclusive CPU時間進(jìn)行排序,查看最消耗時間的函數(shù)列表。分析這些耗時的函數(shù)調(diào)用并進(jìn)行重構(gòu)和優(yōu)化。
一旦做出了修改,讓剖析工具再次檢驗新版本的程序,測試性能的改進(jìn)。XHGui內(nèi)置了完美的工具以比較兩次運(yùn)行;點(diǎn)擊詳細(xì)信息頁面右上角的“Compare this run"按鈕即可。該按鈕會向你展示該URL每一次測試的結(jié)果,從中選擇一個你要比較的對象。對你想比較的對象,點(diǎn)擊”compare“按鈕,XHGui將會轉(zhuǎn)向比較視圖,如下圖所示:
統(tǒng)計表格展示了新版和舊版統(tǒng)計信息的主要區(qū)別,包括每一個信息改動的實(shí)際數(shù)字以及百分比。上圖顯示,新版的請求等待時間僅僅為舊版的8%。統(tǒng)計表格詳細(xì)展示了每一個統(tǒng)計信息的改變,這些統(tǒng)計信息我們在”詳細(xì)信息“頁面能夠經(jīng)??吹?;你可以對任何一列進(jìn)行排序以便查找你感興趣的信息。
一旦你在某一方面成功的進(jìn)行了重構(gòu),查看詳細(xì)信息頁面(detail page)以檢查新版本的實(shí)際效果,然后挑選其他方面進(jìn)行優(yōu)化。嘗試對內(nèi)存使用或者exclusive wall time 進(jìn)行排序,以便挑選能夠最大限度提高應(yīng)用整體性能的函數(shù)進(jìn)行優(yōu)化。同時,不要忘記檢查調(diào)用的次數(shù),一個重復(fù)調(diào)用的函數(shù)經(jīng)過優(yōu)化之后能夠成倍的提高程序的性能。
最優(yōu)化方法
你很難在量化成果之前知道自己改善了多少,這就是為什么我們經(jīng)常在對一個應(yīng)用進(jìn)行優(yōu)化之前檢測它--不然你怎么知道自己是否真的優(yōu)化了它?我們也需要想想一組真實(shí)的數(shù)據(jù)應(yīng)該怎樣表示,不然,我們可能會朝著一個不可能到達(dá)的目標(biāo)前進(jìn)。一個很有用的方法是:盡力去尋找需要使用的最適合的數(shù)據(jù)結(jié)構(gòu)以及最小存儲空間。如果在你擅長的工作環(huán)境中,不能在半秒內(nèi)運(yùn)行一個“Hello world”程序,那么就別指望用同樣的工具構(gòu)建的網(wǎng)頁能有多好的表現(xiàn)。
上面的敘述并不是對編程框架(framework)的不敬;編程框架之所以存在是因為其方便使用、支持快速開發(fā)、容易維護(hù)。相比親自手工編寫代碼,編程框架在性能上的降低是我們綜合各方面進(jìn)行折中的結(jié)果。采用編程框架進(jìn)行應(yīng)用開發(fā)是能夠盡快上線的一種很好的方法,當(dāng)需要的時候,你可以使用Profiling工具分析并改進(jìn)程序的性能。例如,Zend Framework 1的很多模塊能夠提供非好強(qiáng)大的特性,但是并能非常低下;采用Profiling工具就能確定性能低下的部分并將它們進(jìn)行替換。其他所有的框架都有類似的問題,XHGui能夠向您展示問題的所在并檢查他們是否對你的程序產(chǎn)生了可量化的影響。
在你的程序之外,一些其他的策略對占領(lǐng)上風(fēng)或許遲早有用:
- 當(dāng)心非危險的慢速關(guān)聯(lián)函數(shù)(not-dangerously-slow-but-related functions)在一個頁面上露面。如果你的頁面在格式化要點(diǎn)處理的 view helper 中的一系列函數(shù)中花去了它時間的 50%(我承諾這是個假想的例子),那么你可能想要去研究重構(gòu)整個組件。
- 少做。嘗試移除特性,如果性能比它們重要。
- 當(dāng)心一個請求中生成但沒有在特殊的視圖中用到的內(nèi)容,或未改變卻被多次重新生成的內(nèi)容。
- 好的緩存策略。這將是關(guān)于它的另一篇文章,但是考慮用 PHP 中的一個 OpCode 緩存(從 PHP 5.5 起內(nèi)置),在你的 web 服務(wù)器前方添加一個反向代理,簡單地為那些不怎么經(jīng)常改變的內(nèi)容發(fā)送適當(dāng)?shù)木彺骖^。
- 暴力去耦合。如果有一個可怕的資源緊張的特殊功能,把它從你的 web 服務(wù)器上去掉?;蛟S它可以被異步處理,所以你的程序可以僅僅添加一個消息到隊列,或移動到另一個單獨(dú)的服務(wù)器并作為一個單獨(dú)的服務(wù)模型來訪問。無論哪種方式,分離將幫助減少你的 web 服務(wù)器的負(fù)載,同時啟用了有效的擴(kuò)展。
XHGui是你的朋友
XHGui安裝簡單、使用時如影隨形、很棒的輸出以至于可以拿到董事會議上進(jìn)行展示。它能識別出我們應(yīng)用中的錯誤,幫助我們確認(rèn)應(yīng)用真的起作用(或者沒有?。_@可能會經(jīng)歷一些重復(fù)的過程,不過,不管你之前有沒有用過XHProf、XHGui,我勸你花點(diǎn)時間在你的應(yīng)用上試試,你會對你的發(fā)現(xiàn)大吃一驚。
相關(guān)文章
PHP查詢并刪除數(shù)據(jù)庫多列重復(fù)數(shù)據(jù)的方法(利用數(shù)組函數(shù)實(shí)現(xiàn))
這篇文章主要介紹了PHP查詢并刪除數(shù)據(jù)庫多列重復(fù)數(shù)據(jù)的方法,利用數(shù)組函數(shù)實(shí)現(xiàn)該功能,涉及PHP數(shù)據(jù)庫操作的相關(guān)技巧,需要的朋友可以參考下2016-02-02『PHP』PHP截斷函數(shù)mb_substr()使用介紹
截斷文章標(biāo)題,控制在15個文字,接下來為大家講解下如何實(shí)現(xiàn)這個需求,感興趣的朋友可以參考下哈2013-04-04Php 構(gòu)造函數(shù)construct的前下劃線是雙的_
最近寫php的class時,總是碰到function non object的錯誤,知道是類沒有實(shí)例化,但就是不知道錯誤在哪里。2009-12-12MySql數(shù)據(jù)庫查詢結(jié)果用表格輸出PHP代碼示例
這篇文章主要介紹了MySql數(shù)據(jù)庫查詢結(jié)果用表格輸出PHP代碼示例,本文直接給出代碼示例,需要的朋友可以參考下2015-03-03