PHP 8.1 带有一个继承缓存,它与预加载的功能部分重叠。如果您在较低版本上启用了预加载,然后迁移到 PHP 8.1,您可能希望关闭预加载,看看这是否会带来性能损失。
从 PHP 7.4.0 开始,PHP 可以配置为在引擎启动时将脚本预加载到 opcache 中。这些文件中任何函数、类、接口或特性(但不包括常量)将随后对所有请求全局可用,无需显式包含。这以便利性和性能为代价(因为代码始终可用)来换取基本内存使用。它还需要重启 PHP 进程才能清除预加载的脚本,这意味着此功能仅适用于生产环境,不适用于开发环境。
请注意,性能和内存之间的最佳平衡可能因应用程序而异。“预加载所有内容”可能是最简单的策略,但不一定是最佳策略。此外,预加载只有在请求之间存在持久进程时才有用。这意味着虽然它可以在 opcache 启用的情况下在 CLI 脚本中工作,但通常没有意义。唯一的例外是在使用预加载的 FFI 库 时。
注意:
Windows 上不支持预加载。
配置预加载需要两个步骤,并要求 opcache 处于启用状态。首先,在 php.ini 中设置 opcache.preload 值
opcache.preload=preload.php
preload.php 是一个任意文件,它将在服务器启动时(PHP-FPM、mod_php 等)运行一次,并将代码加载到持久内存中。在作为 root 启动并在切换到非特权系统用户之前启动的服务器中,或者如果 PHP 将作为 root 运行(不建议),则 opcache.preload_user 值可以指定运行预加载的系统用户。默认情况下不允许以 root 身份运行预加载。设置 opcache.preload_user=root
以明确允许它。
在 preload.php 脚本中,由 include、include_once、require、require_once 或 opcache_compile_file() 引用的任何文件都将被解析到持久内存中。在以下示例中,src 目录中的所有 .php 文件都将被预加载,除非它们是 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() 都可以使用,但对代码的处理方式有不同的影响。
A
,而 b.php 定义了扩展 A
的类 B
,那么 opcache_compile_file() 可以按任何顺序加载这两个文件。但是,当使用 include 时,a.php 必须先包含。PHP 8.1 带有一个继承缓存,它与预加载的功能部分重叠。如果您在较低版本上启用了预加载,然后迁移到 PHP 8.1,您可能希望关闭预加载,看看这是否会带来性能损失。
启用预加载时有一些注意事项,其中之一是应该通过 php.ini 文件启用它。例如,通过 php-fpm 池配置启用它将不起作用,因为预加载是全局的,而不是按池的。为了确保您成功启用了预加载,您应该检查 opcache_get_status() 的输出中是否存在 preload_statistics 键。应该已经有一个 opcache_statistics 键,但这是完全不同的东西。