今儿在azure里装php5.5.4,发现原先php5.4、php5.3中的zend guard laoder以及php5.2中的Zend Optimizer均不能再用,一直很喜欢用的eaccelerator也悲剧了,编译的时候直接提示错误。

没办法,翻看php5.5.4的安装目录,发现php的安装目录下的扩展库目录有个opcached.so;咦,这个文件是搞毛线的?看名字带cached,难道是个缓存系统?google了下,果不其然,这个是php5.5默认提供的php脚本缓存扩展,编译php5.5时加上参数--enable-opcache就可以编译opcache了,只是要启用的话必须配置。

一、PHP中opcache的安装、加速效果与配置介绍

经过测试,php5.4、php5.3乃至php5.2也是可以使用opcache模块的,参考网络上的测试文章(http://www.cnblogs.com/xiaocen/p/3709850.html)发现:zend opcache(一般就直接简称为opcache了)的加速效率高于xcache,自然也就高于一年多不维护的eaccelerator了。另外,我的测试发现在php5.4上加载了eaccelerator加速扩展后,PHP代码中使用复杂调用preg_replace_callback函数的代码段后会引起严重的内存溢出(memory leak);而preg_replace函数在php5.5已经不再建议使用,而是改用preg_replace_callback代替,从这个层面来说,弃用eaccelerator是一个明智的选择。

低于PHP5.5版本(5.5及其以上版本只需要在编译php的时候加上 --enable-opcache参数即可完成如下编译过程,最后配置启用即可)的php要安装opcache也很简单,下载zend opcache(http://pecl.php.net/package/ZendOpcache),比如下载zendopcache-7.0.3.tgz,那么编译安装就很简单了,代码如下:

 
 
  1. tar zxvf zendopcache-7.0.3.tgz
  2. cd zendopcache-7.0.3
  3. phpize
  4. #若环境变量未加入phpize的路径
  5. #则执行phpize命令时需要加上路径 加环境变量具体请参考 http://blog.jjonline.cn/linux/165.html
  6. #如你的php安装在 /usr/local/php下,那么此处应该输入
  7. #/usr/local/php/bin/phpize
  8. ./configure
  9. #同理,php安装目录下的bin目录以及sbin目录没有加入环境变量的话就需要加上参数
  10. #--with-php-config=/usr/local/php/bin/php-config #路径依据具体路径
  11. make && make install
  12. #make install 后会提示编译出的opcache.so文件的位置,在php.ini加上相关配置段即可

参考网络上的关于opcache的介绍:新一代PHP加速器,由Zend公司研发,其实现原理与Xcache类似,都是把PHP执行后的数据缓冲到内存中从而避免重复的编译过程,能够直接使用缓冲区已编译的代码从而提高速度,降低服务器负载,但性能却比Xcache更加优越,详见下方测试结果图。其机理简单点说就是将php脚本在虚拟机(暂且称php最终的机器码执行引擎为虚拟机吧)中的机器码或相应的服务器能够直接运行的代码给缓存起来,等到用户下次请求该脚本时就略过了php脚本代码转换为机器码的过程,从而达到加速php运行、起到缓存的效果。

zendopcache与xcache效率对比图

如何配置启用opcache呢?

 
 
  1. zend_extension = __Dir__opcached.so
  2. opcache.force_restart_timeout=3600
  3. opcache.memory_consumption=1024
  4. opcache.optimization_level=1
  5. opcache.interned_strings_buffer=8
  6. opcache.max_accelerated_files=4096
  7. opcache.revalidate_freq=60 ;检测php文件变动频率 单位秒 多少秒检测下php文件是否变动
  8. opcache.fast_shutdown=1
  9. opcache.enable=1
  10. opcache.enable_cli=1
  11. #配置中的__Dir__请更换成opcached.so文件的存放位置 一般在php文件目录的下的lib/extension下的目录中寻找

opcache的缓存代码块是可以使用内存的,具体依据配置参数而定;不再多介绍。

opcached.so被加载后,所有脚本执行时通过phpinfo就可以看到高速缓存的命中率,如下图中的Cache hits是12,而Cache misses为1

zend opcache

那么这个高速缓存如何被清理呢?依然通过配置文件配置,具体项目就是opcache.force_restart_timeout,通过指定该时间,在多少时间内容该缓存失效。

看到本文过来的关键词,有人在问如何关闭opcache,其实很简单,配置文件中将相关引入opcahe扩展的配置项注释掉即可(php配置文件中的注释可以使用英文分号,即在相关opcache的配置项行首位置加入英文分号,然后保存,重启apache或php-fpm即可)。

二、启用opcache后的一些情况

典型的就是由于opcache的缓存加速机制导致的代码变更后无法立即看到效果。php代码被转换成可立即执行的“机器码”后会有一定的缓存时间后才会去检查原始的PHP文件是否变动过,具体视配置项opcache.revalidate_freq设置的秒数情况而定;这样就会导致某些情况下明明更新了PHP文件中的代码,但执行后却看不到改变后的效果,这就是因为opcache检查php文件变动的间隔时间尚未结束所导致。

这个问题并不是bug,而要视具体生产环境来设定opcache.revalidate_freq值,倘若php代码很少变动,建议该值设置的大一些,可减少opcahce由于检查php文件变动而带来的额外开销,比如7200

那么在变动php文件后如何才能快速降低opcache缓存带来的这种问题呢?通过在opcache官网查询他的使用资料文档得知最简单的方法就是更新代码后重启下php-fpm(nginx fast-cgi模式)或apache(apache-handler模式)。当然还可以自己编写一个php脚本,调用opcache_reset()函数重置所有opcache缓存字节码,或者你还可以使用opcache_invalidate(PHPfileDir,true)重置指定php文件的缓存字节码。

---


其次在下面稍微介绍一下opcache的配置文件参数

名字 默认 可修改范围 含义
opcache.enable "1" PHP_INI_ALL 是否启用opcache
opcache.enable_cli "0" PHP_INI_SYSTEM 是否在CLI(即命令行时)启用opcache
opcache.memory_consumption "64" PHP_INI_SYSTEM 为opcache分配多少共享内存,单位M
opcache.interned_strings_buffer "4" PHP_INI_SYSTEM interned string的内存大小
opcache.max_accelerated_files "2000" PHP_INI_SYSTEM

最大缓存的文件数目。

实际上这个值会使用第一个大于你配置的数字的下列素数

{ 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 },

如你将该值指定为400,则实际上该值为463.

opcache.max_wasted_percentage "5" PHP_INI_SYSTEM  
opcache.use_cwd "1" PHP_INI_SYSTEM

如果置为1,则将当前路径加入到文件key中,

以避免可能产生的同文件名的文件key冲突

opcache.validate_timestamps "1" PHP_INI_ALL

如果置为1,则OPCACHE会自动检测文件的时间戳

(检测周期为revalidate_freq),

并根据文件的时间戳来更新opcode,如果置为0,

则只能手动去重启opcache或

重启webserver以使更新后的php文件生效

opcache.revalidate_freq "2" PHP_INI_ALL

opcache自动检测文件是否更新的周期,单位秒。

如果是0,则每次请求时opcache都要进行检测。

当validate_timestamps为0时,本指令无效。

opcache.revalidate_path "0" PHP_INI_ALL  
opcache.save_comments "1" PHP_INI_SYSTEM 是否保存文件中的注释
opcache.load_comments "1" PHP_INI_ALL

是否load comments,与save_comments联合起来使用,

如果该值为0,则即使save_comments为1,

那么php脚本中的comments也是不使用的

opcache.fast_shutdown "0" PHP_INI_SYSTEM

是否打开快速关闭,

打开时可使php在request shutdown时回收内存快

opcache.enable_file_override "0" PHP_INI_SYSTEM

如果置为1,则每次调用file_exist() is_file() is_readable()函数时,

opcache将要检查该文件是否被cache了,

这样增加了检查存在性和可读性的开销,

但避免了当validate_timestamps为disable时返回错误文件状态的风险。

opcache.optimization_level "0xffffffff" PHP_INI_SYSTEM 运行时控制优化的掩码(干什么的?)
opcache.inherited_hack "1" PHP_INI_SYSTEM 5.3以前使用。5.3后废弃
opcache.dups_fix "0" PHP_INI_ALL 为解决“cannot redecllare class" 时,可将其置为1
opcache.blacklist_filename "" PHP_INI_SYSTEM

设置黑名单文件,符合黑名单文件中定义的php文件将不被opcache。黑名单文件的例子如下:

; Matches a specific file.
/var/www/broken.php
; A prefix that matches all files starting with x.
/var/www/x
; A wildcard match.
/var/www/*-broken.php
一行为一条规则,支持通配符,注释以分号开头
opcache.max_file_size "0" PHP_INI_SYSTEM 被cache的文件的最大size,单位bytes。0表示不限
opcache.consistency_checks "0" PHP_INI_ALL

如果置为N,N非零,则opcache会每N个请求核实一下cache的检验和。

这会损害性能,应该只在debug时使用

opcache.force_restart_timeout "180" PHP_INI_SYSTEM 如果opcache处于非active状态,当N秒后opcache将自动重启
opcache.error_log "" PHP_INI_SYSTEM opcache自身的errorlog文件路径,为空时则使用stderr
opcache.log_verbosity_level "1" PHP_INI_SYSTEM 日志记录level,默认只有fatal error和error
opcache.preferred_memory_model "" PHP_INI_SYSTEM

opcache首选使用的内存模型,为空时会选择最适当的模型。

常用的有,mmap shm posix 和win32

opcache.protect_memory "0" PHP_INI_SYSTEM

运行php脚本时保护共享内存防止意外的写入。

只对debug时有用。

opcache.mmap_base NULL PHP_INI_SYSTEM  

转载请注明本文标题和链接:《php中的脚本加速扩展opcache

Logo

更多推荐