<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何更好的使用OPcache實(shí)現(xiàn)性能優(yōu)化

          共 5540字,需瀏覽 12分鐘

           ·

          2021-09-26 01:51

          文章說明

          一直知道opcache可以提高PHP性能,但沒有具體的關(guān)注,更多的利用其他的組件來提升系統(tǒng)的性能。一次無意開啟了opcache之后,并隨意設(shè)置了一些配置。結(jié)果導(dǎo)致后面在使用一個(gè)項(xiàng)目時(shí),發(fā)現(xiàn)項(xiàng)目總是不會(huì)讀取到最新的代碼,而是隔一段時(shí)間才會(huì)執(zhí)行到最新代碼。排查了很久才想起來開啟了opcache,于是對(duì)opcache做了一個(gè)簡(jiǎn)單的學(xué)習(xí)與總結(jié)。

          發(fā)現(xiàn)這個(gè)優(yōu)化小技巧之后,后面也會(huì)對(duì)稍微底層進(jìn)行探索學(xué)習(xí),歡迎大家持續(xù)關(guān)注該文。

          什么是opcache

          OPcache 通過將 PHP 腳本預(yù)編譯的字節(jié)碼存儲(chǔ)到共享內(nèi)存中來提升 PHP 的性能, 存儲(chǔ)預(yù)編譯字節(jié)碼的好處就是 省去了每次加載和解析 PHP 腳本的開銷。

          opcache運(yùn)行原理

          不使用opcache

          在使用opcache之前,我們事先看一個(gè)request,PHP的一個(gè)大致處理流程是如何的。大致的示意圖如下:

          1. 首先會(huì)去模塊初始化一次,也就是加載我們php.ini當(dāng)中的一些配置信息,這里需要根據(jù)配置信息初始化一次。

          2. 初始化完php.ini的配置信息之后,第二步就是針對(duì)當(dāng)前請(qǐng)求的信息做一次初始化。例如我的一些get、post以及$_SEVER等相關(guān)的信息。

          3. 得到上面1和2中的信息之后,則時(shí)候就會(huì)去真正執(zhí)行我們的php腳本文件內(nèi)容了,也就是我們寫的代碼。是怎么去實(shí)現(xiàn)的呢?如下圖:Zend引擎讀取.php文件-->掃描其詞典和表達(dá)式 -->解析文件-->創(chuàng)建要執(zhí)行的計(jì)算機(jī)代碼(稱為Opcode)-->最后執(zhí)行Opcode--> response 返回。

          4. 執(zhí)行完php腳本文件內(nèi)容之后,這時(shí)候會(huì)針對(duì)1和2中的一些初始化信息,進(jìn)行銷毀。

          使用opcache

          當(dāng)使用opcache之后,當(dāng)一個(gè)請(qǐng)求來了之后,依然的會(huì)去執(zhí)行上面提到的1和2,進(jìn)行模塊和請(qǐng)求的初始化。接著就會(huì)去編譯php腳本文件內(nèi)容,opcache也是在這一個(gè)階段才會(huì)產(chǎn)生作用。

          通過上面的第3步,我們可以看到每一次請(qǐng)求都會(huì)去解析php文件內(nèi)容,不管是php文件的內(nèi)容是否發(fā)生變化,都會(huì)執(zhí)行這樣的一個(gè)重復(fù)流程來生成opcode。

          opcache的作用就是減少每次請(qǐng)求都會(huì)去編譯php腳本文件,第一次將編譯好的腳本文件內(nèi)容緩存起來,下一次請(qǐng)求就不需要去重復(fù)編譯了,而是直接沖內(nèi)存中取就行了。減少了CPU和內(nèi)存的消耗。

          Snipaste_2021-09-24_23-18-16
          1. 首先會(huì)去模塊初始化一次,也就是加載我們php.ini當(dāng)中的一些配置信息,這里需要根據(jù)配置信息初始化一次。

          2. 初始化完php.ini的配置信息之后,第二步就是針對(duì)當(dāng)前請(qǐng)求的信息做一次初始化。例如我的一些get、post以及$_SEVER等相關(guān)的信息。

          3. 此時(shí)去解析php腳本文件,首先會(huì)去判斷opcode是否存在,如果不存在就執(zhí)行一個(gè)編譯流程并緩存到共享內(nèi)存中。當(dāng)存在opcode時(shí),則直接使用共享內(nèi)存中的opcode,不會(huì)再進(jìn)行一次編譯的過程。

          4. 執(zhí)行完php腳本文件內(nèi)容之后,這時(shí)候會(huì)針對(duì)1和2中的一些初始化信息,進(jìn)行銷毀。

          使用總結(jié)

          1. 通過上面的對(duì)比,很容易看得出來opcache執(zhí)行的時(shí)段在于編譯php腳本文件,減少了編譯的過程。

          2. 對(duì)于模塊初始化、請(qǐng)求初始化等這樣的一個(gè)重復(fù)流程,該如何優(yōu)化。這里可以去了解一下swoole。

          3. 可能會(huì)存在這樣一個(gè)疑問,opcode給緩存起來了,如果我們更新了代碼,這時(shí)候還是會(huì)加載舊的opcode還是重新編譯一次opcode并緩存起來呢?后面我們會(huì)單獨(dú)總結(jié)。

          opcache配置說明

          [opcache]
          ; 是否快開啟opcache緩存。
          ;opcache.enable=1

          ; 是否在cli模式下開啟opcache。
          ;opcache.enable_cli=1

          ; opcache共享內(nèi)存的大小(單位是M)。
          ;opcache.memory_consumption=128

          ; 預(yù)留字符串的的內(nèi)存大小(單位是M)。
          ;opcache.interned_strings_buffer=8

          ; 在hash表中存儲(chǔ)的最大腳本文件數(shù)量,范圍是2001000000之間。實(shí)際的情況是在{ 223463983197939077963162293253165407130987 }中找到第一個(gè)大于等于設(shè)置值的質(zhì)數(shù)。最小范圍是200
          ;opcache.max_accelerated_files=10000

          ; 浪費(fèi)內(nèi)存的上線,如果超過這個(gè)上線,opcache將重新啟動(dòng)。
          ;opcache.max_wasted_percentage=5

          ; 如果啟用,opcache將會(huì)在hash表的腳本鍵后面增加一個(gè)文件目錄,避免吃同名的腳本產(chǎn)生沖突。禁用的話可以提高性能,但是也容易導(dǎo)致應(yīng)用不可用。
          ;opcache.use_cwd=1

          ; 如果啟用(1),opcache會(huì)每隔設(shè)置的值時(shí)間來判斷腳本是否更新。如果禁用(0),則不會(huì)自動(dòng)檢測(cè)腳本更新,必須通過重啟PHP服務(wù),或者使用opcache_reset()、opcache_invalidate()函數(shù)來刷新緩存。
          ;opcache.validate_timestamps=1

          ; opcache檢查腳本是否更新的時(shí)間周期(單位是秒),如果設(shè)置為0則會(huì)針對(duì)每一個(gè)請(qǐng)求進(jìn)行檢查更新,如果validate_timestamps=0,該值不會(huì)生效。
          ;opcache.revalidate_freq=60

          ; 如果禁用,在統(tǒng)一include_path下面已經(jīng)緩存的文件將被重用,因此無法找到該路徑下的同名文件。
          ;opcache.revalidate_path=0

          ; 是否保存PHP腳本中的注釋內(nèi)容。禁用,則不會(huì)緩存PHP代碼中的注釋,可以減少文件中的體積,但是一些依賴注釋或者注解將無法使用。
          ;opcache.save_comments=1

          ; 如果啟用,則會(huì)使用快速停止續(xù)發(fā)事件。 所謂快速停止續(xù)發(fā)事件是指依賴 Zend 引擎的內(nèi)存管理模塊 一次釋放全部請(qǐng)求變量的內(nèi)存,而不是依次釋放每一個(gè)已分配的內(nèi)存塊。
          ; 在php7.2.0開始,被移除,這類說的事件將會(huì)在PHP中自動(dòng)處理。
          ;opcache.fast_shutdown=1

          ; 如果啟用,在調(diào)用file_exists()、is_file()和is_readable()函數(shù)時(shí),不管文件是否被緩存,都會(huì)檢測(cè)操作碼。如果禁用,可能讀取的內(nèi)容是一些舊數(shù)據(jù)。
          ;opcache.enable_file_override=0

          ; 控制優(yōu)化級(jí)別,是一個(gè)二進(jìn)制的位的掩碼。
          ;opcache.optimization_level=0xffffffff

          ; 不進(jìn)行編譯優(yōu)化的配置文件路徑。該文件中配置具體哪些不被編譯的文件。如果文中每行的開頭是";"開頭,則會(huì)被視為注釋。黑名單中的文件名,可以是通配符,也可以使用前綴。
          ; 例如配置文件的路徑是"/home/blacklist.txt",則該配置的值就是該路徑。
          ; 配置的內(nèi)容可以是如下格式

          ; 這是一段注釋,在解析的時(shí)候因?yàn)殚_頭是;,則會(huì)被視為注釋
          ;/var/www/a.php
          ;/var/www/a/b.php

          ;opcache.blacklist_filename=

          ; 以字節(jié)為單位的緩存的文件大小上限。設(shè)置為 0 表示緩存全部文件。
          ;opcache.max_file_size=0

          ; 每個(gè)N次請(qǐng)求會(huì)檢查緩存校驗(yàn)和,0是不檢查。該項(xiàng)對(duì)性能有較大影響,盡量在調(diào)試環(huán)境中使用。
          ;opcache.consistency_checks=0

          ; 如果緩存處于非激活狀態(tài),等待多少秒之后計(jì)劃重啟。 如果超出了設(shè)定時(shí)間,則 OPcache 模塊將殺除持有緩存鎖的進(jìn)程, 并進(jìn)行重啟。
          ;opcache.force_restart_timeout=180

          ; 錯(cuò)誤日志文件位置,不填寫將默認(rèn)輸出到服務(wù)器的錯(cuò)誤日志文件中。
          ;opcache.error_log=

          ; 錯(cuò)誤日志文件等級(jí)。
          ; 默認(rèn)情況下,僅有致命級(jí)別(0)及錯(cuò)誤級(jí)別(1)的日志會(huì)被記錄。 其他可用的級(jí)別有:警告(2),信息(3)和調(diào)試(4)。
          ; 如何設(shè)置的是1以上,在進(jìn)行force_restart_timeout選項(xiàng)時(shí),會(huì)將錯(cuò)誤日志中插入一條警告信息。
          ;opcache.log_verbosity_level=1

          ; opcache首選的內(nèi)存模塊,不配置則自動(dòng)選擇。可以選擇的值有mmap,shm, posix 以及 win32。
          ;opcache.preferred_memory_model=

          ; 保護(hù)共享內(nèi)存,以避免執(zhí)行腳本時(shí)發(fā)生非預(yù)期的寫入。 僅用于內(nèi)部調(diào)試。
          ;opcache.protect_memory=0

          ; 只允許指定字符串開頭的PHP腳本調(diào)用opcache api函數(shù),默認(rèn)不做限制。
          ;opcache.restrict_api=

          ; 在 Windows 平臺(tái)上共享內(nèi)存段的基地址。 所有的 PHP 進(jìn)程都將共享內(nèi)存映射到同樣的地址空間。 使用此配置指令避免“無法重新附加到基地址”的錯(cuò)誤。
          ;opcache.mmap_base=

          ; 配置二級(jí)緩存目錄并啟用二級(jí)緩存。 啟用二級(jí)緩存可以在 SHM 內(nèi)存滿了、服務(wù)器重啟或者重置 SHM 的時(shí)候提高性能。 默認(rèn)值為空字符串 "",表示禁用基于文件的緩存。
          ;opcache.file_cache=

          ; 啟用或禁用在共享內(nèi)存中的 opcode 緩存。
          ;opcache.file_cache_only=0

          ; 當(dāng)從文件緩存中加載腳本的時(shí)候,是否對(duì)文件的校驗(yàn)和進(jìn)行驗(yàn)證。
          ;opcache.file_cache_consistency_checks=1

          ; 在 Windows 平臺(tái)上,當(dāng)一個(gè)進(jìn)程無法附加到共享內(nèi)存的時(shí)候, 使用基于文件的緩存。需要開啟opcache.file_cache_only選項(xiàng)。建議開啟此選項(xiàng),否則可能導(dǎo)致進(jìn)程無法啟動(dòng)。
          ;opcache.file_cache_fallback=1

          ; 啟用或者禁用將 PHP 代碼(文本段)拷貝到 HUGE PAGES 中。 此項(xiàng)配置指令可以提高性能,但是需要在 OS 層面進(jìn)行對(duì)應(yīng)的配置。
          ;opcache.huge_code_pages=1

          ; 針對(duì)當(dāng)前用戶,驗(yàn)證緩存文件的訪問權(quán)限。
          ;opcache.validate_permission=0

          ; 在 chroot 的環(huán)境中避免命名沖突。 為了防止進(jìn)程訪問到 chroot 環(huán)境之外的文件,應(yīng)該在 chroot 的情況下啟用這個(gè)選項(xiàng)。
          ;opcache.validate_root=0

          配置示例

          下面這一段代碼是PHP官方給的一個(gè)示例配置,推薦使用該配置項(xiàng)進(jìn)行配置,也可以根據(jù)自己實(shí)際的情況進(jìn)行單獨(dú)配置。

          ;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

          問題總結(jié)

          1. 如何更新opcode?

          編譯好的opcode會(huì)添加到共享內(nèi)存中,如果我們更新了代碼就需要去更新opcode,否則得到的代碼還是舊的opcode。就會(huì)發(fā)生文章開頭說到的情況。要解決這個(gè)問題,我們有幾種方式。

          ; 方法一
          直接重啟我們的php進(jìn)程,但這樣會(huì)導(dǎo)致服務(wù)中斷,是一種不推薦的方式。

          ; 方法二
          根據(jù)官方給出的函數(shù),進(jìn)行設(shè)置。在代碼中使用opcache_reset()或者使用opcache_invalidate()函數(shù)進(jìn)行充值opcode。直接通過一個(gè)特殊的鏈接去執(zhí)行這個(gè)函數(shù)即可。

          ; 方法三
          使用php.ini中的配置項(xiàng)實(shí)現(xiàn)自動(dòng)充值opcode。
          opcache.validate_timestamps = 1
          opcache.revalidate_freq  = 60

          效果演示

          Snipaste_2021-09-25_12-42-05
          Snipaste_2021-09-25_12-41-15
          1. 上面的兩張圖,第一張是未開啟opcache的一個(gè)壓測(cè),第二個(gè)是開啟opcache的一個(gè)壓測(cè)。

          2. 從截圖上來看,開啟opcache開啟之后,有一些小幅度的提升。也并沒有網(wǎng)上說的翻倍的提升。

          3. 這里的提升不能說opcache的提升效果不明顯,這需要根據(jù)綜合因素決定,這里的演示使用Mac操作本身就會(huì)降低很多。


          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产有码在线 | 久草福利在线 | 九九精品在线视频 | 国产一国产精品一级毛片 | 日韩在线播放视频 |