摘要:怎樣才算是高性能的應(yīng)用性能和速度不是一對(duì)同義詞。紅線表示針對(duì)速度進(jìn)行了優(yōu)化的腳本,藍(lán)線是可擴(kuò)展性優(yōu)先的腳本。將任何這些功能置于循環(huán)中可能會(huì)導(dǎo)致性能問題。完整的代碼檢測評(píng)估雖然可能很耗時(shí),但它可以為你提供有關(guān)應(yīng)用程序性能的深入信息。
程序員都喜歡最新的PHP 7,因?yàn)樗筆HP成為執(zhí)行最快的腳本語言之一(參考PHP 7 vs HHVM 比較)。但是保持最佳性能不僅需要快速執(zhí)行代碼,更需要我們知道影響性能的問題點(diǎn),以及這些問題的解決方案。本文涵蓋了保障PHP應(yīng)用平穩(wěn)高速運(yùn)行的所有知識(shí)點(diǎn),大量干貨來襲,強(qiáng)烈建議收藏。
PHP是由拉斯姆斯·勒多夫于1995年開始開發(fā)的。起初,它只是勒多夫?yàn)榱艘S護(hù)個(gè)人網(wǎng)頁,而用c語言開發(fā)的一些CGI工具程序集,我們從PHP這個(gè)縮寫最初的來源“Personal Home Page”(個(gè)人主頁)就可以看出這一點(diǎn)。然而,隨著勒多夫不斷地?cái)U(kuò)充它的功能,PHP逐漸成為了現(xiàn)在的“PHP:超文本預(yù)處理器”。
在過去的20年中,PHP的開發(fā)團(tuán)隊(duì)一直致力于提升PHP的性能,最引人矚目的是于1999年引入的Zend語法解釋器引擎。2000年發(fā)布的PHP 4,包含了一個(gè)內(nèi)建的編譯器和執(zhí)行器模型,使得PHP開始有能力開發(fā)動(dòng)態(tài)的Web應(yīng)用。2015年P(guān)HP發(fā)布了里程碑式的版本PHP 7.0,極大的提升了Zend引擎的性能,并降低了PHP的整體內(nèi)存使用率。截止到本文發(fā)稿為止,目前最新的PHP版本是7.1.4,有興趣的話可以看看這篇文章PHP7 新特性,改變變化。
怎樣才算是高性能的PHP應(yīng)用?性能和速度不是一對(duì)同義詞。實(shí)現(xiàn)最佳性能通常需要在速度、準(zhǔn)確性和可擴(kuò)展性之間進(jìn)行權(quán)衡。例如,在開發(fā)Web應(yīng)用時(shí),如果你優(yōu)先考慮速度,你可能會(huì)編寫一個(gè)將所有內(nèi)容都載入內(nèi)存的腳本,而如果從可擴(kuò)展性出發(fā),可能你就會(huì)編寫以塊為單位將數(shù)據(jù)載入內(nèi)存的腳本。
基于phpLens的研究,下圖展示了速度與可擴(kuò)展性之間理論上的權(quán)衡關(guān)系。
紅線表示針對(duì)速度進(jìn)行了優(yōu)化的腳本,藍(lán)線是可擴(kuò)展性優(yōu)先的腳本。當(dāng)并發(fā)連接數(shù)低時(shí),紅線運(yùn)行速度更快; 然而,隨著并發(fā)連接數(shù)量的增加,紅線變慢。當(dāng)并發(fā)連接數(shù)上升時(shí),藍(lán)線也減慢;然而,下降并不那么劇烈,因此,在一定閾值后,速度優(yōu)先的腳本會(huì)比可擴(kuò)展性優(yōu)先的腳本慢。然而,在現(xiàn)實(shí)當(dāng)中,一些腳本可能隨著運(yùn)行環(huán)境的變化而表現(xiàn)出前后不同的性能差異。你需要仔細(xì)的觀察用戶的使用情況,以及應(yīng)用的并發(fā)請(qǐng)求數(shù)量,來適時(shí)調(diào)整合適的優(yōu)化策略。
PHP代碼優(yōu)化最佳實(shí)踐編寫好的PHP代碼是創(chuàng)建快速穩(wěn)定Web應(yīng)用的關(guān)鍵一步。從一開始就遵循一些最佳實(shí)踐技巧將節(jié)省后期填坑的時(shí)間。
1. 盡可能的使用PHP的內(nèi)置方法只要可以盡可能的使用PHP的內(nèi)置方法,而不是自己編寫相同功能的方法。花點(diǎn)時(shí)間去熟悉和學(xué)習(xí)PHP的內(nèi)置方法,不但可以幫助你更快的編寫代碼,而且可以使你編寫的代碼更高效的運(yùn)行。
2. 使用Json替代xmljson_encode()和json_decode() 等PHP的內(nèi)置方法,運(yùn)行速度都非常快,所有應(yīng)該優(yōu)先使用Json。如果你無法避免使用xml,那么請(qǐng)務(wù)必使用正則表達(dá)式而不是DOM操作來進(jìn)行解析。
3. 使用緩存技術(shù)Memcache特別適用于減少數(shù)據(jù)庫負(fù)載,而像APC或OPcache這樣的字節(jié)碼緩存引擎在腳本編譯時(shí)可節(jié)省執(zhí)行時(shí)間。
4. 減少不必要的計(jì)算當(dāng)一個(gè)變量會(huì)被多次使用時(shí),一開始就計(jì)算好,肯定要比每次使用時(shí)都計(jì)算一遍要更高效。
5. 使用isset()和empty()與count()、strlen()和sizeof()函數(shù)相比,isset()和empty()對(duì)于檢測一個(gè)變量是否為空等場景更加簡單和高效。
6. 減少不必要的類如果你不打算重復(fù)使用一個(gè)類或者方法,那么它就沒什么存在的價(jià)值。而如果你必須要定義和使用一個(gè)類,則需要合理規(guī)劃類中的方法,對(duì)于不是特別公用的方法,盡量將他們放到子類中去,因?yàn)檎{(diào)用子類中的方法,比調(diào)用父類方法速度更快。
7. 在生產(chǎn)環(huán)境關(guān)閉用作調(diào)試的相關(guān)代碼及錯(cuò)誤報(bào)告開發(fā)時(shí)打開錯(cuò)誤報(bào)告,可以讓你避免很多潛藏的Bug,而一些調(diào)試代碼也有助于你定位Bug,但是當(dāng)代碼部署到生產(chǎn)環(huán)境后,這些錯(cuò)誤報(bào)告和調(diào)試代碼會(huì)拖慢你的程序速度,而且將一些錯(cuò)誤報(bào)告直接顯示給用戶,也具有相當(dāng)?shù)陌踩L(fēng)險(xiǎn)。因此,在生產(chǎn)環(huán)境請(qǐng)關(guān)閉它們。
8. 關(guān)閉數(shù)據(jù)庫連接當(dāng)使用完畢后,注銷變量和關(guān)閉數(shù)據(jù)庫連接,可以釋放珍貴的內(nèi)存資源。
9. 使用聚合函數(shù)減少數(shù)據(jù)庫查詢查詢數(shù)據(jù)庫時(shí),使用聚合函數(shù),可以減少檢索數(shù)據(jù)庫的頻率,并且使程序運(yùn)行的更快。
10. 使用強(qiáng)大的字符串操作函數(shù)舉個(gè)例子,str_replace()比preg_replace()要快,而strtr()函數(shù)則比str_replace()函數(shù)快四倍。
11. 盡量使用單引號(hào)如果可能,盡量使用單引號(hào)替代雙引號(hào)。程序運(yùn)行時(shí),會(huì)檢查雙引號(hào)中的變量,這會(huì)拖慢程序的性能。
12. 嘗試使用恒等運(yùn)算符由于“===”僅檢查閉合范圍,因此比使用“==”進(jìn)行比較速度更快。
PHP代碼之外的性能瓶頸因素優(yōu)化代碼當(dāng)然能夠提高PHP的性能。但是,還有一些代碼之外的因素也會(huì)成為PHP的性能瓶頸。這就是為什么程序員需要了解代碼部署的整個(gè)服務(wù)器環(huán)境,這有助于他們?cè)诰帉懘a時(shí)有一定的心理準(zhǔn)備,并能夠在性能出現(xiàn)問題時(shí),快速識(shí)別和定位性能瓶頸。以下是你遇到性能瓶頸時(shí)需要檢查的點(diǎn)。
1. 網(wǎng)絡(luò)帶寬如果網(wǎng)絡(luò)帶寬不夠,其傳輸?shù)目倲?shù)據(jù)量將會(huì)受到嚴(yán)重影響,使其成為最明顯的性能瓶頸。
2. CPU如果只是傳輸一些純靜態(tài)的HTML,則不需要消耗很多CPU資源,但是PHP畢竟創(chuàng)建的是動(dòng)態(tài)的應(yīng)用程序,根據(jù)應(yīng)用的需要,你可能至少需要一臺(tái)具備多核處理器的服務(wù)器來提升PHP代碼的運(yùn)行效率。
3. 共享內(nèi)存缺少共享內(nèi)存可能會(huì)影響進(jìn)程間通信,從而影響程序性能。
4. 文件系統(tǒng)隨著時(shí)間推移,你的文件系統(tǒng)可能會(huì)出現(xiàn)大量磁盤碎片。如果內(nèi)存足夠,利用內(nèi)存作為文件緩存可以加快磁盤的訪問速度。
5. 進(jìn)程管理檢查服務(wù)器的進(jìn)程,確保里面沒有非必要的進(jìn)程。移除哪些不需要的網(wǎng)絡(luò)協(xié)議、病毒掃描軟件、郵件服務(wù)以及硬件驅(qū)動(dòng)。將PHP代碼運(yùn)行在多線程模式,也能提高程序的響應(yīng)時(shí)間。
6. 相關(guān)的其它服務(wù)如果你的應(yīng)用程序還依賴于一些外部服務(wù),那這些外部服務(wù)的性能瓶頸也有可能拖慢你的應(yīng)用。雖然這種情況下你能做的事情不多,但你仍然可以通過你這一邊的操作來減輕外部服務(wù)性能瓶頸對(duì)你的影響,例如切換到備用服務(wù)上等。
更多PHP性能優(yōu)化建議 1. 發(fā)揮OPCache的優(yōu)勢由于默認(rèn)情況下,PHP代碼在執(zhí)行時(shí)都會(huì)重新編譯為可執(zhí)行的中間代碼OPCode,因此可以及時(shí)看到修改的代碼所帶來的變化,而不必頻繁的重啟PHP服務(wù)。不幸的是,如果每次在你的網(wǎng)站上運(yùn)行時(shí),都重新編譯相同的代碼會(huì)嚴(yán)重影響服務(wù)器的性能,這就是為什么opcode緩存或OPCache 非常有用。
OPCache是一個(gè)將編譯好的代碼保存到內(nèi)存中的擴(kuò)展。因此,下一次代碼執(zhí)行時(shí),PHP將檢查時(shí)間戳和文件大小,以確定源文件是否已更改。如果沒有,則直接運(yùn)行緩存的代碼。
下圖顯示了運(yùn)行無緩存的PHP應(yīng)用程序,OPcache和eAccelerator(另一個(gè)PHP緩存工具)三者的執(zhí)行時(shí)間和內(nèi)存使用情況的差異。
如上所述,性能問題并不總是由代碼引起的。大多數(shù)瓶頸都出現(xiàn)在應(yīng)用程序必須訪問資源的時(shí)候。由于PHP應(yīng)用程序的數(shù)據(jù)訪問層可能占用最高90%的執(zhí)行時(shí)間,因此你應(yīng)該采取的第一步是查看代碼中訪問數(shù)據(jù)庫的所有實(shí)例。
確保打開SQL的慢日志,以幫助你識(shí)別和處理慢SQL,然后評(píng)估這些查詢的執(zhí)行效率。如果你發(fā)現(xiàn)查詢過多,或者在單次執(zhí)行過程中發(fā)現(xiàn)相同的查詢被多次進(jìn)行,你可以通過減少數(shù)據(jù)庫訪問時(shí)間進(jìn)行調(diào)整,從而提高應(yīng)用程序的性能。
3. 清理文件系統(tǒng)清理文件系統(tǒng),并確保沒有使用文件系統(tǒng)來存儲(chǔ)Session。最重要的是,請(qǐng)注意file_exists(),filesize()或filetime()等觸發(fā)文件統(tǒng)計(jì)信息的代碼。將任何這些功能置于循環(huán)中可能會(huì)導(dǎo)致性能問題。
4. 監(jiān)控外部API接口大部分對(duì)外部系統(tǒng)有依賴關(guān)系的應(yīng)用都會(huì)調(diào)用遠(yuǎn)程API。雖然這些遠(yuǎn)程API接口你無法直接控制,但你仍可以采取一些措施來減輕源自遠(yuǎn)程API的性能問題。例如,你可以緩存API輸出的數(shù)據(jù),或者可以在后臺(tái)調(diào)用這些API。為API請(qǐng)求設(shè)置合理的超時(shí)時(shí)間,并且如果可能的話,隨時(shí)做好API沒有響應(yīng)的情況下的顯示輸出。
5. 使用工具評(píng)估檢測你的PHP代碼使用OPcache和監(jiān)控外部API接口應(yīng)該足以使大多數(shù)應(yīng)用程序運(yùn)行順利;但是,如果你發(fā)現(xiàn)系統(tǒng)負(fù)載不斷增加,那么可能需要使用工具來對(duì)你的PHP代碼進(jìn)行檢測評(píng)估。完整的PHP代碼檢測評(píng)估雖然可能很耗時(shí),但它可以為你提供有關(guān)應(yīng)用程序性能的深入信息。幸運(yùn)的是,有幾個(gè)開源程序可以用于分析你的PHP代碼,如Xdebug。
監(jiān)控PHP性能的重要性如果你沒有做好準(zhǔn)備,你的Web應(yīng)用可能前一分鐘還在正常運(yùn)行,但是下一分鐘,一波突然激增的流量就會(huì)導(dǎo)致你的應(yīng)用程序崩潰。 當(dāng)然,優(yōu)化和重構(gòu)總是需要時(shí)間、精力和資金,而且投入是否值得的也很難說。因此,做出明智決策的最佳方式是不斷收集數(shù)據(jù)。
PHP性能監(jiān)控軟件可以幫助你立即測量所做的任何更改的影響。當(dāng)然,知道要監(jiān)測什么同樣重要。速度和內(nèi)存使用被認(rèn)為是性能的最佳指標(biāo),因?yàn)樗鼈冇绊懙巾撁婕虞d時(shí)間,這對(duì)Web應(yīng)用程序至關(guān)重要。
雖然數(shù)據(jù)收集很重要,但是當(dāng)你不需要監(jiān)控系統(tǒng)時(shí),你應(yīng)該關(guān)閉監(jiān)控系統(tǒng),因?yàn)榇罅咳罩就瑯右矔?huì)對(duì)性能造成影響。當(dāng)然,這樣的日志可以提供有關(guān)如何提高性能的有用信息,因此你應(yīng)該在高峰期間定期監(jiān)控。
未來的PHP性能PHP仍在不斷進(jìn)化中,在目前正在開發(fā)的PHP 8版本中,最新的功能是即時(shí)編譯或JIT,它將可以為我們創(chuàng)建更快的Web應(yīng)用。隨著技術(shù)的不斷進(jìn)步,用戶的期望也隨之增加。因此,開發(fā)人員必須始終關(guān)注未來的變化。
在構(gòu)建Web應(yīng)用程序時(shí),請(qǐng)記住,今年的工作可能在明年不起作用。你可能需要進(jìn)行調(diào)整才能持續(xù)保持優(yōu)秀的PHP性能。在開發(fā)過程中,應(yīng)該持續(xù)重點(diǎn)關(guān)注如何構(gòu)建適用于高并發(fā)場景的Web應(yīng)用和網(wǎng)站,保證它們的高可用性。
參考文章Using a PHP CDN Setup
How to Install Nginx PHP
掃描下方二維碼或者微信搜索[phpjiagoushier],關(guān)注我的微信公眾號(hào)[PHP架構(gòu)],參與互動(dòng)交流。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/22943.html
平日學(xué)習(xí)接觸過的網(wǎng)站積累,以每月的形式發(fā)布。2017年以前看這個(gè)網(wǎng)址:http://www.kancloud.cn/jsfron... 1. Javascript 前端生成好看的二維碼 十大經(jīng)典排序算法(帶動(dòng)圖演示) 為什么知乎前端圈普遍認(rèn)為H5游戲和H5展示的JSer 個(gè)人整理和封裝的YU.js庫|中文詳細(xì)注釋|供新手學(xué)習(xí)使用 擴(kuò)展JavaScript語法記錄 - 掉坑初期工具 漢字拼音轉(zhuǎn)換...
平日學(xué)習(xí)接觸過的網(wǎng)站積累,以每月的形式發(fā)布。2017年以前看這個(gè)網(wǎng)址:http://www.kancloud.cn/jsfron... 1. Javascript 前端生成好看的二維碼 十大經(jīng)典排序算法(帶動(dòng)圖演示) 為什么知乎前端圈普遍認(rèn)為H5游戲和H5展示的JSer 個(gè)人整理和封裝的YU.js庫|中文詳細(xì)注釋|供新手學(xué)習(xí)使用 擴(kuò)展JavaScript語法記錄 - 掉坑初期工具 漢字拼音轉(zhuǎn)換...
平日學(xué)習(xí)接觸過的網(wǎng)站積累,以每月的形式發(fā)布。2017年以前看這個(gè)網(wǎng)址:http://www.kancloud.cn/jsfron... 1. Javascript 前端生成好看的二維碼 十大經(jīng)典排序算法(帶動(dòng)圖演示) 為什么知乎前端圈普遍認(rèn)為H5游戲和H5展示的JSer 個(gè)人整理和封裝的YU.js庫|中文詳細(xì)注釋|供新手學(xué)習(xí)使用 擴(kuò)展JavaScript語法記錄 - 掉坑初期工具 漢字拼音轉(zhuǎn)換...
平日學(xué)習(xí)接觸過的網(wǎng)站積累,以每月的形式發(fā)布。2017年以前看這個(gè)網(wǎng)址:http://www.kancloud.cn/jsfron... 1. Javascript 前端生成好看的二維碼 十大經(jīng)典排序算法(帶動(dòng)圖演示) 為什么知乎前端圈普遍認(rèn)為H5游戲和H5展示的JSer 個(gè)人整理和封裝的YU.js庫|中文詳細(xì)注釋|供新手學(xué)習(xí)使用 擴(kuò)展JavaScript語法記錄 - 掉坑初期工具 漢字拼音轉(zhuǎn)換...
閱讀 3512·2021-11-22 09:34
閱讀 1955·2019-08-30 12:53
閱讀 3567·2019-08-28 18:07
閱讀 3078·2019-08-27 10:55
閱讀 3031·2019-08-26 10:12
閱讀 3666·2019-08-23 18:21
閱讀 1406·2019-08-23 14:10
閱讀 1560·2019-08-23 13:04