Composer の使い方(その3:オートローダーの最適化)

この記事は最終更新日から 3年以上 が経過しています。

前回、「Composer の使い方(その2:スクリプト)」の続きです。今回はオートローダーの最適化についてです。

オートローダーの最適化

デフォルトでは、Composer のオートローダーはクラスの名前を解決する際に、ファイルシステムのチェックを行っています。 新しくファイルが追加されたり削除されたりしても、オートローダーがそのファイルをすぐに検出して使用できるようするためなのですが、 この処理が有効であるがために、処理速度が大幅に低下している状態になっています。 開発環境などではとても便利なのですが、本番環境では不要な処理ですし、処理速度を少しでも向上させたいと考えるでしょう。 このため、このオートローダーの処理を最適化するための方法がいくつかあります。

最適化レベル1:Class map generation

最適化レベル1は、クラスマップというファイルを生成するというものです。 このクラスマップというのは、どのクラスがどのファイルにあるかというのが一覧で記載されたファイルです。 あらかじめ全てのファイルの場所を先に調べておくことで、実行時にファイルシステムのチェックを無くし、処理を高速化しようというものです。

このクラスマップというのは PHP ファイルです。 そのため、PHP 5.6 以降では、このクラスマップも OPcache にキャッシュされるため、初期化時間が大幅に短縮されます。 OPcache が有効になっていることを確認すると、クラスマップはほぼ瞬時に読み込まれ、クラスの読み込みが高速になります。

この最適化レベル1は、本番環境では常に有効にしておいた方が良いでしょう。

使い方

最適化レベル1を有効にするには、下記のいずれかを行います。

  • composer.json に「"optimize-autoloader": true」という設定値を加える
    (※ 開発環境ではオススメしません)
  • install コマンドもしくは、update コマンドを実行する際に、-o もしくは --optimize-autoloader オプションをつけて実行する
    php composer.phar install -o
    
    php composer.phar update -o
    
  • dump-autoload コマンドを実行する際に、-o もしくは --optimize オプションをつけて実行する
    php composer.phar dump-autoload -o
    

問題点

唯一の問題は、クラスが見つからない場合に、そのファイルを探すためにファイルシステムをチェックし、処理が遅くなる可能性がある点です。 この問題を解決するために、さらにもう1段階の最適化ができる最適化レベル2があります。

最適化レベル2にはAとBの2種類の方法がありますが、AとBは同時に使用することはできません。どちらか片方のみ使用できます。

最適化レベル2/A:Authoritative class maps

最適化レベル2/Aは、最適化レベル1のクラスマップをさらに発展させたものです。 最適化レベル2/Aを有効にすると、自動的に最適化レベル1のクラスマップも有効になります。

最適化レベル1と2/Aの違いは、クラスマップに無いクラスを読み込もうとした場合の動作の違いです。 最適化レベル1では、クラスマップに無いファイルでも、PSR-4のオートローダーによってファイルシステムをチェックし、読み込める場合は読み込むことができますが、 最適化レベル2/Aでは、クラスマップに無いファイルは読み込むことができません。 クラスマップを正しく生成できていることが大前提となります。

クラスマップに無いファイルを読み込むことなんてあるのか?と思うかもしれませんが、意外と簡単に発生します。 例えば、独自のライブラリなどを使用している場合などです。composer.json が下記のような設定になっているとしましょう。

composer.json
{
	"name": "hoge/hoge",
	"require": {
		"monolog/monolog": "1.0.*",
		"guzzlehttp/guzzle": "7.0"
	},
	"autoload": {
		"psr-4": {
			"Foo\\": "library/Foo/"
		}
	}
}

require にあるパッケージのクラスは、Composer の install コマンドや require コマンドで追加/削除を行っていれば、クラスマップから漏れることはないでしょう。 ですが、autoload > psr-4 > Foo に関しては、"library/Foo/" というローカルのディレクトリにファイルがあるので、クラスマップを生成した後に、 そのディレクトリのファイルを変更したりすると簡単にクラスマップと食い違うという状況が発生します。 つまり、そのディレクトリに変更を加える度に毎回クラスマップを再生成しないといけなくなるということです。

しかしながら、こういった状況が起きるのは開発環境ぐらいで、本番環境においてはデプロイ時等に必ずクラスマップを再作成するようにすれば、 最適化レベル2/Aで問題ないということになりますので、速度を向上させたい方は最適化レベル2/Aまでやってしまったほうが良いでしょう。

使い方

