opcache的配置与使用

分享于:2020-11-04 20:01:17

安装与开启


php5.5以后,Opcache 是默认安装好了的,已经不需要再手动去安装了。

可以通过phpinfo函数、cli下 php -mphp-fpm -m 查看是否支持opcache。

[root@abcdocker ~]# /usr/local/php/sbin/php -m
[PHP Modules]
....
[Zend Modules]
Zend OPcache


不支持,重新安装PHP,携带参数--enable-opcache


opcache默认是没有开启的,如果我们需要使用,需要手动去开启,在php.ini文件中添加:


zend_extension=opcache.so #用来引用opcache
[opcache]
opcache.enable=1 #允许在web环境使用,默认是开启的。
opcache.enable_cli=1 #运行在cli环境使用


配置


opcache常有的一些配置项:

opcache.enable boolean
启用操作码缓存。如果禁用此选项,则不会优化和缓存代码。 在运行期使用 ini_set() 函数只能禁用 opcache.enable 设置,不可以启用此设置。 如果在脚本中尝试启用此设置项会产生警告。

opcache.enable_cli boolean
仅针对 CLI 版本的 PHP 启用操作码缓存。 通常被用来测试和调试。

opcache.memory_consumption integer
OPcache 的共享内存大小,以兆字节(MB)为单位。

opcache.interned_strings_buffer integer
用来存储临时字符串的内存大小,以兆字节为单位。 PHP 5.3.0 之前的版本会忽略此配置指令。
这是一个很有用的选项,但是似乎完全没有文档说明。PHP使用了一种叫做字符串驻留(stringinterning)的技术来改善性能。例如,如果你在代码中使用了1000次字符串“foobar”,在PHP内部只会在第一使用这个字符串的时候分配一个不可变的内存区域来存储这个字符串,其他的999次使用都会直接指向这个内存区域。这个选项则会把这个特性提升一个层次——默认情况下这个不可变的内存区域只会存在于单个php-fpm的进程中,如果设置了这个选项,那么它将会在所有的php-fpm进程中共享。在比较大的应用中,这可以非常有效地节约内存,提高应用的性能。

opcache.max_accelerated_files integer
  OPcache 哈希表中可存储的脚本文件数量上限。 真实的取值是在质数集合 { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 } 中找到的第一个比设置值大的质数。 设置值取值范围最小值是 200,最大值在 PHP 5.5.6 之前是 100000,PHP 5.5.6 及之后是 1000000。

opcache.max_wasted_percentage integer
 浪费内存的上限,以百分比计。 如果达到此上限,那么 OPcache 将产生重新启动续发事件。

opcache.use_cwd boolean
    如果启用,OPcache 将在哈希表的脚本键之后附加改脚本的工作目录, 以避免同名脚本冲突的问题。 禁用此选项可以提高性能,但是可能会导致应用崩溃。

opcache.validate_timestamps boolean
    如果启用,那么 OPcache 会每隔 opcache.revalidate_freq 设定的秒数 检查脚本是否更新。 如果禁用此选项,你必须使用 opcache_reset() 或者 opcache_invalidate() 函数来手动重置 OPcache,也可以 通过重启 Web 服务器来使文件系统更改生效。

opcache.revalidate_freq integer
    检查脚本时间戳是否有更新的周期,以秒为单位。 设置为 0 会导致针对每个请求, OPcache 都会检查脚本更新。
    如果 opcache.validate_timestamps 配置指令设置为禁用,那么此设置项将会被忽略。

opcache.revalidate_path boolean
    如果禁用此选项,在同一个 include_path 已存在的缓存文件会被重用。 因此,将无法找到不在包含路径下的同名文件。

opcache.save_comments boolean
    如果禁用,脚本文件中的注释内容将不会被包含到操作码缓存文件, 这样可以有效减小优化后的文件体积。 禁用此配置指令可能会导致一些依赖注释或注解的 应用或框架无法正常工作, 比如: Doctrine, Zend Framework 2 以及 PHPUnit。

opcache.load_comments boolean
    如果禁用,则即使文件中包含注释,也不会加载这些注释内容。 本选项可以和 opcache.save_comments 一起使用,以实现按需加载注释内容。

opcache.fast_shutdown boolean
    如果启用,则会使用快速停止续发事件。 所谓快速停止续发事件是指依赖 Zend 引擎的内存管理模块 一次释放全部请求变量的内存,而不是依次释放每一个已分配的内存块。

