こんな機能があるなんて知りませんでした。割と古い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倍くらい遅いです。しかし、クラスの読み込みを意識せずに実装することができるので、うまく使えば素晴らしい威力を発揮してくれそうです。でもパフォーマンスがシビアな場合は無理ですね。
コメント