• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

PHP加速器之opcache配置详解

PHP 彭东稳 8年前 (2016-07-28) 30702次浏览 已收录 1个评论

一、什么是opcode?

当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode)。Opcode cache的目地是避免重复编译,减少CPU和内存开销。如果动态内容的性能瓶颈不在于CPU和内存,而在于I/O操作,比如数据库查询带来的磁盘I/O开销,那么opcode cache的性能提升是非常有限的。但是既然opcode cache能带来CPU和内存开销的降低,这总归是好事。

二、为什么要使用opcode缓存?

这得从PHP代码的生命周期说起,请求PHP脚本时,会经过五个步骤,如下图所示:

PHP加速器之opcache配置详解

Zend引擎必须从文件系统读取文件、扫描其词典和表达式、解析文件、创建要执行的计算机代码(称为Opcode),最后执行Opcode。每一次请求PHP脚本都会执行一遍以上步骤,如果PHP源代码没有变化,那么Opcode也不会变化,显然没有必要每次都重行生成Opcode,结合在Web中无所不在的缓存机制,我们可以把Opcode缓存下来,以后直接访问缓存的Opcode岂不是更快,启用Opcode缓存之后的流程图如下所示:

PHP加速器之opcache配置详解

三、PHP opcode原理

Opcode是一种PHP脚本编译后的中间语言,就像Java的ByteCode,或者.NET的MSL,举个例子,比如你写下了如下的PHP代码:

PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend)

1)Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)。

2)Parsing, 将Tokens转换成简单而有意义的表达式。

3)Compilation, 将表达式编译成Opocdes。

4)Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。

四、PHP opcache介绍

Optimizer+(Optimizer+于2013年3月中旬改名为Opcache),OPcache通过将PHP脚本预编译的字节码存储到共享内存中来提升PHP的性能,存储预编译字节码的好处就是省去了每次加载和解析PHP脚本的开销。

PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。 对于 PHP 5.2,5.3 和 5.4 版本可以使用 » PECL扩展中的OPcache库。

PHP 5.5.0及后续版本

OPcache只能编译为共享扩展。如果你使用–disable-all参数禁用了默认扩展的构建,那么必须使用–enable-opcache选项来开启OPcache。编译之后,就可以使用 zend_extension 指令来将 OPcache 扩展加载到 PHP 中。

推荐的php.ini设置

使用下列推荐设置来获得较好的性能:

你也可以禁用 opcache.save_comments 并且启用 opcache.enable_file_override。 需要提醒的是,在生产环境中使用上述配置之前,必须经过严格测试。 因为上述配置存在一个已知问题,它会引发一些框架和应用的异常, 尤其是在存在文档使用了备注注解的时候。

以下是opcache的配置说明,其中给有值得都是默认配置:

最后说一下使用opcache加速php时应该注意的坑:

opcache依靠的是PHP文件的modify time作为文件被修改的检测条件,基于这个会引发两个问题。

第一个问题是做版本回滚时,由于版本回滚后的文件修改时间比现有opcache缓存的文件时间要往前一些,所以可能会导致opcache不会清除缓存,需要手动reload。

第二个问题是做版本发布时,一般都是sync方式,可能会出现文件发布一半时被opcache缓存,用户访问会报程序错误,这个主要是因为文件内容缓存了一半,但是文件的时间戳不会在改变,所以就算opcache检测时也不会去读取新的文件了,需要手动reload。

针对这两个问题,不光reload可以解决,同样调用opcache的接口也可以清除opcache缓存。

你可以使用opcache_reset()或者或者opcache_invalidate()函数来手动重置OPcache。

opcache_reset():该函数将重置整个字节码缓存,在调用opcache_reset()之后,所有的脚本将会重新载入并且在下次被点击的时候重新解析。

opcache_invalidate():该函数的作用是使得指定脚本的字节码缓存失效。 如果force没有设置或者传入的是FALSE,那么只有当脚本的修改时间 比对应字节码的时间更新,脚本的缓存才会失效。

但是不推荐使用,个人在生产环境中进行代码发布后调用opcache_reset()清空缓存(测试确实可以清空缓存),出现过奇葩问题(访问量大的应用),后来就果断放弃了,使用了reload的方式。


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (6)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!

(1)个小伙伴在吐槽