鸟哥的博客 让PHP7达到最高性能的几个Tips 中,第一点就提到了Opcache;
部分原文如下:
记得启用Zend Opcache, 因为PHP7即使不启用Opcache速度也比PHP-5.6启用了Opcache快,所以之前测试时期就发生了有人一直没有启用Opcache的事情.
那么,Opcache 到底是什么,为什么启用了Opcache 后PHP就会有如此高的性能提升?
相比于C/C++、Java而言,PHP、Python属于解释型语言,不产生机器码,而是产生中间码,我们把这个中间码称为 “Opcode”;
Opcode是一种PHP脚本编译后的中间语言,就像Java的ByteCode,或者.NET的MSL,举个例子,比如你写下了如下的PHP代码:
<?php
echo "Hello World";
$a = 1 + 1;
echo $a;
?>
PHP执行这段代码会经过如下4个步骤:
1.Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)
2.Parsing, 将Tokens转换成简单而有意义的表达式
3.Compilation, 将表达式编译成Opocde
4.Execution, 顺次执行Opcode,每次一条,从而实现PHP脚本的功能。
而我们的代码,每次运行都会重复上面的四步;
但是,业务逻辑和功能一旦完成,处于生产阶段时,代码是基本不会变化的,因此,我们大多数时间并不需要重新编译生成Opcode;
如果我们可以将每次生成的Opcode保存下来,也就是省略前三步的编译过程,只执行第四步,那么我们PHP代码的执行效率将会得到一个质的提升;
而 OPcache 就是PHP官方提供的保存Opcode的工具,基本原理就是通过将 PHP 脚本预编译的字节码存储到共享内存中,省去了每次加载和解析 PHP 脚本的开销,从而大大提升 PHP 的性能。
在PHP 5.5.0 及后续版本中,官方已经绑定了 OPcache 扩展,不需要我们额外添加;对于 PHP 5.4及之前的版本可以使用 PECL 扩展中的 OPcache 库。
不管使用什么版本的PHP,都需要在php.ini中添加下面的代码,引入扩展:
保存php.ini并退出编辑器后,查看扩展是否引入成功:
在确定Opcache扩展库存在之后,接下来的工作就是修改php.ini 配置文件,启动Opcache即可;
以下是西岭老湿给出的简单配置,并且也已经表明了注释含义;
如果想具体查看其他配置及细节,请查看官方文档:
http://php.net/manual/zh/opcache.configuration.php
//启用操作码缓存。如果禁用此选项,则不会优化和缓存代码。
//在运行期使用 ini_set() 函数只能禁用 opcache.enable 设置,不可以启用此设置。
//如果在脚本中尝试启用此设置项会产生警告。
opcache.enable=1
//仅针对 CLI 版本的 PHP 启用操作码缓存。
//通常被用来测试和调试。
opcache.enable_cli=1
//OPcache 的共享内存大小,以兆字节为单位。
//官方建议值 128
opcache.memory_consumption=64
//用来存储临时字符串的内存大小,以兆字节为单位.
//PHP 5.3.0之前的版本会忽略此配置指令。
//官方建议值 8
opcache.interned_strings_buffer=8
//OPcache 哈希表中可存储的脚本文件数量上限。
//真实的取值是在质数集合 { 223, 463, 983, 1979, 3907,
// 7963, 16229, 32531,65407, 130987 }
//中找到的第一个大于等于设置值的质数。
//设置值取值范围最小值是 200,
//最大值在 PHP 5.5.6 之前是 100000,
//PHP 5.5.6 及之后是 1000000。
//官方建议值 4000
opcache.max_accelerated_files=4000
//检查脚本时间戳是否有更新的周期,以秒为单位。
//设置为 0 会导致针对每个请求,
//OPcache 都会检查脚本更新。
//也可以简单理解为 缓存时长
opcache.revalidate_freq=30
//如果启用,则会使用快速停止续发事件。
//所谓快速停止续发事件是指依赖 Zend
//引擎的内存管理模块 一次释放全部请求
//变量的内存,而不是依次释放每一个已分配的内存块。
opcache.fast_shutdown=1
修改之后,重启服务器与php相关进程即可;
紧接着,我们对其效果进行测试:
代码文件如下:
<?php
echo 1;
?>
使用浏览器访问后,结果为 1 ;这是正常的;
但是紧接着修改代码,速度要快:
<?php
echo 2;
?>
使用浏览器访问后,结果仍然为 1 ;
不断刷新,大约30秒过后,输出结果为 2;
30秒的间隔就是Opcache为我们缓存了代码造成的;