PHP 應用效能優化指南

沙袋發表於2017-05-11

程式設計師都喜歡最新的PHP 7,因為它使PHP成為執行最快的指令碼語言之一(參考PHP 7 vs HHVM 比較)。但是保持最佳效能不僅需要快速執行程式碼,更需要我們知道影響效能的問題點,以及這些問題的解決方案。本文涵蓋了保障PHP應用平穩高速執行的所有知識點,大量乾貨來襲,強烈建議收藏。

PHP簡史

PHP是由拉斯姆斯·勒多夫於1995年開始開發的。起初,它只是勒多夫為了要維護個人網頁,而用c語言開發的一些CGI工具程式集,我們從PHP這個縮寫最初的來源“Personal Home Page”(個人主頁)就可以看出這一點。然而,隨著勒多夫不斷地擴充它的功能,PHP逐漸成為了現在的“PHP:超文字前處理器”。

在過去的20年中,PHP的開發團隊一直致力於提升PHP的效能,最引人矚目的是於1999年引入的Zend語法直譯器引擎。2000年釋出的PHP 4,包含了一個內建的編譯器和執行器模型,使得PHP開始有能力開發動態的Web應用。2015年PHP釋出了里程碑式的版本PHP 7.0,極大的提升了Zend引擎的效能,並降低了PHP的整體記憶體使用率。截止到本文發稿為止,目前最新的PHP版本是7.1.4,有興趣的話可以看看這篇文章PHP7 新特性,改變變化

怎樣才算是高效能的PHP應用?

效能和速度不是一對同義詞。實現最佳效能通常需要在速度、準確性和可擴充套件性之間進行權衡。例如,在開發Web應用時,如果你優先考慮速度,你可能會編寫一個將所有內容都載入記憶體的指令碼,而如果從可擴充套件性出發,可能你就會編寫以塊為單位將資料載入記憶體的指令碼。

基於phpLens的研究,下圖展示了速度與可擴充套件性之間理論上的權衡關係。

紅線表示針對速度進行了優化的指令碼,藍線是可擴充套件性優先的指令碼。當併發連線數低時,紅線執行速度更快; 然而,隨著併發連線數量的增加,紅線變慢。當併發連線數上升時,藍線也減慢;然而,下降並不那麼劇烈,因此,在一定閾值後,速度優先的指令碼會比可擴充套件性優先的指令碼慢。然而,在現實當中,一些指令碼可能隨著執行環境的變化而表現出前後不同的效能差異。你需要仔細的觀察使用者的使用情況,以及應用的併發請求數量,來適時調整合適的優化策略。

PHP程式碼優化最佳實踐

編寫好的PHP程式碼是建立快速穩定Web應用的關鍵一步。從一開始就遵循一些最佳實踐技巧將節省後期填坑的時間。

1. 儘可能的使用PHP的內建方法

只要可以儘可能的使用PHP的內建方法,而不是自己編寫相同功能的方法。花點時間去熟悉和學習PHP的內建方法,不但可以幫助你更快的編寫程式碼,而且可以使你編寫的程式碼更高效的執行。

2. 使用Json替代xml

json_encode()json_decode() 等PHP的內建方法,執行速度都非常快,所有應該優先使用Json。如果你無法避免使用xml,那麼請務必使用正規表示式而不是DOM操作來進行解析。

3. 使用快取技術

Memcache特別適用於減少資料庫負載,而像APCOPcache這樣的位元組碼快取引擎在指令碼編譯時可節省執行時間。

4. 減少不必要的計算

當一個變數會被多次使用時,一開始就計算好,肯定要比每次使用時都計算一遍要更高效。

5. 使用isset()和empty()

與count()、strlen()和sizeof()函式相比,isset()empty()對於檢測一個變數是否為空等場景更加簡單和高效。

6. 減少不必要的類

如果你不打算重複使用一個類或者方法,那麼它就沒什麼存在的價值。而如果你必須要定義和使用一個類,則需要合理規劃類中的方法,對於不是特別公用的方法,儘量將他們放到子類中去,因為呼叫子類中的方法,比呼叫父類方法速度更快。

7. 在生產環境關閉用作除錯的相關程式碼及錯誤報告

開發時開啟錯誤報告,可以讓你避免很多潛藏的Bug,而一些除錯程式碼也有助於你定位Bug,但是當程式碼部署到生產環境後,這些錯誤報告和除錯程式碼會拖慢你的程式速度,而且將一些錯誤報告直接顯示給使用者,也具有相當的安全風險。因此,在生產環境請關閉它們。

8. 關閉資料庫連線

當使用完畢後,登出變數和關閉資料庫連線,可以釋放珍貴的記憶體資源。

9. 使用聚合函式減少資料庫查詢

查詢資料庫時,使用聚合函式,可以減少檢索資料庫的頻率,並且使程式執行的更快。

10. 使用強大的字串操作函式

舉個例子,str_replace()比preg_replace()要快,而strtr()函式則比str_replace()函式快四倍。

11. 儘量使用單引號

如果可能,儘量使用單引號替代雙引號。程式執行時,會檢查雙引號中的變數,這會拖慢程式的效能。

12. 嘗試使用恆等運算子

由於“===”僅檢查閉合範圍,因此比使用“==”進行比較速度更快。

PHP程式碼之外的效能瓶頸因素

優化程式碼當然能夠提高PHP的效能。但是,還有一些程式碼之外的因素也會成為PHP的效能瓶頸。這就是為什麼程式設計師需要了解程式碼部署的整個伺服器環境,這有助於他們在編寫程式碼時有一定的心理準備,並能夠在效能出現問題時,快速識別和定位效能瓶頸。以下是你遇到效能瓶頸時需要檢查的點。

