dump-autoload在Swoole中“漏内存”是因为其触发的autoload注册、PSR-4映射加载及files全量读取行为在常驻进程中反复叠加,每次执行新建ClassLoader实例且旧实例未销毁,静态缓存持续堆积,导致RSS持续上涨且GC后不回落。

dump-autoload 为什么在 Swoole 里会“漏内存”
因为 dump-autoload 本身不泄漏,但它触发的 autoload 注册、PSR-4 映射加载、autoload.files 全量读取行为,在常驻进程里会反复叠加——每次执行都 new 一个 Composer\Autoload\ClassLoader 实例,而旧实例没被销毁,静态缓存(如 Composer\Autoload\ClassMapGenerator::$classMap)也持续堆积。
典型现象:Swoole Worker 进程 RSS 每次调用 composer dump-autoload 后上涨 10–50MB,且 GC 后不回落;var_dump(spl_autoload_functions()) 返回多个不同 ID 的 ClassLoader::loadClass 回调。
- 不要在 onReceive/onRequest 中动态执行
dump-autoload—— 它不是运行时 API,而是构建期命令 - 确认是否误将
vendor/autoload.php在每次请求中重复require(比如在中间件里写了require_once __DIR__.'/../vendor/autoload.php') -
autoload.files里若引入了大体积 helpers.php(含数百函数),dump-autoload阶段会全量include_once进内存,且不会释放
如何验证是不是 autoload 注册导致的累积
在 Worker 启动后、首次调用 dump-autoload 前,执行:
php -r "print_r(spl_autoload_functions());"
记录输出中 ClassLoader 对象数量和 ID;再执行一次 composer dump-autoload,重新运行上面命令对比。若对象数量增加、ID 不同,说明注册未清理。
- 检查是否手动调用了
ClassLoader::register()多次,尤其在自定义插件或热重载逻辑里 - 禁用所有 Composer 插件:
composer dump-autoload --no-plugins,观察内存增长是否消失 - 用
gc_collect_cycles()+gc_mem_caches()后立刻看 RSS,不降 = 强引用仍在(比如闭包 use 了 $loader)
生产环境禁止在 Swoole 进程里跑 dump-autoload
这个命令设计目标是生成静态映射文件(vendor/composer/autoload_classmap.php 等),不是运行时重载机制。在常驻进程中执行,等于把构建逻辑塞进服务生命周期,必然破坏内存稳定性。
- 正确做法:CI 构建阶段执行
composer dump-autoload -o --no-dev,生成优化后的 classmap,然后把整个vendor/打包部署 - 若需热更新 autoload(极少见),应重启 Worker 进程,而不是 reload autoload —— Swoole 没有安全的 “unregister + re-register” autoload 链路
- 误用
--classmap-authoritative会导致 classmap 漏类后直接 fatal error,且该模式下 classmap 缓存更难清理,加剧 RSS 上涨
最容易被忽略的陷阱:opcache + realpath cache 双重滞留
Swoole 进程长期运行时,PHP 的 opcache 和 realpath_cache 都不会自动刷新。即使你删了旧 vendor/、替换了新 autoload_*.php,opcache 仍执行旧字节码,realpath cache 还指向旧路径 —— 导致 dump-autoload 生成的新文件根本没被加载,而旧 loader 却还在内存里挂着。
- 必须在
dump-autoload后调用opcache_reset()(CLI 下有效),Web 环境则需配置opcache.validate_timestamps=1并设合理opcache.revalidate_freq - PHP 8.2.0–8.2.3 / 8.3.0 存在 realpath cache 不释放 Bug,
realpath_cache_size()会持续上涨;临时解法是启动时加-d realpath_cache_size=4194304 - 别信
clearstatcache(true)—— 它对 realpath cache 无效,得用realpath_cache_clear()
dump-autoload 本身,而是它暴露了项目结构松散、autoload 注册失控、缓存策略缺失这些底层问题。一旦进程常驻,所有“只跑一次”的假设都会失效。


















