PHP预加载(opcache.preload)通过在服务启动时编译并常驻类、函数、常量至共享内存,跳过每次请求的文件I/O与编译过程,显著降低单请求耗时;它不减少HTTP请求数,仅优化PHP内部加载路径。

PHP预加载(opcache.preload)不是“减少HTTP请求”,而是直接砍掉每个PHP请求里最耗时的文件I/O和编译环节——它让类、函数、常量在服务启动时就进内存,后续所有请求都不再走require、include或自动加载器的磁盘读取流程。
opcache.preload为什么能绕过文件I/O
普通请求中,哪怕只是new Router(),PHP也要按自动加载规则找到Router.php、打开文件、读取内容、词法分析、语法解析、生成字节码、存入OPcache——这一整套操作涉及多次系统调用和磁盘寻道。而opcache.preload在PHP-FPM master进程启动时,就用opcache_compile_file()或require_once把指定文件编译好并常驻共享内存。之后所有worker进程直接复用这些已编译的字节码,跳过全部文件读取和编译步骤。
- 实测显示:一个含20个核心类的网关项目,启用预加载后单请求平均节省 0.8–1.2ms 文件加载时间(尤其在机械硬盘或高IO压力下更明显)
- 注意:
opcache.preload不改变HTTP请求数量,也不合并JS/CSS——它只作用于PHP自身的代码加载路径 - 若你误以为它能减少前端资源请求数,那是混淆了「PHP服务端预加载」和「HTML的」
preload.php里该用require_once还是opcache_compile_file()
两者行为完全不同,选错会导致类找不到或静态状态错乱:
-
require_once:真实执行文件,会触发class_alias、define()、if (PHP_VERSION_ID > 80000) { ... }等运行时逻辑,但依赖顺序必须严格(比如先加载父类再加载子类) -
opcache_compile_file():只编译不执行,跳过所有if/define/赋值语句,适合批量加载纯类定义文件(如vendor/symfony/http-foundation/Response.php),但无法处理含条件逻辑的引导文件 - 推荐组合:用
opcache_compile_file()加载框架和业务类,用require_once加载vendor/autoload.php或自定义配置入口——后者需要执行自动加载注册逻辑
哪些类绝对不该预加载
预加载的类字节码是进程级共享的,其静态属性、全局变量会在所有请求间共用——这极易引发数据污染:
立即学习“PHP免费学习笔记(深入)”;
- 含静态缓存数组的工具类:
class CacheHelper { public static $data = []; }→ 多请求写入会互相覆盖 - 单例实例化代码:
private static $instance = null; public static function getInstance() { if (self::$instance === null) self::$instance = new static(); return self::$instance; } - 依赖运行时环境的类:比如根据
$_SERVER['HTTP_HOST']初始化的路由映射器 - 正确做法:只预加载结构稳定、无副作用的类——
Symfony\Component\HttpFoundation\Request、App\Http\Kernel、Eloquent基类等
配置生效但类仍报Class not found的常见原因
这不是代码问题,而是预加载链路中的静默失败点:
-
opcache.preload值必须是**绝对路径**,且PHP-FPM master进程用户(如www-data)要有读取权限;../preload.php或~开头的路径一定失败 -
opcache.enable=1和opcache.memory_consumption(建议≥256)必须启用,否则预加载脚本自己都进不了OPcache - 修改
php.ini后必须重启PHP-FPM(systemctl restart php8.3-fpm),仅重载配置无效 - Windows系统不支持
opcache.preload,这个限制至今未变 - 验证是否生效:
opcache_get_status()['preload_statistics']['memory_consumption'] > 0且opcache_get_status()['preload_statistics']['file_count']有值
真正容易被忽略的是:预加载后,你改了类文件内容,它不会自动更新——必须重启PHP-FPM。这点在热更新频繁的开发环境里,比性能提升本身更值得警惕。



















