PHP OPcache 调优指南:jit、内存与命中率的参数怎么配
OPcache 调优其实就三件事:内存给够、文件数算准、生产环境把 `validate_timestamps` 关掉;JIT 是 PHP 8.0 以后才有的加分项,Web 场景从 `opcache.jit_buffer_size=64M` + `opcache.jit=1255` 起步即可,收益远小于前三个参数没配对带来的损失。
先把三个基础参数按比例配好
结论:`opcache.memory_consumption`、`opcache.interned_strings_buffer`、`opcache.max_accelerated_files` 必须一起调,只调其中一个基本等于没调。
- `opcache.memory_consumption`:缓存编译后字节码的内存。小型站点 128M 够用,中型社区 192M–256M。给太小会触发缓存淘汰,表现为命中率上不去、CPU 反而升高。
- `opcache.interned_strings_buffer`:驻留字符串池,默认 8M。PHP 8 时代各类框架/插件字符串多,建议 16M–32M,这个值偏小是「内存明明够却频繁重启缓存」的常见原因。
- `opcache.max_accelerated_files`:能缓存的脚本文件数上限。它会被系统向上取到质数集合里最接近的值,所以填 10000 实际生效的可能是 10691,不用纠结精确数字。经验算法:项目 PHP 文件数 × 2 起步。Clara BBS 这类插件化系统,插件目录 `content/plugins` 会随安装数量增长,建议直接给 20000。
三者的关系是:文件数不够 → 旧脚本被挤掉;字符串池不够 → 共享内存快速耗尽;内存不够 → 两者一起崩。所以要么全给足,要么别开。
validate_timestamps 决定你的命中率上限
结论:生产环境设 `opcache.validate_timestamps=0`,这是命中率从 90% 出头拉到 99%+ 的关键一步。
默认 `validate_timestamps=1`,OPcache 每隔 `opcache.revalidate_freq` 秒(默认 2 秒)去 `stat()` 每个脚本文件,看时间戳有没有变。文件一多,这堆 stat 系统调用本身就吃掉不少 IO。关掉之后 OPcache 完全信任内存里的字节码,不再回查磁盘。
代价是:改了 PHP 文件不会自动生效,必须重启 PHP-FPM 或调用 `opcache_reset()`。所以开发机、以及还在频繁改代码/装插件的站点,保持 `validate_timestamps=1`、`revalidate_freq=60` 更省心;正式上线且代码冻结了再关。
这里有个容易混淆的点:Clara BBS 的模板和插件是运行时钩子加载、保存即生效、不写编译缓存的,后台「系统工具→缓存清理」清掉的是站内应用缓存(`Cache::remember` 那一层),跟 PHP 的 OPcache 不是一回事。所以别指望点一下「缓存清理」去刷新 OPcache——关了 `validate_timestamps` 之后,正确做法是重启 PHP-FPM。
JIT 怎么配:版本、模式和容量
结论:JIT 只在 PHP 8.0+ 存在,PHP 7.4 没有这个选项,写进 php.ini 会被忽略;开启的最小配置是 `opcache.jit_buffer_size=64M` + `opcache.jit=1255`。
注意 `jit_buffer_size` 默认是 0,也就是说 PHP 8 装好了 JIT 默认也是关的,必须显式给值。
`opcache.jit` 是个四位数字,Web 应用常见的两档:
- `opcache.jit=1205`:函数级 JIT,编译开销小,适合请求短、代码路径分散的场景。
- `opcache.jit=1255`:tracing 模式,热点循环优化更彻底,适合计算密集代码。多数跑 PHP 8.2/8.3 的社区站可以直接用 1255。
JIT 对纯数据库+模板渲染的 Web 请求收益通常只有个位数百分比,别期待翻倍;真正吃到红利的是图像处理、加解密、复杂循环这类 CPU 密集逻辑。另外 JIT 缓冲区是从共享内存里另算的,开了 128M 的 JIT 就意味着 PHP 进程组多占 128M,小内存机器别贪大。
两个验证动作:看命中率、看缓存是否被打满
结论:调完不看 `opcache_get_status()` 就是盲调,命中率和 `wasted_memory` 是两个必看指标。
在站点根目录临时放一个脚本,打印 `opcache_get_status(false)`,重点看三项:
- `opcache_hit_rate`:稳定运行几天后应高于 99%;
- `memory_usage.free_memory`:长期接近 0 说明内存给小了;
- `memory_usage.wasted_memory` 与 `current_wasted_percentage`:持续增长说明不断有脚本被淘汰,通常是 `max_accelerated_files` 或字符串池不够。
顺手再确认 `opcache.enable=1`、`opcache.enable_cli=0`(除非你跑常驻 CLI 队列,Web 场景开 CLI 版纯属浪费内存)。云面板用户改完记得重启 PHP 服务,改 php.ini 不重启是不生效的。
收束
顺序别搞反:先按文件数×2 给 `max_accelerated_files`,再给 128M–256M 的 `memory_consumption` 和 16M 起步的字符串池,生产环境关掉 `validate_timestamps`,最后才考虑 PHP 8+ 的 JIT(`jit_buffer_size=64M`、`jit=1255`)。上线后用 `opcache_get_status()` 复核命中率与碎片,按数据再微调,比抄一份别人的 php.ini 靠谱得多。
转载请注明出处,版权归原作者所有。
星耀SVIP
管理员
黑卡会员





