Opcache是一种通过将解析的PHP脚本,预编译的字节码,存放在共享内存中,来避免每次加载和解析PHP脚本的开销,解析器可以直接从共享内存读取已经缓存的字节码,从而大大提高PHP的执行效率。这里需要区别于Xcache机制。

OPcache 官网: http://php.net/manual/zh/book.opcache.php

 

PHP 5.5+版本以上的,可以使用PHP自带的opcache开启性能加速(默认是关闭的)。

vim /usr/local/php/lib/php.ini

[opcache]
; Determines if Zend OPCache is enabled
;opcache.enable=0

; Determines if Zend OPCache is enabled for the CLI version of PHP
;opcache.enable_cli=0

; The OPcache shared memory storage size.
;opcache.memory_consumption=64

; The amount of memory for interned strings in Mbytes.
;opcache.interned_strings_buffer=4

; The maximum number of keys (scripts) in the OPcache hash table.
; Only numbers between 200 and 100000 are allowed.
;opcache.max_accelerated_files=2000

; The maximum percentage of "wasted" memory until a restart is scheduled.
;opcache.max_wasted_percentage=5

; When this directive is enabled, the OPcache appends the current working
; directory to the script key, thus eliminating possible collisions between
; files with the same name (basename). Disabling the directive improves
; performance, but may break existing applications.
;opcache.use_cwd=1

; When disabled, you must reset the OPcache manually or restart the
; webserver for changes to the filesystem to take effect.
;opcache.validate_timestamps=1

; How often (in seconds) to check file timestamps for changes to the shared
; memory storage allocation. ("1" means validate once per second, but only
; once per request. "0" means always validate)
;opcache.revalidate_freq=2

; Enables or disables file search in include_path optimization
;opcache.revalidate_path=0

; If disabled, all PHPDoc comments are dropped from the code to reduce the
; size of the optimized code.
;opcache.save_comments=1

; If disabled, PHPDoc comments are not loaded from SHM, so "Doc Comments"
; may be always stored (save_comments=1), but not loaded by applications
; that don't need them anyway.
;opcache.load_comments=1

; If enabled, a fast shutdown sequence is used for the accelerated code
;opcache.fast_shutdown=0

; Allow file existence override (file_exists, etc.) performance feature.
;opcache.enable_file_override=0

; A bitmask, where each bit enables or disables the appropriate OPcache
; passes
;opcache.optimization_level=0xffffffff

;opcache.inherited_hack=1
;opcache.dups_fix=0

; The location of the OPcache blacklist file (wildcards allowed).
; Each OPcache blacklist file is a text file that holds the names of files
; that should not be accelerated. The file format is to add each filename
; to a new line. The filename may be a full path or just a file prefix
; (i.e., /var/www/x  blacklists all the files and directories in /var/www
; that start with 'x'). Line starting with a ; are ignored (comments).
;opcache.blacklist_filename=

; Allows exclusion of large files from being cached. By default all files
; are cached.
;opcache.max_file_size=0

; Check the cache checksum each N requests.
; The default value of "0" means that the checks are disabled.
;opcache.consistency_checks=0

; How long to wait (in seconds) for a scheduled restart to begin if the cache
; is not being accessed.
;opcache.force_restart_timeout=180

; OPcache error_log file name. Empty string assumes "stderr".
;opcache.error_log=

; All OPcache errors go to the Web server log.
; By default, only fatal errors (level 0) or errors (level 1) are logged.
; You can also enable warnings (level 2), info messages (level 3) or
; debug messages (level 4).
;opcache.log_verbosity_level=1

; Preferred Shared Memory back-end. Leave empty and let the system decide.
;opcache.preferred_memory_model=

; Protect the shared memory from unexpected writing during script execution.
; Useful for internal debugging only.
;opcache.protect_memory=0

需要开发人员在php.ini中添加或删除注释Opcache相关配置即可。

