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 键,但这完全是另一回事。