1. 網路頻寬

如果網路頻寬不夠,其傳輸的總資料量將會受到嚴重影響,使其成為最明顯的效能瓶頸。

2. CPU

如果只是傳輸一些純靜態的HTML,則不需要消耗很多CPU資源,但是PHP畢竟建立的是動態的應用程式,根據應用的需要,你可能至少需要一臺具備多核處理器的伺服器來提升PHP程式碼的執行效率。

3. 共享記憶體

缺少共享記憶體可能會影響程式間通訊,從而影響程式效能。

4. 檔案系統

隨著時間推移,你的檔案系統可能會出現大量磁碟碎片。如果記憶體足夠,利用記憶體作為檔案快取可以加快磁碟的訪問速度。

5. 程式管理

檢查伺服器的程式,確保裡面沒有非必要的程式。移除哪些不需要的網路協議、病毒掃描軟體、郵件服務以及硬體驅動。將PHP程式碼執行在多執行緒模式,也能提高程式的響應時間。

6. 相關的其它服務

如果你的應用程式還依賴於一些外部服務,那這些外部服務的效能瓶頸也有可能拖慢你的應用。雖然這種情況下你能做的事情不多,但你仍然可以通過你這一邊的操作來減輕外部服務效能瓶頸對你的影響,例如切換到備用服務上等。

更多PHP效能優化建議

1. 發揮OPCache的優勢

由於預設情況下,PHP程式碼在執行時都會重新編譯為可執行的中間程式碼OPCode,因此可以及時看到修改的程式碼所帶來的變化,而不必頻繁的重啟PHP服務。不幸的是,如果每次在你的網站上執行時,都重新編譯相同的程式碼會嚴重影響伺服器的效能,這就是為什麼opcode快取或OPCache 非常有用。

OPCache是一個將編譯好的程式碼儲存到記憶體中的擴充套件。因此,下一次程式碼執行時,PHP將檢查時間戳和檔案大小,以確定原始檔是否已更改。如果沒有,則直接執行快取的程式碼。

下圖顯示了執行無快取的PHP應用程式,OPcache和eAccelerator(另一個PHP快取工具)三者的執行時間和記憶體使用情況的差異。

圖片來源: Prestashop

2. 識別資料庫響應延遲

如上所述,效能問題並不總是由程式碼引起的。大多數瓶頸都出現在應用程式必須訪問資源的時候。由於PHP應用程式的資料訪問層可能佔用最高90%的執行時間,因此你應該採取的第一步是檢視程式碼中訪問資料庫的所有例項。

確保開啟SQL的慢日誌,以幫助你識別和處理慢SQL,然後評估這些查詢的執行效率。如果你發現查詢過多,或者在單次執行過程中發現相同的查詢被多次進行,你可以通過減少資料庫訪問時間進行調整,從而提高應用程式的效能。

3. 清理檔案系統

清理檔案系統,並確保沒有使用檔案系統來儲存Session。最重要的是,請注意file_exists(),filesize()或filetime()等觸發檔案統計資訊的程式碼。將任何這些功能置於迴圈中可能會導致效能問題。

4. 監控外部API介面

大部分對外部系統有依賴關係的應用都會呼叫遠端API。雖然這些遠端API介面你無法直接控制,但你仍可以採取一些措施來減輕源自遠端API的效能問題。例如,你可以快取API輸出的資料,或者可以在後臺呼叫這些API。為API請求設定合理的超時時間,並且如果可能的話,隨時做好API沒有響應的情況下的顯示輸出。

5. 使用工具評估檢測你的PHP程式碼

使用OPcache和監控外部API介面應該足以使大多數應用程式執行順利;但是,如果你發現系統負載不斷增加,那麼可能需要使用工具來對你的PHP程式碼進行檢測評估。完整的PHP程式碼檢測評估雖然可能很耗時,但它可以為你提供有關應用程式效能的深入資訊。幸運的是,有幾個開源程式可以用於分析你的PHP程式碼,如Xdebug

監控PHP效能的重要性

如果你沒有做好準備,你的Web應用可能前一分鐘還在正常執行,但是下一分鐘,一波突然激增的流量就會導致你的應用程式崩潰。 當然,優化和重構總是需要時間、精力和資金,而且投入是否值得的也很難說。因此,做出明智決策的最佳方式是不斷收集資料

PHP效能監控軟體可以幫助你立即測量所做的任何更改的影響。當然,知道要監測什麼同樣重要。速度和記憶體使用被認為是效能的最佳指標,因為它們影響到頁面載入時間,這對Web應用程式至關重要。

雖然資料收集很重要,但是當你不需要監控系統時,你應該關閉監控系統,因為大量日誌同樣也會對效能造成影響。當然,這樣的日誌可以提供有關如何提高效能的有用資訊,因此你應該在高峰期間定期監控。

未來的PHP效能

PHP仍在不斷進化中,在目前正在開發的PHP 8版本中,最新的功能是即時編譯或JIT,它將可以為我們建立更快的Web應用。隨著技術的不斷進步,使用者的期望也隨之增加。因此,開發人員必須始終關注未來的變化。

在構建Web應用程式時,請記住,今年的工作可能在明年不起作用。你可能需要進行調整才能持續保持優秀的PHP效能。在開發過程中,應該持續重點關注如何構建適用於高併發場景的Web應用和網站,保證它們的高可用性。

相關文章