[opcache]
; dll地址
zend_extension=/usr/local/php/lib/php/extensions/no-debug-zts-20160303/opcache.so
; 开关打开
opcache.enable=1
; 开启CLI
opcache.enable_cli=1
; 可用内存, 酌情而定, 单位为:Mb
opcache.memory_consumption=528
; Zend Optimizer + 暂存池中字符串的占内存总量.(单位:MB)
opcache.interned_strings_buffer=8
; 对多缓存文件限制, 命中率不到 100% 的话, 可以试着提高这个值
opcache.max_accelerated_files=10000
; Opcache 会在一定时间内去检查文件的修改时间, 这里设置检查的时间周期, 默认为 2, 定位为秒
opcache.revalidate_freq=1
; 打开快速关闭, 打开这个在PHP Request Shutdown的时候回收内存的速度会提高
opcache.fast_shutdown=1

重启 PHP,加载修改后的配置项

/etc/init.d/php-fpm restart

 

创建 phpinfo.php 

<?php
    echo phpinfo();
?>

 

查看 phpinfo.php 信息

http://localhost/phpinfo.php

php-kai-qi-you-hua-jia-su-mo-kuai-opcache-01

 

对于PHP之前的老版本,可以将Opcache作为PECL拓展库进行安装和配置,

或对于PHP 5.5以下版本的,需要使用APC加速,可以自行上网搜索PHP APC加速的方法。

 

OPcache 原理

Opcache 可以在 PHP 执行的时候,由解析器将PHP源码转换为字节码 byte-code

对于同一个 PHP 文件来说,假如每次执行的时候就需要转换一次,那就太影响性能了,因此出现了很多的加速模块,而从 PHP 5.5 开始 Opcache 已经成为官方标准的模块。假如你还是个新手,就不要去了解其它的加速模块了(比如 APC),因为既然是官方的,那么性能、稳定性、适配性各方面就不用太担心了,也有一些文章比较 APC cache 和 Opcache。

对于应用层的开发者来说,只要知道 Opcache 是一个 PHP 内置的加速模块就行,当 PHP 解析器在解析一个 PHP 文件的时候,假如该文件对应的 byte-code 存储在内存中,则省去了转换过程直接执行了;反之则会编译,并将编译后的 byte-code 存入到内存中(以文件名作为索引)。

不管是通过源码还是包安装,默认 Opcache 安装后是开启的,相关的参数类似于:

#/usr/local/php/lib/php.ini 

validate_timestamps=1
revalidate_freq=0
memory_consumption=64
max_accelerated_files=4000 
opcache.fast_shutdown=0

validate_timestamps 这个参数很重要,假如等于 0,那么 PHP 解析器只要发现内存中有对应 PHP 文件的 byte-code 内容就会加载,反应灵敏的同学可能会想,假如开发者修改了其开发的 PHP 代码,那么这个 byte-code 不就是“脏”内容吗,确实是这样的(如何解决呢?)。

假如 validate_timestamps 等于 1,PHP 解析器从内存中获取某个 PHP 文件对应的 byte-code,会通过一定的方法比较 byte-code 内容是不是最新的(读取文件系统),假如比较后发现 byte-code 已经过期,应该重新编译生成。

需要注意,PHP 解析器不是每次都会去检查(一切为了效率),检查的频率取决于 revalidate_freq 参数( 0 表示每次都检查)。

memory_consumption 代表这块内存区开辟的大小,另外需要注意不同 PHP SAPI 内存区不是共享的,就是说同一个 PHP 文件,运行在命令行模式或者 PHP-FPM 模式下,对应的 byte-code 会存储在不同的内存区中。

max_accelerated_files 表示内存区最大能存储的 PHP 文件数量。

 

Opcache 的运行状况

