1. 程式人生 > >php程式碼優化方法,加速執行速度的技巧總結

php程式碼優化方法,加速執行速度的技巧總結

1. 儘量採用大量的PHP內建函式。
2. echo 比 print 快。
3. 不要把方法細分得過多,仔細想想你真正打算重用的是哪些程式碼?
4. 在執行for迴圈之前確定最大迴圈數,不要每迴圈一次都計算最大值。
5. 登出那些不用的變數尤其是大陣列,以便釋放記憶體。
6. 並非要用類實現所有的資料結構,陣列也很有用。
7. $row['id']的效率是$row[id]的7倍。
8. 在包含檔案時使用完整路徑,解析作業系統路徑所需的時間會更少。
9. 如果你想知道指令碼開始執行(譯註:即伺服器端收到客戶端請求)的時刻,使用$_SERVER[‘REQUEST_TIME’]要好於time()。
10. 檢查是否能用strncasecmp,strpbrk,stripos函式代替正則表示式完成相同功能。

11. str_replace函式比preg_replace函式快,但strtr函式的效率是str_replace函式的四倍。
12. 如果一個字串替換函式,可接受陣列或字元作為引數,並且引數長度不太長,那麼可以考慮額外寫一段替換程式碼,使得每次傳遞引數是一個字元,而不是隻寫一行程式碼接受陣列作為查詢和替換的引數。
13. 使用選擇分支語句(譯註:即switch case)好於使用多個if,else if語句。
14. 用@遮蔽錯誤訊息的做法非常低效。
15. 開啟apache的mod_deflate模組。
16. 資料庫連線當使用完畢時應關掉。
18. 錯誤訊息代價昂貴。
19. 儘量不要在for迴圈中使用函式,比如for ($x=0; $x < count($array); $x)每迴圈一次都會呼叫count()函式。

20. 在方法中遞增區域性變數,速度是最快的。幾乎與在函式中呼叫區域性變數的速度相當。
21. 遞增一個全域性變數要比遞增一個區域性變數慢2倍。
22. 遞增一個物件屬性(如:$this->prop++)要比遞增一個區域性變數慢3倍。
23. 遞增一個未預定義的區域性變數要比遞增一個預定義的區域性變數慢9至10倍。
24. 僅定義一個區域性變數而沒在函式中呼叫它,同樣會減慢速度(其程度相當於遞增一個區域性變數)。PHP大概會檢檢視是否存在全域性變數。
25. 方法呼叫看來與類中定義的方法的數量無關,因為我(在測試方法之前和之後都)添加了10個方法,但效能上沒有變化。
26. 派生類中的方法執行起來要快於在基類中定義的同樣的方法。

27. 呼叫帶有一個引數的空函式,其花費的時間相當於執行7至8次的區域性變數遞增操作。類似的方法呼叫所花費的時間接近於15次的區域性變數遞增操作。
28. 用單引號代替雙引號來包含字串,這樣做會更快一些。因為PHP會在雙引號包圍的字串中搜尋變數,單引號則不會。當然,只有當你不需要在字串中包含變數時才可以這麼做。
29. 用echo 輸出多個字串時,用逗號代替句點來分隔字串,速度更快。
30. Apache解析一個PHP指令碼的時間要比解析一個靜態HTML頁面慢2至10倍。儘量多用靜態HTML頁面,少用指令碼。
31. 除非指令碼可以快取,否則每次呼叫時都會重新編譯一次。引入一套PHP快取機制通常可以提升25%至100%的效能,以免除編譯開銷。
32. 儘量做快取,可使用memcached。memcached是一款高效能的記憶體物件快取系統,可用來加速動態Web應用程式,減輕資料庫負載。對運算碼(OP code)的快取很有用,使得指令碼不必為每個請求做重新編譯。
33. 當操作字串並需要檢驗其長度是否滿足某種要求時,你想當然地會使用strlen()函式。此函式執行起來相當快,因為它不做任何計算,只返回在zval 結構(C的內建資料結構,用於儲存PHP變數)中儲存的已知字串長度。但是,由於strlen()是函式,多多少少會有些慢,因為函式呼叫會經過諸多步驟,如字母小寫化(譯註:指函式名小寫化,PHP不區分函式名大小寫)、雜湊查詢,會跟隨被呼叫的函式一起執行。在某些情況下,你可以使用isset() 技巧加速執行你的程式碼。