最適化レベル2/Aを有効にするには、下記のいずれかを行います。

  • composer.json に「"classmap-authoritative": true」という設定値を加える
    (※ 開発環境ではオススメしません)
  • install コマンドもしくは、update コマンドを実行する際に、-a もしくは --classmap-authoritative オプションをつけて実行する
    php composer.phar install -a
    
    php composer.phar update -a
    
  • dump-autoload コマンドを実行する際に、-a もしくは --classmap-authoritative オプションをつけて実行する
    php composer.phar dump-autoload -a
    

最適化レベル2/B:APCu cache

デフォルトの Composer のオートローダーもしくは、最適化レベル1のオートローダーは、 クラスマップに無いファイルの場合、PSR-4のオートローダーによってファイルシステムをチェックしますが、 この最適化レベル2/Bでは、さらにそのチェックした結果を、クラスが見つかったかどうかに関係なく常に APCu キャッシュに追加します。 そうすることで、次のリクエストでは、ファイルシステムをチェックすることなく、すぐに結果を返すことができるというものです。

この最適化レベル2/Bは、最適化レベル1で生成されるクラスマップは自動的に生成されません。 もし、最適化レベル1のクラスマップが必要であれば、最適化レベル1を手動で有効にしたうえで、最適化レベル2/Bを有効にする必要があります。 つまり、最適化レベル1と最適化レベル2/Bは組み合わせて使えるということです。 最適化レベル1が無効な場合でも動作しますし、最適化レベル1と2/Bを同時に有効にした状態でも動作します。

ただ、この最適化レベル2/Bを使う機会は少ないと思われます。 APCu が必要なのですが、APCu が使用できない環境もあるでしょう。 また、最適化レベル1だけでも OPcache が使用されるため、処理速度も充分に早いと思われます。

考えられる利用用途としては、クラスがあまりにも多く、 最適化レベル1で作成されるクラスマップがあまりにも巨大なファイルになってしまうような場合であれば、 APCu キャッシュの方が有利になる場合があるのかもしれません(詳しいベンチマーク等はとっていないので断言はできませんが)。 その場合は、最適化レベル1と組み合わせたりせず、最適化レベル2/Bのみで使用することになるでしょう。

使い方

最適化レベル2/Bを有効にするには、下記のいずれかを行います。

  • composer.json に「"apcu-autoloader": true」という設定値を加える
    (※ 開発環境ではオススメしません)
  • install コマンドもしくは、update コマンドを実行する際に、--apcu-autoloader オプションをつけて実行する
    # 最適化レベル2/Bのみで使用する場合
    php composer.phar install --apcu-autoloader
    
    # 最適化レベル1と2/Bを組み合わせて使用する場合
    php composer.phar install -o --apcu-autoloader
    
    # 最適化レベル2/Bのみで使用する場合
    php composer.phar update --apcu-autoloader
    
    # 最適化レベル1と2/Bを組み合わせて使用する場合
    php composer.phar update -o --apcu-autoloader
    
  • dump-autoload コマンドを実行する際に、--apcu オプションをつけて実行する
    # 最適化レベル2/Bのみで使用する場合
    php composer.phar dump-autoload --apcu
    
    # 最適化レベル1と2/Bを組み合わせて使用する場合
    php composer.phar dump-autoload -o --apcu
    

参考サイト

関連記事

もはや PHP で開発を行う際に、使用していないプロジェクトは探すのが大変なぐらいスタンダードな存在となった Composer ですが、昨年めでたく 2.0 になったということで、改めて少しまとめてみます。今更とか言っちゃダメです。Composer とは?Composer は、PHP の依存関係管理のためのツールです。 ...
前回、「Composer の使い方(その1:概要)」の続きです。今回はスクリプトについてです。スクリプトとは?composer.json にスクリプトを定義しておくと、Composer からそのスクリプトを実行できます。特定の定型処理などをまとめておきたいという場合に、登録しておくと便利です。スクリプトを登録するcom ...
前回、「Composer の使い方(その3:オートローダーの最適化)」の続きです。今回は便利コマンドについてです。list コマンドComposer で使用できるコマンドの一覧を表示できます。どんなコマンドがあるのか、このコマンドで調べましょう。php composer.phar listhelp コマンドhelp コ ...
最近のアプリケーションは開発効率を上げるために大量のライブラリを組み合わせて作成することが多くなっています。そういった状況下では、たった1つのライブラリがバージョンアップすることで、そのライブラリに依存している他のライブラリが正常に動作しなくなり、やがてアプリケーション全体が正常に動作しなくなるというような状況に陥りま ...

記事検索

最新記事

人気記事

RSSフィード

フィードバック

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

匿名でフィードバックする
匿名でフィードバックする

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

なお、このフォームから入力された内容について、管理者から返信はできませんので注意してください。 もし、管理者からの返信が必要であれば、X(旧 Twitter) もしくは、お問い合わせより、お願いします。