opcache.enable_file_override boolean
    如果启用,则在调用函数 file_exists(), is_file() 以及 is_readable() 的时候, 都会检查操作码缓存,无论文件是否已经被缓存。 如果应用中包含检查 PHP 脚本存在性和可读性的功能,这样可以提升性能。 但是如果禁用了 opcache.validate_timestamps 选项, 可能存在返回过时数据的风险。

opcache.optimization_level integer
    控制优化级别的二进制位掩码。

opcache.inherited_hack boolean
    在 PHP 5.3 之前的版本,OPcache 会存储代码中使用 DECLARE_CLASS 操作码 来实现继承的位置。当文件被加载之后,OPcache 会尝试使用当前环境来绑定被继承的类。 由于当前脚本中可能并不需要 DECLARE_CLASS 操作码,如果这样的脚本需要对应的操作码被定义时, 可能无法运行。
    在 PHP 5.3 及后续版本中,此配置指令会被忽略。

opcache.dups_fix boolean
    仅作为针对 “不可重定义类”错误的一种解决方案。

opcache.blacklist_filename string
    OPcache 黑名单文件位置。 黑名单文件为文本文件,包含了不进行预编译优化的文件名,每行一个文件名。 黑名单中的文件名可以使用通配符,也可以使用前缀。 此文件中以分号(;)开头的行将被视为注释。


我们所能常用的有这几个:

opcache.enable=1  #开启
opcache.memory_consumption=128 #缓存opcode的最大内存空间
opcache.interned_strings_buffer=32 
opcache.max_accelerated_files=200000 #可缓存的PHP文件数量
opcache.validate_timestamps=1 #是否开启PHPcode的缓存有效期
opcache.revalidate_freq=60 #PHPcode缓存时间
opcache.save_comments=0 #不缓存注释内容


opcache开启后的效果


1)执行结果上:


假如代码是

$str = 'abc'; 
echo $str; // 输出abc


执行一次,被缓存。把代码修改为


$str = 'abcdef'; 
echo $str; // 输出的还是abc


直到缓存到期,缓存新的代码,才会输出“abcdef”。


2)执行效率上:


编写一个功能页面,按f12,第一次访问,可观察到


1128628-20180504150651899-685437096.png


第一次的URL请求+响应时间


1128628-20180504150651899-685437096.png


当第二次请求时,因为不需要重新编译为opcode,时间大幅度下降。


操作函数


虽然opcahce是php内置的行为,只要你开启了,就会生效,不需要像传统的redis或者memcache需要手动写代码才能使用。但是php也提供了若干个opcache相关的函数。


opcache_compile_file — 无需运行,即可编译并缓存 PHP 脚本
opcache_get_configuration — 获取php.ini中的配置信息
opcache_get_status — 获取缓存的状态信息
opcache_invalidate — 废除脚本缓存
opcache_is_script_cached — 一个php文件是否被缓存
opcache_reset — 重置情况所有的缓存内容



这个几个函数,自认为opcache_reset挺好用的一个函数。

说下配置参数opcache.validate_timestamps,开启后,opcache会每隔一段时间去检查哪个opcode缓存是否到期,这必然会付出一点性能代价。在生产环境下,其实代码都是很固定的,很长时间不会变化,设置这样一个定时任务纯属浪费不必要的性能资源。

所以有必要把opcache.validate_timestamps关掉,当有新的代码上传到生产环境,只需要在脚本执行下opcache_reset函数,就可以清掉所有的缓存,让新代码在下次脚本执行时被缓存。


在开发环境下,不建议开启opcache,会影响正常效果展示。


opcache.enable_cli是否需要开启


启用opcache.enable_cli选项,在命令行(cli模式)下运行PHP脚本时才会有效果(例如 php index.php)。

OPcache扩展通过将缓存的操作码存储在当前进程的内存中来工作。

这仅在 PHP进程处理[可以重用这些操作码的多个请求]时有用,例如在Web服务器或FastCGI下。对于像PHP CLI这样运行一个“请求”并退出的进程,它只会浪费内存和时间。

所以不建议开启


如果使用了swoole拓展做常驻内存的web应用,可以开启。它的作用可以体现在这些地方:

比如【include多次调用同一PHP文件】,在一些模板组件中会遇到这些情况,比如TP模板引擎。

TP模板组件会多次调用include语句载入同一个模板PHP缓存文件,开启了cli模式下的opcache,第一次include就会把【编译好的模板PHP缓存文件的opcode】放入内存中,从第二次include开始直接从内存中读取,而不用每次都从硬盘上读取,再编译……