Ex.(舉例如下)
[phpif (strlen($foo) < 5) { echo "Foo is too short"; }[/php]
vs.(與下面的技巧做比較)
檢視原始碼列印幫助1if (!isset($foo{5})) { echo "Foo is too short"; }

呼叫isset()恰巧比strlen()快,因為與後者不同的是,isset()作為一種語言結構,意味著它的執行不需要函式查詢和字母小寫化。也就是說,實際上在檢驗字串長度的頂層程式碼中你沒有花太多開銷。

34. 當執行變數$i的遞增或遞減時,$i++會比++$i慢一些。這種差異是PHP特有的,並不適用於其他語言,所以請不要修改你的C或Java程式碼並指望它們能立即變快,沒用的。++$i更快是因為它只需要3條指令(opcodes),$i++則需要4條指令。後置遞增實際上會產生一個臨時變數,這個臨時變數隨後被遞增。而前置遞增直接在原值上遞增。這是最優化處理的一種,正如Zend的PHP優化器所作的那樣。牢記這個優化處理不失為一個好主意,因為並不是所有的指令優化器都會做同樣的優化處理,並且存在大量沒有裝配指令優化器的網際網路服務提供商(ISPs)和伺服器。

35. 並不是事必面向物件(OOP),面向物件往往開銷很大,每個方法和物件呼叫都會消耗很多記憶體。
36. 如果在程式碼中存在大量耗時的函式,你可以考慮用C擴充套件的方式實現它們。
37. 評估檢驗(profile)你的程式碼。檢驗器會告訴你,程式碼的哪些部分消耗了多少時間。Xdebug偵錯程式包含了檢驗程式,評估檢驗總體上可以顯示出程式碼的瓶頸。
38. mod_zip可作為Apache模組,用來即時壓縮你的資料,並可讓資料傳輸量降低80%

PHP是一種執行起來非常迅速的程式語言,但是比起僅僅優化程式碼來說仍然值得優化PHP本身。
本文我們將根據一些實效闡述為什麼優化PHP本身要比優化程式碼來的更貼切,以及為什麼需要理解根據PHP在你的伺服器上其他相關子系統的表現找出瓶頸並修復之。與此同時,我們也提到了如何優化您的PHP程式碼來讓他們擁有更快的執行速度。

獲得高效能

當我們談及好的效能,往往不僅僅是指您的PHP程式碼執行起來有多快。效能是一套在可量化評測和速度之間取出的平衡。僅僅依靠使用更少資源的程式碼執行起來也許比在快取記憶體中之行的程式碼更慢,並且相同的一組(在高速緩衝中執行的)程式碼可以在同時併發執行在一臺Web伺服器上。
在下面的例子中,A.php算作一位儘可能跑得快的賽跑選手,而B.php是一個幾乎可以以同一慢速永遠跑下去的馬拉松選手。輕負荷情況下,A.php可以充分的快,但是當流量增加後,B.php的效能表現將僅僅降低一點點而A.php會垮掉。
讓我們來通過一個事實來驗證此說法更深遠的本質意義。假設我們需要讀取一個250K的檔案並生成一個關於此檔案的HTML概要。我們寫了兩個指令碼來做同樣一件事:hare.php將一次性讀取整個檔案到記憶體中,然後一步執行到位;而tortoise.php每次只讀取檔案的一行,並且決不超過內容容量。結果Tortoise.php因為多次讀寫需要更多的系統迴應而慢得多。”
程式每執行一次,hare.php需要0.04秒CPU執行時間和10Mb的記憶體,而tortoise.php需要0.06秒CPU執行時間和5Mb 的記憶體。伺服器共有100Mb實際記憶體容量並且其CPU有99%是空閒的。我們同時假定執行這樣一個簡單事件不產生記憶體碎片。
當有10各程式併發執行時,hare.php將發生記憶體溢位(10 ×10 = 100)。與此同時,tortoise.php仍將有50Mb空餘記憶體可用!11個程式併發執行將使hare.php徹底“潰敗”因為它開始需要使用虛擬記憶體——執行速度有可能降低到其常規速度的一半以下;而且現在每一個單獨程式程序需要0.08秒CPU執行時間。而此期間,tortoise.php仍舊執行在其常規CPU執行時間——0.06秒!

以下表格中,執行得更快的PHP指令碼使用粗體區分開來:
[/php]
如您在上例中看到的,獲得更好的效能不再僅僅是寫出執行起來更快的PHP程式。高效能PHP表現需要對底層硬體知識以及作業系統、軟體支援如Web伺服器、資料庫等有一個良好認識和理解。

瓶頸

以上兩個例子讓我們看到了(效能)下降的瓶頸所在。當擁有無限大容量的記憶體時,hare.php的確是始終比tortoise.php快。但是,僅僅認為記憶體是PHP整體效能的瓶頸所在顯得過於單純——實際上遠不止這些:
(a) 網路
你的網路有可能是最大的瓶頸所在。如果你有10M的頻寬——最多你只能獲得1M/秒的傳輸速度。如果假設每個PHP頁為30k,那麼每秒僅僅只傳輸 33頁就將使你的網路頻寬達到飽和。更多導致瓶頸產生的因素包括頻繁訪問低速DNS,或者網路裝置僅能獲得十分有限的儲存。
(b) CPU
如果你監視一下你的CPU負荷情況,傳送一個純靜態HTML頁面並不會增加CPU負擔——就像我們以上提到的,此時瓶頸在於網路。當然啦,對於由 PHP生成的複雜動態頁面,你的CPU速度自然將成為限制因素之一。擁有包含多個CPU的伺服器或者一個伺服器陣列將減輕因CPU帶來的影響。
(c) 共享儲存
共享儲存主要在通訊程序中發揮作用,或者是用於儲存公共資源(比如多個CPU間的快取資料或程式碼)。如果共享儲存分配不足,同樣將導致瓶頸的發生。
(d) 檔案系統
訪問硬碟的速度至少比直接讀取記憶體要慢50到100倍。使用快取記憶體將使情況有所好轉。然而低記憶體空間將適用於檔案緩衝的記憶體(通常稱為虛擬記憶體)空間減少,進而導致整體效能下降。虛擬記憶體容易產生大量檔案碎片,導致訪問硬碟速度下降。在Unix系統上使用大量連結標記同樣也會石訪問硬碟的速度下降。預設Linux安裝模式下的預設硬碟訪問設定也是很不被看好的,因為它是為了相容性而不是速度。必要時請使用hdparm命令來更改Linux硬碟配置。
(e) 程序管理
在某些作業系統上(比如說Windows系統)建立一個新的程序是很緩慢的操作。這意味著在這些作業系統上作涉及到程序建立的CGI應用會慢許多。這種時候在多程序模式下執行PHP將會有所改善。(注意:老版本PHP尚不支援多程序模式)
應避免你的伺服器產生過多的無效程序。舉個例子,如果你的伺服器是純Web服務,需關閉(設定是不安裝)X-Windows視窗系統。Windows系統上,應禁用微軟快速搜尋(Office的一部分)和第三方屏保程式(通常會需要100%的CPU利用)。
有些程式你可以考慮刪除包括一些不常用的網路協議、郵件服務、病毒掃描、(滑鼠,紅外線埠)驅動程式等。Unix系統上,假定你通過SSH訪問你的伺服器,那麼你可以考慮去除:
telnetd,inetd,atd,ftpd,lpd,sambad模組
用於收取郵件的sendmail模組
NFS的對映表
xfs,fvwm,xinit,X
你也可以通過修改啟動指令碼(其路徑通常位於/etc/init* 或 /etc/rc*/init*)來實現禁用不同的啟動程式。
也可以檢查一下定期處理任務安排是否合理,看是否可以在伺服器空閒期執行。
(f) 連線到其他伺服器
如果你的伺服器需要其他伺服器提供的服務,此時有可能是其他伺服器產生了瓶頸。最常見的就是一個很慢的執行諸多複雜查詢的資料庫伺服器服務於很多其他伺服器。