PHP-FPM worker RSS持续上涨、slowlog频发主因是Composer autoload_classmap.php全量加载与opcache.interned_strings_buffer不足共同引发内存碎片;需精简classmap并按真实占用调高interned_strings_buffer至16~64MB。

PHP-FPM 单个 worker 进程 RSS 持续上涨、slowlog 频发但代码无明显泄漏,大概率是 Composer Autoload + OPcache 共同导致的内存碎片,而非 PHP 本身没释放变量。
autoload_classmap.php 被全量 require 进每个进程,直接推高 RSS
Composer 生成的 autoload_classmap.php 是一个纯 PHP 数组文件,内容常达数 MB。PHP-FPM 每个 worker 启动时都会 require 它一次——不是只加载一次共享,而是每个进程独立解析并存入自己的内存空间。
- 该文件无法被 OPcache 的共享内存段高效复用,因为它是动态结构(大数组),OPcache 更擅长缓存函数/类定义体
- 若项目用了
"classmap": ["src/", "tests/"]这类宽泛配置,autoload_classmap.php会包含大量实际不用的类路径,白白占用内存 - 检查方法:运行
php -r "echo memory_get_peak_usage() / 1024 / 1024;" -f vendor/autoload.php,看是否 >3MB
opcache.interned_strings_buffer 不足会加剧碎片
当 autoload_classmap.php 被加载,其中成千上万个类名字符串会被 intern。若 opcache.interned_strings_buffer 太小(默认仅 8MB),就会频繁触发字符串池重哈希和内存重分配,造成堆碎片。
- 现象:
opcache_get_status()['interned_strings_usage']['free_memory']长期低于 1MB,且opcache_get_status()['memory_usage']['used_memory']波动剧烈 - 不要盲目调大
opcache.memory_consumption,先看interned_strings_usage是否吃紧 - 建议值:中小型项目设为
16,大型 Laravel 项目建议32或64(单位 MB)
--classmap-authoritative 实际加重碎片?要看 classmap 是否真精简
--classmap-authoritative 关闭 fallback 后,自动加载器不再调用 file_exists(),看似减少系统调用,但前提是 autoload_classmap.php 本身足够轻。如果它仍混着 tests/、docs/、examples/ 的路径,就只是把碎片从“磁盘扫描”换成了“内存膨胀”。
立即学习“PHP免费学习笔记(深入)”;
- 错误示范:
"autoload": {"psr-4": {"Tests\": "tests/"}}没加--no-dev,测试类全进 classmap - 正确做法:部署命令必须是
composer install --no-dev --optimize-autoloader --classmap-authoritative,且composer.json中删掉所有非生产 autoload 条目 - 验证:打开
vendor/composer/autoload_classmap.php,搜索tests/或phpunit,不应出现任何匹配
真正可控的内存碎片点不在代码层,而在 classmap 的体积和 intern 字符串池的配比——这两者都必须用真实数据校准,而不是按文档抄参数。



















