composer installをproduct環境で使う際はoptimize-autoloaderオプションを使おう

by @dekokun on 2014/06/22 23:34

Tagged as: PHP, composer.

概要

composer installには–optimize-autoloaderオプションつけたほうが若干アプリケーションの性能が上がるよ。 もしくは、composer installした後にcomposer dumpautoload -oするか。

なぜか

composerが自動生成するautoloaderは、以下の順番でクラスファイルを探していくんですね。

  1. vendor/composer/autoload_classmap.php(以下、classmapファイルと記載)ファイルの中にクラス及びそのファイルの定義があればそのファイルをinclude
  2. 上記なければそのファイルをまぁいろいろ検索してファイルの存在まで確認して存在すれば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の初期状態でテストしています

実際の効果

実際に自分でもやってみました。

  • 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