FrankenPHP 不支持 OPcache 预加载,因其嵌入式 Go 服务器不触发 PHP 引擎的持久化进程初始化阶段,导致 opcache.preload 无效;但普通 OPcache 缓存仍可启用并显著提速。

FrankenPHP 默认不支持 OPcache 预加载
直接说结论:opcache.preload 在 FrankenPHP 中无效,无论你怎么配 php.ini,重启服务后 opcache_get_status() 的 preload_statistics 字段永远为空,opcache.preload 路径也不会被加载。
根本原因在于 FrankenPHP 不基于传统 PHP-FPM 或 mod_php 启动模型——它用 Go 编写的 HTTP 服务器直接嵌入 PHP 解释器(via PHP-CPP),启动时不会触发 PHP 引擎的“持久化进程初始化阶段”,而预加载机制恰恰依赖这个阶段执行 preload.php 并将字节码钉入共享内存。
你可能会看到这些现象:
-
php -v显示 PHP ≥ 7.4,php --ini确认opcache.enable=1且opcache.preload=/path/to/preload.php已设置 - 但
php -m | grep opcache正常,opcache_get_status()['preload_statistics']却是null - 访问 Laravel 应用时,
get_included_files()不包含 preload.php 里require_once的任何类文件
那 FrankenPHP 上的 Laravel 还能用 OPcache 吗?
能,但仅限普通 OPcache 缓存:即脚本首次请求时编译字节码并缓存,后续请求复用。这已经能显著提速,尤其对路由、中间件、Blade 模板等高频文件。
立即学习“PHP免费学习笔记(深入)”;
关键配置仍需生效(放在 php.ini 或 FrankenPHP 的 php-config 块中):
opcache.enable=1-
opcache.memory_consumption=256(Laravel vendor 文件多,建议 ≥128) -
opcache.max_accelerated_files=100000(默认 10000 完全不够) opcache.interned_strings_buffer=32opcache.fast_shutdown=1
注意:FrankenPHP 的 php-config 是 YAML 格式,不是 ini;若你用 frankenphp.yaml,需写成:
php-config: opcache.enable: "1" opcache.memory_consumption: "256"
想绕过限制强行“模拟预加载”?别试
有人尝试在 public/index.php 开头 require_once 所有核心类,或用 opcache_compile_file() 批量编译——这看似“提前加载”,实则无效:
-
opcache_compile_file()只编译不执行,无法让类/函数全局可用(预加载的核心价值) - 在
index.php中require会污染请求生命周期,可能引发Cannot declare class XXX错误(尤其配合 Composer 自动加载时) - FrankenPHP 的每个请求是独立的 PHP 执行上下文,没有跨请求的“常驻内存”概念,所谓“模拟”只是徒增开销
更糟的是,这类操作会让 Laravel 的自动加载器(vendor/autoload.php)和框架本身的类注册逻辑冲突,调试时日志里频繁出现 Class not found 或 Cannot redeclare function。
真正值得投入的替代方案
既然预加载走不通,就把优化重心移到 FrankenPHP 原生优势上:
- 用
php artisan config:cache和php artisan route:cache—— 这些缓存文件是纯 PHP 数组,OPcache 能高效缓存,效果接近预加载的“免解析”收益 - 启用 FrankenPHP 的
static-files直接服务public/下资源,绕过 PHP 层,比 Nginx + PHP-FPM 更快 - 把高频工具类(如自定义的
StrHelper、JsonResponseBuilder)抽成独立小包,用 Composer 的classmap生成扁平 autoload,减少自动加载器遍历开销
最后提醒一句:FrankenPHP 的性能瓶颈通常不在类加载,而在事件循环调度和协程 I/O。与其纠结预加载,不如检查是否误用了同步阻塞调用(比如没加 co\run 就直接 file_get_contents 远程 API)——那才是拖慢整个服务的真凶。



















