composer installをproduct環境で使う際はoptimize-autoloaderオプションを使おう
by @dekokun on 2014/06/22 23:34
概要
composer installには–optimize-autoloaderオプションつけたほうが若干アプリケーションの性能が上がるよ。 もしくは、composer installした後にcomposer dumpautoload -oするか。
なぜか
composerが自動生成するautoloaderは、以下の順番でクラスファイルを探していくんですね。
- vendor/composer/autoload_classmap.php(以下、classmapファイルと記載)ファイルの中にクラス及びそのファイルの定義があればそのファイルをinclude
- 上記なければそのファイルをまぁいろいろ検索してファイルの存在まで確認して存在すればinclude
というわけでclassmapファイルにいろいろ書いてあるとファイルの検索部分が省略され基本的に高速化される模様なのですが、classmapファイルは、普通にcomposer installを行っただけでは空の配列を返す感じになっているのです。
以下のような感じです。
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
ではどうすればいいかというと、表題のようにcomposer install時に –optimize-autoloaderオプションをつければいいのです。つけると以下のように、クラス名とファイル名を対応させる記述が増えます。
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Acme\\DemoBundle\\AcmeDemoBundle' => $baseDir . '/src/Acme/DemoBundle/AcmeDemoBundle.php',
'Acme\\DemoBundle\\Command\\HelloWorldCommand' => $baseDir . '/src/Acme/DemoBundle/Command/HelloWorldCommand.php',
'Acme\\DemoBundle\\Controller\\DemoController' => $baseDir . '/src/Acme/DemoBundle/Controller/DemoController.php',
'Acme\\DemoBundle\\Controller\\SecuredController' => $baseDir . '/src/Acme/DemoBundle/Controller/SecuredController.php',
'Acme\\DemoBundle\\Controller\\WelcomeController' => $baseDir . '/src/Acme/DemoBundle/Controller/WelcomeController.php',
'Acme\\DemoBundle\\DependencyInjection\\AcmeDemoExtension' => $baseDir . '/src/Acme/DemoBundle/DependencyInjection/AcmeDemoExtension.php',
...以下略 なお、こちらはSymfonyの初期状態でテストしています
実際の効果
- 上記最適化を行うことでMoufというフレームワークでhello worldするWebアプリのレスポンスが37%早くなったという話
実際に自分でもやってみました。
- OS: Mac
- 言語: PHP5.5
- Web server: PHPのビルトインサーバ
- Apache Bench: Mac上から自分自身に対してApache Bench実施
クラスファイルを1万ほど生成し(参考までに、素のSymfonyをインストールした際にvendorディレクトリ以下は6000ファイルほどとなっています)、そのクラスのスタティックメソッドをひたすら呼び出すアプリケーションを作ってApache Benchをかけてみました。 (もろもろキャッシュに載せた結果を確認するため、2回同じことを行い、2回目の結果を採用しています)
composer install
Time per request: 788.825 [ms] (mean)
composer install --optimize-autoloader
Time per request: 731.721 [ms] (mean)
はい、少し早くなりましたね。
何回かやりましたが全部こんなかんじでしたので、まぁある程度正しいんでしょうが、かなり適当に計測しているというのはご了承ください。
なお、2014/06/23時点で、Composerが生成するautoloaderにおいてクラス名の最初の一文字というのは非常に重要(クラス名の一文字目を検索の最初のフィルタリングのキーとして使っている)なのですが、今回全てTestから始まるクラス名だったため、あまりにもこの計測は実態から乖離しまくっているなとは思いました。
結論
composer install –optimize-autoloader をしよう ただ、まぁ、若干composer installにかかる時間が長くなる
自分が行ったテストについて
Apache Benchとサーバを同じPC上で行っていたり、100リクエスト程度しかしてなかったり、まぁかなり適当な感じのテストではある。
アプリケーションは以下。
<?php
require_once __DIR__ . '/../vendor/autoload.php';
for($i = 1; $i < 10000; $i++) {
$className = "Test" . $i;
$a = $className::hoge();
}
echo 'hoge';
composer.json
{
"name": "dekokun/hoge",
"description": "hoge demo",
"repositories": [
],
"autoload": {
"psr-0": {"": "lib"}
}
}
libディレクトリの下は以下
$ ll | more
total 80016
-rw-r--r-- 1 dekokun staff 71B 6 22 23:14 Test1.php
-rw-r--r-- 1 dekokun staff 72B 6 22 23:14 Test10.php
-rw-r--r-- 1 dekokun staff 73B 6 22 23:14 Test100.php
-rw-r--r-- 1 dekokun staff 74B 6 22 23:14 Test1000.php
…以下略
各クラスファイルは以下
<?php
class Test1 {
static function hoge()
{
return 1;
}
}
comments powered by Disqus