OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来实现,这样可以省去每次加载和解析 PHP 脚本的开销,从而提升 PHP 的运行性能。PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。本教程主要介绍了PHP中OPcache的原理、安装和相关配置。
一、安装
OPcache 只能编译为共享扩展。 如果你使用 –disable-all 参数禁用了默认扩展的构建, 那么必须使用 –enable-opcache 选项来开启 OPcache。
编译之后,就可以使用 zend_extension 指令来将 OPcache 扩展加载到 PHP 中。
- 在非 Windows 平台使用 zend_extension=/full/path/to/opcache.so;
- Windows 平台使用 zend_extension=C:\path\to\php_opcache.dll。
使用下列推荐设置来获得较好的性能:
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 ; prior to PHP 7.2.0
你也可以禁用 opcache.save_comments 并且启用 opcache.enable_file_override。 需要提醒的是,在生产环境中使用上述配置之前,必须经过严格测试。 因为上述配置存在一个已知问题,它会引发一些框架和应用的异常, 尤其是在存在文档使用了备注注解的时候。在 Windows 上,应该启用 opcache.file_cache_fallback,以及应该将 opcache.file_cache 设置为存在且可写的目录。
二、预加载
从 PHP 7.4.0 起,PHP 可以被配置为在引擎启动时将一些脚本预加载进 opcache 中。在那些文件中的任何函数、类、 接口或者 trait (但不包括常量)将在接下来的所有请求中变为全局可用,不再需要显示地包含它们。这牺牲了基准的 内存占用率但换来了方便和性能(因为这些代码将始终可用)。它还需要通过重启 PHP 进程来清除预加载的脚本, 这意味着这个功能仅在生产环境中有实用价值,而非开发环境。
需要注意的是,性能和内存之间的最佳平衡因应用而异。 “预加载一切” 可能是最简单的策略,但不一定是最好的策略。 此外,只有当不同的请求间有持久化的进程时,预加载才有用。这意味着,虽然在启用了 opcache 的命令行脚本中可以使用预加载, 但这通常是没有意义的。
注意:Windows 上不支持预加载。
配置预加载需要两步,并且要求开启 opcache。首先,在php.ini 中设置 opcache.preload 的值:
opcache.preload=preload.php
preload.php 是一个在服务器启动时会运行一次(PHP-FPM、mod_php 等)的任意文件, 它的代码会加载到持久化内存中。在以 root 用户启动后切换到非特权系统用户的服务器上,又或者是以 root 用户身份运行 PHP 的情况(不建议这样做),可以通过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]; } ?>
三、OPcache函数
- opcache_compile_file — 无需运行,即可编译并缓存 PHP 脚本;
- opcache_get_configuration — 获取缓存的配置信息;
- opcache_get_status — 获取缓存的状态信息;
- opcache_invalidate — 废除脚本缓存;
- opcache_is_script_cached — 告诉是否在 OPCache 中缓存脚本;
- opcache_reset — 重置字节码缓存的内容。