composer install 慢的根本原因是默认单线程串行处理依赖,i/o 和阻塞占时超70%;升级至2.2+、禁用钩子插件、启用--concurrency并发、优化镜像源与文件系统写入可显著提速。

composer install 为什么慢得像在编译内核?
根本原因不是网络,而是 PHP 进程串行解析 composer.lock、逐个发起 HTTP 请求、解压、校验、写入磁盘——尤其当依赖超过 50 个时,I/O 等待和单线程阻塞会吃掉 70% 以上时间。
官方 composer install 默认不并发,哪怕你机器有 16 核、千兆宽带,它也只开 1 个 HTTP 连接、1 个解压进程。
实操建议:
- 别碰
COMPOSER_PROCESS_TIMEOUT或盲目调高memory_limit——这解决不了并发瓶颈 - 确认你用的是 Composer 2.2+(
composer --version),低于此版本不支持原生并行下载 - 禁用所有非必要插件:
composer global config -g disable-tls true无意义,反而危险;真正要关的是composer-unused、phpstan-extension-installer这类钩子型插件,它们会在每个包安装后触发,放大串行延迟
启用 composer-parallel-install 是最直接的提速方式
这不是第三方“加速插件”,而是 Composer 官方在 2.2 中合并的内置能力,通过 --concurrency 控制并发数,底层复用 cURL multi 和进程池,无需额外安装扩展。
常见错误现象:加了 --concurrency=8 但速度没变化 → 很可能是你的镜像源(如阿里云、腾讯云)本身限流或不支持 HTTP/2 多路复用,导致并发请求被排队堵死。
实操建议:
- 优先用官方源测试基准速度:
composer config -g repo.packagist composer https://packagist.org - 再执行:
composer install --concurrency=6 --no-interaction --no-progress(--concurrency值设为 CPU 核心数 × 1.5,但不超过 12) - 若仍卡在某个包(比如
symfony/console),用strace -e trace=openat,connect,write -p $(pgrep -f "composer install")看是否在反复重试 DNS 或 TLS 握手——这时要换 DNS(如1.1.1.1)或加export COMPOSER_NO_TLS=1(仅限内网可信环境)
vendor 目录写入慢?关掉 fsync 和杀毒实时扫描
Composer 并行下载快了,但解压完往 vendor/ 写文件时可能又卡住——特别是 macOS APFS 或 Windows NTFS + 实时防病毒软件(如 Windows Defender、腾讯电脑管家)会同步拦截每个 file_put_contents 调用。
性能影响比想象中大:一个 2MB 的
.tar` 包解压成数百个小文件,fsync 触发次数 ≈ 文件数,每秒写入从 120MB 掉到 8MB。</p> <p>实操建议:</p> <ul> <li>Linux/macOS:临时关闭 sync:<code>composer install --concurrency=8 --no-scripts && sync && echo 3 | sudo tee /proc/sys/vm/drop_caches(仅用于 CI 环境,开发机慎用)
composer install --no-plugins --no-scripts,后续用 composer run-script post-install-cmd 单独触发脚本——避免脚本在并发写入中途干扰CI 环境下进一步压榨:缓存 lock + 并行 + 分层 vendor
GitHub Actions / GitLab CI 每次都重装 vendor 是最大浪费。单纯缓存 vendor/ 目录不可靠(不同 PHP 版本、扩展差异会导致运行时错误),必须配合 composer.lock 和平台约束。
容易踩的坑:用 cache: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} 却没锁死 PHP 版本 → 缓存命中后 ext-redis 版本不一致,composer install 静默跳过但运行时报 Class Redis not found。
实操建议:
- 在
composer.json显式声明:"config": { "platform": { "php": "8.2.12" } } - CI 脚本分三步:
①composer install --dry-run --no-plugins验证 lock 兼容性
②composer install --concurrency=10 --no-interaction --no-progress --no-scripts
③composer run-script post-install-cmd - 不要缓存整个
vendor/,缓存~/.composer/cache+composer.lock哈希即可,体积小、命中率高、无污染风险
真正的极限优化不在参数调多大,而在于让每一步都可预测、可跳过、不互相拖累。比如一个 post-install-cmd 里执行 php-cs-fixer fix,它会等全部 vendor 写完才启动,而这个过程本身是单线程的——这种地方,比改 --concurrency 值重要十倍。










