PHP8 預(yù)加載

2023-09-07 11:41 更新

從 PHP 7.4.0 起,PHP 可以被配置為在引擎啟動(dòng)時(shí)將一些腳本預(yù)加載進(jìn) opcache 中。在那些文件中的任何函數(shù)、類、 接口或者 trait (但不包括常量)將在接下來的所有請(qǐng)求中變?yōu)槿挚捎茫辉傩枰@示地包含它們。這犧牲了基準(zhǔn)的 內(nèi)存占用率但換來了方便和性能(因?yàn)檫@些代碼將始終可用)。它還需要通過重啟 PHP 進(jìn)程來清除預(yù)加載的腳本, 這意味著這個(gè)功能僅在生產(chǎn)環(huán)境中有實(shí)用價(jià)值,而非開發(fā)環(huán)境。

需要注意的是,性能和內(nèi)存之間的最佳平衡因應(yīng)用而異。 “預(yù)加載一切” 可能是最簡單的策略,但不一定是最好的策略。 此外,只有當(dāng)不同的請(qǐng)求間有持久化的進(jìn)程時(shí),預(yù)加載才有用。這意味著,雖然在啟用了 opcache 的命令行腳本中可以使用預(yù)加載, 但這通常是沒有意義的。例外情況是在使用預(yù)加載時(shí)的 FFI 庫。

注意:Windows 上不支持預(yù)加載。

配置預(yù)加載需要兩步,并且要求開啟 opcache。首先,在php.ini 中設(shè)置 opcache.preload 的值:

opcache.preload=preload.php

preload.php 是一個(gè)在服務(wù)器啟動(dòng)時(shí)會(huì)運(yùn)行一次(PHP-FPM、mod_php 等)的任意文件, 它的代碼會(huì)加載到持久化內(nèi)存中。在以 root 用戶啟動(dòng)后切換到非特權(quán)系統(tǒng)用戶的服務(wù)器上,又或者是以 root 用戶身份運(yùn)行 PHP 的情況(不建議這樣做),可以通過opcache.preload_user 來指定進(jìn)行預(yù)加載的系統(tǒng)用戶。 默認(rèn)情況下,不允許以 root 用戶身份進(jìn)行預(yù)加載。通過設(shè)置 opcache.preload_user=root 來顯示地允許它。

在 preload.php 腳本中, 任何被 include、 include_once、require、require_once或 opcache_compile_file() 引用的文件將被解析到持久化內(nèi)存中。 在下面的這個(gè)例子中, 所有在 src 目錄下的 .php 文件將被預(yù)加載,除非那是一個(gè) Test 文件。

<?php
$directory = new RecursiveDirectoryIterator(__DIR__ . '/src');
$fullTree = new RecursiveIteratorIterator($directory);
$phpFiles = new RegexIterator($fullTree, '/.+((?<!Test)+\.php$)/i', RecursiveRegexIterator::GET_MATCH);

foreach ($phpFiles as $key => $file) {
require_once($file[0]);
}
?>

include 和 opcache_compile_file() 都會(huì)生效,但對(duì)代碼處理方式有不同的影響。 Both include and opcache_compile_file() will work, but have different implications for how code gets handled.

  • include 將執(zhí)行文件中的代碼,而 opcache_compile_file() 不會(huì)執(zhí)行代碼。這意味著只有前者支持條件聲明(在 if 塊中聲明函數(shù))。
  • 由于 include 會(huì)執(zhí)行代碼,因此所有被 include 的文件也將被解析, 其中的定義也將被預(yù)加載。
  • opcache_compile_file() 可以按任何順序加載文件。也就是說,如果 a.php 定義了類 A,而 b.php 定義了一個(gè)繼承類 A 的類 B, 則 opcache_compile_file() 可以按任何順序來加載這兩個(gè)文件。然而,當(dāng)使用 include 時(shí), a.php 必須 先被包含。
  • 不管在哪種情況下,如果一個(gè)腳本包含了一個(gè)已經(jīng)被預(yù)加載的文件,那么這個(gè)已經(jīng)被預(yù)加載的文件里的內(nèi)容仍將被執(zhí)行, 但其中定義的任何符號(hào)將不會(huì)被重新定義。使用 include_once 不會(huì)阻止文件被二次包含。有時(shí)候可能仍需要重新加載文件 來包含其中定義的全局常量,因?yàn)檫@些常量預(yù)加載并不會(huì)處理。

因此,哪種方式更好取決于所需的行為。對(duì)于本來會(huì)使用自動(dòng)加載器的代碼,opcache_compile_file() 有更高的靈活性。而對(duì)于本來會(huì)需要手動(dòng)加載的代碼,include 會(huì)更健壯。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)