上面主要说了 Opcache 的定义、安装、配置、简单的运作机制,对于开发者来说,了解这些就足够了,但是可进一步了解 Opcache 到底缓存了什么,PHP 提供了一些函数(opcache_get_configuration()和 and opcache_get_status())获取配置信息和运行信息,比如了解那些文件被缓存了、使用了多少内存、内存命中率等等。我们一般只需要做两件事儿:

1、使用Opcache优化器,加快PHP程序的执行速度;

2、通过Opcache各项指标参数,实时了解当前PHP程序的性能状态;

 

 

使用 OpCacheGUI 可以更直观的获取运行信息。

Github上开源的项目:https://github.com/rlerdorf/opcache-status

将下载下来的项目放入到当前的Web服务器根目录下,直接访问即可,先看效果:

php-kai-qi-you-hua-jia-su-mo-kuai-opcache-02 

从上面的截图及项目文件看出,Opcache工具是一个简化的GUI版本,使用它可以清楚了解和分析下面的内容:

1、缓存使用情况、剩余情况及内存浪费情况及比例;

2、缓存的keys、剩余的keys数;

3、缓存命中数以及未命中数;

4、缓存配置、状态以及缓存捕获脚本;

5、缓存的脚本文件,以视图形式划分直观显示;

 

注意事项

1、不建议Xcache和Opcache同时启用PHP优化;

因为PHP 5.5.0及后续版本已经内嵌对Opcache的支持,所以PHP意识到其重要性,相对于Xcache等第三方的PHP优化器来说,使用Opcache会是更好的选择。另外,两者同时存在的话,会使Opcache的缓存命中数大大降低,而且增加不必要的开销。

 

2、不建议在开发过程中开启Opcache

原因很明显,开启了Opcache之后,开发人员修改的内容不会立即显示和生效,因为受到opcache.revalidate_freq=60的影响,所以建议在开发并测试之后,测试性能时再行打开测试,当然,生产环境一直都要开着Opcache

 

3、不建议将Opcache指标设置太大

Opcache各项指标配置大小或是否开启,需要结合项目实际情况需求及Opcache官方建议的配置,项目的实际情况分析,可结合上面第四部分的可视化缓存信息分析调整。

 

4、不建议长期使用老版本的Opcache

建议及时关注Opcache官网动态,实时了解其的bugs修复,功能优化及新增功能,以便更好的将其应用在自己的项目中。

 

5、不建议在生产环境中,将上面介绍的开源项目放入Web服务根目录

原因很简单,因为这个开源项目并未做访问的限制和安全处理,也就是说凡是可以访问外网的用户,只要知道了访问地址就可以直接访问,所以不安全。一般下,这个开源工具只是帮助可视化分析PHP的性能,通常在开发调试阶段使用。如果就是想在生产环境开启使用,那么就必须做好安全限制工作。

 

 

validate_timestamps 指令

其实写这篇文章,主要是了解这个指令,文档上建议生产环境不开启,开发环境不开启。
不开启的意思就是不校验 PHP 文件最近有没有修改过,主要是为了效率(参考前面讲的),那么如何解决文件更新带来的问题呢(让它保持最新),有两种方法:

第一种方法就是调用 opcache_reset() 函数,

第二种重启 PHP SPAI,比如运行service php5-fpm restart等。

但是上面两种方式都太凶残,假如开发的项目频繁上线,每次缓存区都要全部清空,可以使用opcache_invalidate()函数更新特定文件的缓存。

不管那种方式,为了清除失效的 byte-code,在部署代码的时候必然会有一些麻烦,可以写一些脚本来做到自动化更新缓存。

关闭这个指令的好处:

  • 不用频繁读取文件系统(校验内存中的 byte-code 是不是最新的)
  • 同个文件不会缓存多份(因为某个文件 byte-code 并不会因为过期而释放内存区)

 

 

参考推荐

A Simple Performance Comparison of HTTPS, SPDY and HTTP/2

Fine-Tune Your Opcache Configuration to Avoid Caching Suprises