Opcache全程Operation Code, 意为操作码。由于PHP是解释型语言,当解析器执行PHP脚本时会解析脚本代码,将它们生成可以直接运行的中间代码,称为Zend OpCode, 类似于Java的ByteCode。
Zend引擎
Zend引擎是PHP的编译引擎和执行引擎,当它执行一段PHP脚本时,会依次按照如下步骤执行:
- Scan:扫描,将PHP代码转换成语言片段。
- Parse:解析,将语言片段组合成有意义的表达式。
- Complie:编译,将表达式编译程OpCode。
- Excute:执行,顺次执行OpCode。
Nginx或其他Web服务器把HTTP请求转发给PHP-FPM, PHP-FPM再把请求交给某个PHP子进程处理,PHP进程找到PHP脚本后执行,把脚本编译为OpCode后生成响应。我们从图中看到PHP脚本被编译为Zend Opcode后生成内容,然后被发送到浏览器客户端。
如果每次请求一个PHP脚本都要编译一次Zend OpCode,然后执行字节码,就会消耗很多资源。如果每次HTTP请求PHP都必须不断解析、编译和执行PHP脚本,消耗的资源更多。如果有一个工具能缓存预告编译好的字节码,减少应用的响应时间,降低系统资源压力,这当然就是我们想要的方式—字节码缓存。
字节码缓存的共通特性就是能够存储预先编译的Zend OpCode,使用OpCode缓存后,当请求一个PHP脚本时,不用再读取、解析和编译PHP代码。PHP解释器会从内存中读取预先编译好的字节码,立即执行。这样就能节省很多时间,极大提升应用的性能。
Zend Opcache
在PHP5.5以后,Zend OpCache虽然被内置,但默认没有启用,需要显式指定启用Zend OpCache。
如果是自己编译的PHP运行环境,需要在configure命令时包含如下:
–enable -opcache
编译好,须在php.ini文件中配置Zend OpCache。
1 | zend_extension=opcache.so |
重启PHP FPM,使用phpinfo函数查看,确认Zend OpCache是否正常工作,如图所示:
A/B测试
现在我们对开启Opcache效果进行A/B测试,以请求phpinfo.php为例。
未开启:
1 | Document Path: /phpinfo.php |
未开启状态下,TPS:255/s。
开启后:
1 | Document Path: /phpinfo.php |
开启后,TPS: 284/s, 性能提升11.4%, 开启后效果还是非常棒的。