如何使用OPCache提升PHP的性能
對(duì)于 PHP 這樣的解釋型語(yǔ)言來(lái)說(shuō),每次的運(yùn)行都會(huì)將所有的代碼進(jìn)行一次加載解析,這樣一方面的好處是代碼隨時(shí)都可以進(jìn)行熱更新修改,因?yàn)槲覀儾恍枰幾g。但是這也會(huì)帶來(lái)一個(gè)問(wèn)題,那就是無(wú)法承載過(guò)大的訪問(wèn)量。畢竟每次加載解析再釋放,都會(huì)增加 CPU 的負(fù)擔(dān),通常一臺(tái) 8核16G 的服務(wù)器在2、3000并發(fā)左右 CPU 就能達(dá)到60%以上的使用率。而且如果你使用的是類(lèi)似于 Laravel 這種大型的框架,效率將更加低下。這個(gè)時(shí)候,我們通常會(huì)通過(guò)增加服務(wù)器數(shù)量來(lái)做負(fù)載均衡,從而達(dá)到減輕服務(wù)器壓力的效果。不過(guò),這樣做的成本又會(huì)增加許多。那么,有沒(méi)有什么優(yōu)化的方案呢?
鳥(niǎo)哥在他的博客中針對(duì) PHP7 的優(yōu)化的一篇文章中,第一條建議就是開(kāi)啟 OPcache 。當(dāng)然,另外一個(gè)方案就是使用 Swoole 。關(guān)于 Swoole 的內(nèi)容我們將來(lái)再說(shuō),今天,我們先學(xué)習(xí)學(xué)習(xí) OPcache 。
什么是 OPcache
OPcache 通過(guò)將 PHP 腳本預(yù)編譯的字節(jié)碼存儲(chǔ)到共享內(nèi)存中來(lái)提升 PHP 的性能, 存儲(chǔ)預(yù)編譯字節(jié)碼的好處就是 省去了每次加載和解析 PHP 腳本的開(kāi)銷(xiāo)。
這是 PHP 文檔中關(guān)于 OPcache 的簡(jiǎn)介,也就是說(shuō),OPcache 節(jié)約了每次加載和解析的步驟,將第一次解析編譯后的腳本字節(jié)碼緩存到系統(tǒng)的共享內(nèi)存中。其實(shí),這就類(lèi)似于一個(gè)不完全的編譯。
類(lèi)似于 Java 之類(lèi)的語(yǔ)言,都是要打包編譯之后才能上線(xiàn)運(yùn)行的,比如打包成一個(gè) jar包 。C++ 或 C# 可以打包成一個(gè) .dll 或 .exe 。這些打包之后的文件就是編譯完成的文件,將它們運(yùn)行起來(lái)后一般會(huì)一直保持運(yùn)行狀態(tài),也就是會(huì)成為一個(gè)常駐進(jìn)程,它們的代碼就進(jìn)入內(nèi)存中了。在程序運(yùn)行的時(shí)候,不需要再進(jìn)行解釋或編譯,自然速度就要快很多。而 OPcache 也是起到類(lèi)似的作用。只不過(guò)它并不是完全的一套編譯流程,我們還是依賴(lài)的 PHP-FPM 來(lái)運(yùn)行腳本,只不過(guò)在開(kāi)啟 OPcache 后,PHP-FPM 會(huì)先從內(nèi)存中查找是否已經(jīng)有相關(guān)的已經(jīng)緩存的字節(jié)碼在內(nèi)存中了,如果有的話(huà)就直接取用,如果沒(méi)有的話(huà),會(huì)再次進(jìn)行解釋編譯后緩存下來(lái)。另外,OPcache 是針對(duì)文件的,也就是說(shuō),一個(gè)文件如果是新增加進(jìn)來(lái)的,只有運(yùn)行過(guò)它才會(huì)緩存,如果沒(méi)有運(yùn)行過(guò),它并不在當(dāng)前的共享內(nèi)存中。
安裝 Opcache
OPcache 已經(jīng)是 PHP 的官方擴(kuò)展并隨安裝包一起發(fā)布了,所以,我們可以在編譯安裝 PHP 時(shí)使用 --enable-opcache 來(lái)開(kāi)啟擴(kuò)展,它已經(jīng)是默認(rèn)擴(kuò)展。也可以在未安裝 OPcache 的系統(tǒng)中使用安裝包中的文件來(lái)進(jìn)行安裝。
cd php-7.4.4/ext/opcache/ phpize ./configure make && make install
需要注意的是, OPcache 和 Xdebug 在生產(chǎn)環(huán)境中盡量不要一起使用。本身 Xdebug 就是不推薦在生產(chǎn)環(huán)境中使用的,如果一定需要同時(shí)使用的話(huà),需要先加載 OPcache ,然后再加載 Xdebug 。
擴(kuò)展安裝后,在 php.ini 文件中打開(kāi)擴(kuò)展。需要注意的是,OPcache 擴(kuò)展是 Zend 擴(kuò)展包,所以我們需要打開(kāi)的是 Zend 擴(kuò)展。
zend_extension=opcache.so
另外,還需要啟用它。
opcache.enable=1
當(dāng)開(kāi)啟了 OPcache 之后,我們?cè)俑麓a將會(huì)發(fā)現(xiàn)剛剛更新的代碼不是我們最新的代碼。這是因?yàn)榇a已經(jīng)被緩存了,就像 Java 一樣,我們需要重啟服務(wù)才行。那么 PHP 這邊重啟的是什么呢?當(dāng)然就是重啟下我們的 PHP-FPM 就可以了,直接使用 kill -USR2 命令去重啟主進(jìn)程就行了。這里也給出一個(gè)快速重啟的命令。
ps -ef | grep "php-fpm: master" | grep -v grep | cut -c 9-15 | xargs kill -USR2
感謝知乎大佬的指正,重啟 PHP-FPM 不是最佳方案,應(yīng)該使用 opcache_reset() 手動(dòng)重啟,或者通過(guò) php.ini 文件的配置 opcache.validate_timestamps + opcache.revalidate_freq 自動(dòng)間隔編譯,或者通過(guò) opcache_compile_file() 來(lái)直接重新編譯修改過(guò)的文件
ab 測(cè)試效果
我們進(jìn)行測(cè)試的內(nèi)容是測(cè)試環(huán)境的一臺(tái)2核4G的服務(wù)器,使用的 PHP 版本是 PHP7.4 ,正常的 Nginx 及 PHP 配置, ulimit 也都開(kāi)到了最大。代碼只是簡(jiǎn)單的輸出了一行文字,不過(guò)我們使用的是一個(gè)簡(jiǎn)單的 mvc 框架 ,也就是說(shuō)這段代碼運(yùn)行起來(lái)至少也會(huì)加載幾個(gè)文件,而不是簡(jiǎn)簡(jiǎn)單單的一個(gè)文件。
首先我們來(lái)看未開(kāi)啟 OPcache 的情況。
接下來(lái)是開(kāi)啟了 OPcache 的情況。
很明顯,性能有了很大的提高。不僅速度快了很多,吞吐率也是直接上升了幾倍。當(dāng)然,這只是非常簡(jiǎn)單的一個(gè)測(cè)試,不過(guò)總體看來(lái),確實(shí)對(duì)單機(jī)的性能提升有很大的幫助。最最主要的是,同樣的并發(fā)情況下,CPU 資源也比未開(kāi)啟的狀態(tài)下低了70%。
配置參考
在 PHP 的官方文檔中,已經(jīng)為我們給出了一套默認(rèn)的 OPcache 在 php.ini 中的配置。經(jīng)過(guò)測(cè)試,基本沒(méi)什么問(wèn)題,當(dāng)然,現(xiàn)在還沒(méi)有在生產(chǎn)環(huán)境中使用過(guò),還需要進(jìn)行更多的測(cè)試。不過(guò)文檔中指出,這套配置是可以直接運(yùn)用到線(xiàn)上的,不過(guò)需要注意的是某些使用了注解之類(lèi)功能的高級(jí)框架可能需要注意某些參數(shù)。
opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.revalidate_freq=60 opcache.fast_shutdown=1 opcache.enable_cli=1
具體的配置說(shuō)明以及其他的一些配置選項(xiàng)我們可以參考官方文檔進(jìn)行詳細(xì)的了解。
總結(jié)
既然是我們的 PHP 大神鳥(niǎo)哥推薦的,而且也是官方推薦的擴(kuò)展,我覺(jué)得在正式生產(chǎn)環(huán)境中使用不會(huì)有太大問(wèn)題。另外,官方也給出了一套可以直接運(yùn)用于線(xiàn)上生產(chǎn)環(huán)境的配置參數(shù),也方便我們直接在線(xiàn)上進(jìn)行測(cè)試。目前在生產(chǎn)環(huán)境中,我們只使用了一臺(tái)服務(wù)器來(lái)進(jìn)行測(cè)試,并且給它多分配了一些負(fù)載過(guò)來(lái),從目前的情況來(lái)看,這一臺(tái)機(jī)器的運(yùn)行效率比其他幾臺(tái)的高很多。因?yàn)樗环矫嫣幚砹烁嗟恼?qǐng)求,另一方面它的 CPU 資源占用率還沒(méi)有其他幾臺(tái)機(jī)器高。同時(shí),OPcache 也不需要我們?nèi)チ私飧嗟倪M(jìn)程協(xié)程之類(lèi)的知識(shí),不像 Swoole 一樣的會(huì)帶來(lái)更高的學(xué)習(xí)成本。所以綜上所述,在測(cè)試完備的情況下,OPcache 絕對(duì)是我們最優(yōu)先考慮的單機(jī)優(yōu)化方案。
參考文檔
https://www.php.net/manual/zh/book.opcache.php
以上就是如何使用OPCache提升PHP的性能的詳細(xì)內(nèi)容,更多關(guān)于用OPCache提升PHP的性能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用php偽造referer的方法 利用referer防止圖片盜鏈
當(dāng)瀏覽器向web服務(wù)器發(fā)送請(qǐng)求的時(shí)候,一般會(huì)帶上Referer,告訴服務(wù)器我是從哪個(gè)頁(yè)面鏈接過(guò)來(lái)的,服務(wù)器籍此可以獲得一些信息用于處理,不過(guò)這個(gè)Referer是可以偽造,下面看一個(gè)示例,大家就明白了2014-01-01php array_walk_recursive 使用自定的函數(shù)處理數(shù)組中的每一個(gè)元素
php中,如果需要對(duì)數(shù)組中的每個(gè)元素進(jìn)行一定規(guī)則的處理,我們可以使用array_walk_recursive,array_walk_recursive函數(shù)用于對(duì)數(shù)組中的每個(gè)成員遞歸地應(yīng)用用戶(hù)函數(shù)。本文章通過(guò)實(shí)例向大家講解array_walk_recursive函數(shù)的使用方法2016-11-11基于jQueryUI和Corethink實(shí)現(xiàn)百度的搜索提示功能
這篇文章主要介紹了基于jQueryUI和Corethink實(shí)現(xiàn)百度的搜索提示功能,這里是以corethink模塊的形式,只需要安裝上訪問(wèn)index.php?s=/test/index 就可以了,需要的朋友可以參考下2016-11-11Apache啟動(dòng)報(bào)錯(cuò)No space left on device: AH00023該怎么解決
最近有朋友說(shuō):Apache啟動(dòng)報(bào)錯(cuò)No space left on device: AH00023,是怎么回事,該怎么解決呢?經(jīng)過(guò)小編的一番折騰,問(wèn)題解決,下面把解決辦法分享給大家,需要的朋友可以參考下2015-10-10詳解PHP文件的自動(dòng)加載(autoloading)
這篇文章主要介紹了詳解PHP文件的自動(dòng)加載(autoloading)相關(guān)知識(shí)點(diǎn)以及詳細(xì)用法,有這方面需要的朋友參考下吧。2018-02-02php桌面中心(二) 數(shù)據(jù)庫(kù)寫(xiě)入
php桌面中心(二) 數(shù)據(jù)庫(kù)寫(xiě)入...2007-03-03