【modernPHP專題(13)】ZendOpcache字節碼緩存

概述

字節碼緩存不是PHP的新特性,有很多獨立的擴展可以實現,比如APC、eAccelerator和Xache等,但是截至目前這些擴展都沒有集成到PHP內核,從PHP 5.5.0開始,PHP內置了字節碼緩存功能,名爲Zend Opcache。

開始之前,我們先來看看什麼是字節碼緩存,以及字節碼緩存的作用是什麼。

衆所周知,PHP是解釋型語言,構建在Zend 虛擬機之上,PHP解釋器在執行PHP腳本時會解析PHP腳本代碼,把PHP代碼編譯成一系列Zend操作碼( opcode,由於每個操作碼都是一個字節長,所以又叫字節碼,字節碼可以直接被Zend虛擬機執行),然後執行字節碼。每次請求PHP文件都是這樣,這會消耗很多資源,如果每次HTTP請求都必須不斷解析、編譯和執行PHP腳本,消耗的資源更多。如果PHP源碼不變,相應的字節碼也不會變化,顯然沒有必要每次都重新生成Opcode,結合在Web應用中無處不在的緩存機制,我們可以把首次生成的Opcode緩存起來,這樣下次直接從緩存取,豈不是很快?下面是啓用Opcode緩存之前和之後的流程圖:

圖片描述

字節碼緩存能存儲預先編譯好的PHP字節碼,這樣,下次請求PHP腳本時,PHP解釋器不用每次讀取、解析和編譯PHP代碼,直接從內存中讀取預先編譯好的字節碼,然後立即執行,這樣能省很多時間,極大提升應用的性能。

啓用Zend Opcache

注:如果使用Windows開發環境,或者使用brew或apt-get等命令安裝的PHP可以略過編譯步驟。

默認情況下,Zend Opcache沒有開啓,需要我們在編譯時使用--enable-opcache指定啓用Zend Opcache。

編譯好PHP後還需要在php.ini中指定Opcache擴展路徑:

zend_extension=/path/to/opcache.so

一般而言PHP編譯成功後會顯示Zend Opcache擴展路徑,但如果想不起來,可以使用如下命令找到PHP擴展所在目錄:

php -ini | grep extensions
[info] 注:如果你使用Xdebug,需要在php.ini中先加載Zend Opcache,再加載Xdebug。

重啓後,查看phpinfo

php -info | grep Opcache

配置Zend Opcache

啓用Zend Opcache後還需要在php.ini中配置Zend Opcache,下面是一份配置示例作爲參考:

opcache.validate_timestamps=1    // 生產環境中配置爲0
opcache.revalidate_freq=0    //檢查腳本時間戳是否有更新時間
opcache.memory_consumption=64    //Opcache的共享內存大小,以M爲單位
opcache.interned_strings_buffer=16    //用來存儲臨時字符串的內存大小,以M爲單位
opcache.max_accelerated_files=4000    //Opcache哈希表可以存儲的腳本文件數量上限
opcache.fast_shutdown=1         //使用快速停止續發事件

官網配置參考

使用Zend Opcache

Zend Opcache使用起來很簡單,因爲啓用之後它會自動運行,Zend Opcache會自動在內存中緩存預先編譯好的PHP字節碼,如果緩存了某個文件的字節碼,就執行對應的字節碼。

如果php.ini中配置了opcache.validate_timestamps值爲0,需要小心,因爲Zend Opcache將不能覺察PHP腳本的變化,必須手動清空Zend OPcache緩存的字節碼,才能讓它發現PHP文件的變動。這個配置適合在生產環境中設置爲0,但在開發環境會帶來不便,我們可以在開發環境中這樣配置啓用自動驗證緩存功能:

opcache.enable=1 # 啓用操作碼緩存,默認爲“1”, 如果禁用此選項,則不會優化和緩存代碼。
opcache.revalidate_freq=0 #  檢查腳本時間戳是否有更新的週期,以秒爲單位。設置爲 0 會導致針對每個請求, OPcache 都會檢查腳本更新。
opcache.validate_timestamps=1 # 如果啓用,那麼 OPcache 會每隔 opcache.revalidate_freq 設定的秒數 檢查腳本是否更新。

手動清理緩存

除了重啓php-fpm的進程可以清理opcache緩存外,
手動清理緩存涉及到的opcache函數主要爲:opcache_reset()和opcache_invalidate() 。

boolean opcache_reset ( void ) # 該函數將重置整個字節碼緩存。 在調用 opcache_reset() 之後,所有的腳本將會重新載入並且在下次被點擊的時候重新解析。

[warning] 需要注意的是,當PHP以PHP-FPM的方式運行的時候,opcache的緩存是無法通過php命令進行清除的,只能通過http或cgi到php-fpm進程的方式來清除緩存。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章