PHP 8.3 で Composer の autoload を classmap に切り替えたときの実測と罠

这篇内容暂时只有 日本語 版本,以下是原文。

PHP 8.3、FPM 8.3.6、Debian 12 のコンテナ。依存パッケージは 180 個ほど、アプリ側のクラスが約 1,400。PSR-4 のまま composer dump-autoload -o で運用していたが、リクエストごとに vendor/composer/autoload_psr4.php の配列を引き、存在しないクラス名のたびに file_exists が走るのが気になっていた。プロファイルは取っていないが、opcache のヒット率が高くても autoload のスタックが上位に残るのが常だった。

やったことは単純で、composer.json に以下を足して classmap を併用させた。

"config": {
  "optimize-autoloader": true,
  "classmap-authoritative": true,
  "apcu-autoloader": true
}

生成は composer dump-autoload -o --classmap-authoritative。classmap-authoritative を入れると PSR-4 のフォールバック探索が無効になり、classmap に無いクラスはその場で「見つからない」と確定する。apcu-autoloader は APCu が有効な FPM でのみ効くので、CLI のバッチでは classmap をそのまま読む。デプロイは composer install --no-dev -o --classmap-authoritative をイメージビルド時に一度だけ実行し、実行時に dump しない。

仕組みとしては、classmap は vendor/composer/autoload_classmap.php の巨大な配列を opcache に載せ、探索を配列参照 1 回で済ませる。代わりに配列そのものがメモリを食う。手元では 1,400 クラスで 1 MB 前後、opcache の shared memory 使用量は数十 MB 増えた。APCu を挟むとプロセスごとのコピーを避けられるが、APCu の領域が小さいと apc.enable_cli 絡みで CLI 側が静かに落ちる。

効かない条件もはっきりしている。classmap-authoritative は実行時に eval や動的 require でクラスを読み込むコードと相性が悪い。うちでは古いプラグイン読み込みが require_once でクラスを後から足しており、classmap に無いため 500 になった。もう一つ、composer install をデプロイ先で走らせる運用だと、classmap がビルド時のファイル一覧に固定されるので、ホットフィックスでファイルを足した瞬間に壊れる。結局、動的読み込みの箇所だけ spl_autoload_register で明示的に登録する形に直した。

同じ構成で classmap-authoritative を外したときと比べて、autoload の所要は体感で減ったが、数字は取っていない。皆さんの環境では、動的読み込みと classmap の折り合いをどう付けていますか。

0
赞同度 100% · 0 条评论 · 5 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。