PHPでクラスのincludeを自動化するautoloadの速度を測ってみた。

こんな機能があるなんて知りませんでした。割と古いPHPで頭が止まっていましたが、久しぶりにPHPのドキュメントを呼んでいて、autoloadという機能があることを知りました。

大規模プロジェクトだと、クラスをincludeするだけで一苦労

超大雑把に説明すると、以下のようなソースコードはエラーを吐きます。


このとおり。

PHP Fatal error:  Class 'MyClass' not found in /Users/katty/Documents/AutoLoader/index.php on line 2

そもそも、MyClassというクラスが定義されているファイルをincludeしないと使えないというエラーです。
規模が大きくなってきて、クラスが100個とか200個とかになってくると、includeするだけでも一苦労だったりしますね。

クラスを使うためにソースコードを自動でincludeしてくれる

そこで、「クラスのオートローディング」です。
spl_autoload_register() なり、__autoload() を使うことで、クラスが定義されていなかった場合に、必要なソースコードを動的にincludeすることができます。

でも遅いんでしょう?

というわけで、少しベンチマークしてみました。PHPのバージョンは5.3.10。マシンは、MacBook Air(1.7 GHz Intel Core i5)です。

bench.php

メインのファイル"bench.php"は以下のような形。時間を測定して、$argv[1]に指定した方式でクラスをincludeし、$argv[2]で指定した数だけクラスを呼び出しています。呼び出し方は2種類で、newでインスタンスを生成するパターンと、staticなメソッドを呼ぶパターンです。


require.php

requireでクラスを読み込む場合の測定のための"require.php"は以下です。事前に1000個のクラスをclassesディレクトリに作成しておいて、それを全部読み込んでいます。


autoload.php

autoloadを使ってクラスを読み込む場合の測定のための"autoload.php"は以下です。クラスがなければ、ここで定義する関数に処理が渡り、クラス名を元にincludeを実行するものとしています。(今考えたら、ここもrequireにすべきでした・・・)


requireを使う場合

まず、1000クラスを読み込んだ上で、10クラスを使う場合です。

$ php bench.php require 10
Class0::__construct
Class1::static_function
# ... 略 ...
Class8::__construct
Class9::static_function
56.918859481812ms

続いて100クラス使う場合。

$ php bench.php require 100
Class0::__construct
Class1::static_function
# ... 略 ...
Class98::__construct
Class99::static_function
55.775880813599ms

1000クラス使う場合。

$ php bench.php require 1000
Class0::__construct
Class1::static_function
# ... 略 ...
Class998::__construct
Class999::static_function
65.891027450562ms

最初に1000クラスを読み込むので、使わないクラスは無駄に読み込まれたことになります。1000クラス読み込むとだいたい50msくらいで、それを使う時間は読み込む時間に比べると大きくないですね。
requireで1クラス読むのにかかる時間はだいたい0.5msというところでしょうか。

autoloadを使う場合

autoloadは必要になった場合にはじめて読み込みます。10クラス使う場合は、10個のソースコードを読み込ます。

$ php bench.php autoload 10
Class0::__construct
Class1::static_function
# ... 略 ...
Class8::__construct
Class9::static_function
1.3880729675293ms

100クラスの場合。

$ php bench.php autoload 100
Class0::__construct
Class1::static_function
# ... 略 ...
Class98::__construct
Class99::static_function
11.373043060303ms

1000クラスの場合

$ php bench.php autoload 1000
Class0::__construct
Class1::static_function
# ... 略 ...
Class998::__construct
Class999::static_function
100.74710845947ms

不要なクラスを読まないので、10クラスの場合は、990クラスを無駄にしているrequireよりも速いです。1000クラスの場合は、どちらも無駄がないので、autoloadのオーバーヘッドが見える分、autoloadの場合の方が遅いです。
autoloadの場合はだいたい1クラスで1msというところです。

まとめ

autoloadで読み込むと、requireで読み込む場合の2倍くらい遅いです。しかし、クラスの読み込みを意識せずに実装することができるので、うまく使えば素晴らしい威力を発揮してくれそうです。でもパフォーマンスがシビアな場合は無理ですね。

コメント

タイトルとURLをコピーしました