PHP 开启 opcache 提高性能

开启opcache性能提高10倍

opcache开启方法

以lnmp.org站点下载的lnmp包为例:

# 开启opcache
cd /home/lnmp1.4-full

sudo ./addons.sh install opcache

# 配置opcache
/usr/local/php/etc/php.ini

# 按照服务器性能配置如下参数
[opcache]
opcache.enable=1    # 启用 OPcache
opcache.memory_consumption=512      # OPcache 的内存空间(M)
opcache.interned_strings_buffer=64      # 实际字符串的空间(单位:MB)
opcache.max_accelerated_files=32531     # 可以缓存多少个脚本,将这个值尽可能设置为与项目包含的脚本数接近或更大
opcache.validate_timestamps=0   # 0表示不自动释放缓存,性能最佳
opcache.save_comments=0     # 在脚本中保留注释,若存在库需要注释,设为1
opcache.revalidate_freq=0  # 控制了 PHP 缓存(Opcode 缓存)多少秒检查一次文件的修改时间; 0 标识不检查,需要php reload后才更新代码
~opcache.fast_shutdown=0~     # 从 PHP 7.2.0 开始被移除,不需要配置;快速关闭,打开这个在PHP Request Shutdown的时候回收内存的速度会提高
opcache.error_log=/alidata/log/php/php_errors.log

opcache 配置项参考文档: https://www.php.net/manual/zh/opcache.configuration.php

opcache开启后,每次更新代码执行命令:

sudo lnmp php-fpm reload

opcache状态查看开源项目:
https://github.com/rlerdorf/opcache-status
部署该项目,查看 访问opcache.php 文件,可以查看opcache使用情况

opcache 原理介绍

OPCache 是官方的Opcode(Operate Code) 缓存解决方案,它将PHP编译产生的字节码以及数据缓存到共享内存中, 在每次请求,从缓存中直接读取编译后的opcode,进行执行。

通过节省脚本的编译过程,提高PHP的运行效率。

说明:

从PHP代码的生命周期来看,请求PHP脚本时,会经过五个步骤,如下所示:

PHP 代码 => Token => 抽象语法树 => Opcodes => 执行

各个步骤内容如下:

1、源代码通过词法分析得到 Token

Token(语言片段) 是 PHP 代码被切割成的有意义的标识。PHP7 一共有 137 种 Token,在 zend_language_parser.h 文件中做了定义。

2、基于语法分析器将 Token 转换成抽象语法树(AST)

Token 就是一个个的词块,但是单独的词块不能表达完整的语义,还需要借助一定的规则进行组织串联。所以就需要语法分析器根据语法匹配 Token,将 Token 进行串联。语法分析器串联完 Token 后的产物就是抽象语法树(AST,Abstract Syntax Tree)。
AST 是 PHP7 版本的新特性,之前版本的 PHP 代码的执行过程中是没有生成 AST 这一步的。它的作用主要是实现了 PHP 编译器和解释器的解耦,提升了可维护性。

3、将语法树转换成 Opcode

需要将语法树转换成 Opcode,才能被引擎直接执行。

4、执行 Opcodes

opcodes 是 opcode 的集合形式,是 PHP 执行过程中的中间代码。PHP 工程优化措施中有一个比较常见的 “开启 opcache”,指的技术这里将 opcodes 进行缓存。通过省去从源码到 opcode 的阶段,引擎直接执行缓存好的 opacode,以提升性能。

Opcache 会缓存OPCode以及如下内容:

PHP脚本涉及到的函数

PHP脚本中定义的Class

PHP脚本文件路径

PHP脚本OPArray

PHP脚本自身结构/内容

引用链接

[1] https://www.php.net/manual/zh/opcache.configuration.php: https://www.php.net/manual/zh/opcache.configuration.php
[2] https://github.com/rlerdorf/opcache-status: https://github.com/rlerdorf/opcache-status