ECWorks Blog

ECWorks Blog

CakePHPを中心としたサイト開発情報をメインに公開。新しもの好きなので時々製品レポートなんかも。

【CakePHP】App::importが遅い件の調査

最近CakePHPフォーラムの方で、App::importが遅い、という話題がありました。
この件について、結構いい加減なレスを付けてしまったのですが、自分でも結構切実なため、ちょっと調査してみることにしました。

手っ取り早くpearのBenchmarkを入れ、configure.php内のメソッドに全て適用して走らせたところ、一番重いのは、App::import内で呼び出しているApp::__findのようです。具体的な数値はさらしても全く参考にならないので割愛しますが、当方の遅いサーバで、トータルの処理時間が他のメソッドが0.001s以下の処理であるのに対し、App::importやApp::__findは0.1s単位の話になっています。

フォーラムで指摘のあったものとして、「ディレクトリ検索のリストの一番最後にcakeディレクトリがある」というのがあり、確かに見つからなかった場合に最悪今まで調べたcake内のほかのディレクトリを再チェックしかねません。こうなる可能性があるもので、必ずファイルが存在しているものはbasics.php、bootstrap.php、dispatcher.phpの3つです。

ソースを調べたところ、案の定というのか、bootstrap.php内で「dispatcher.php」がApp::importで呼ばれているではありませんか! ほかのファイルについてはrequireで直接呼ばれているようなので問題なさそうですが、dispatcherがなぜApp::importで呼ばれているのか理解できません。

本来はrequire(_once)で片付けるのが一番高速なのですが、どこか別の場所でdispatcherを呼んでいる場所があるらしく、このままだと_loadedリストに書かれないため2度読みの可能性があります。そこで、App::importでファイルを直接指定することで2度読みOKの状況を作ることにして、変更してみました。

【/path/to/cake/bootstrap.php】

App::import(‘Core’, array(‘Dispatcher’));
↓↓↓
App::import(‘Core’, ‘Dispatcher’, true, array(), ‘/path/to/cake/dispatcher.php’);

ブランクページを表示するだけの「/mypages/index」を作り、早速abしてみました。
100アクセス中、改造前は45req/sくらいでしたが、65req/secくらいに跳ね上がりました!

結論として、bootstrap.phpのdispatcher.php呼び出しが諸悪の根源とみて良いと思います。
また、基本的に場所の分かり切っているクラスの読み込みはファイルパスの直接指定に直すことで高速化できると思います。例えばrouter.php, controller.php等も必ず読み込まれるファイルですから、直接指定で問題ないと思います(ただ、比較的早い段階で見つかるので、それほど高速になるかは分からないです)。できればこういったファイルについてはrequireで問題ないような作りになっていると…(^^;

【追記】
全く書かれていなかったので補足しますと、テストを行ったのはRC3版です。
RC1やRC2で同様の改造を行う場合は、App::importに列挙されているSession、Security、Stringの3点を分解してから行う必要があります。

【追記その2】
さらに調査した結果が こちら にあります。
合わせてお読みください。




2 Comments

  1. 凄く参考になります!
    自分もcake1.2(RC3)を利用していて重いな・・
    と感じていましたが、上記の修正でかなり
    体感速度がUPしました!