色々なPHPフレームワークのパフォーマンスを比較

PHPフレームワークの速度比較では、HelloWorldを表示するのみの単純なアプリを用いた計測を元に比較表が作られることが多いです。特に後発のフレームワークは分かりやすい特徴付けとして速度をアピールする傾向にあるため、その比較表を元に N倍速いというアピールをしています。

PHPフレームワークを使うということは、DBまで絡めたWebアプリを作ることがほとんどなため、HelloWorldアプリの比較よりは、DBからレコード取得して表示するまでの処理速度を比較したほうがより現実に近い指標になると思います。特にCakePHP1系ではDBのデータ取得も独自ドライバになっていますし、モデルの処理も重いのでそこまで含めて他と比較したほうが良いと思ってます。

今回はDBから1レコード取得して表示するという簡単なアプリで各フレームワークの速度を評価しました。フレームワークに備わっているViewキャッシュなどはOFFにしています(必ずDBに接続してデータを加工する処理を通る場合の比較をしたかったため)。
本当は、もうちょっと複雑なアプリで評価したかったのですが、自分のリソースも有限ですし、慣れないフレームワークで実装していくと時間がかかるので、今回は結果を出すことを優先しました。これをフェーズ1として、徐々に進化させていきたいと思います。手伝ってくれる方、募集中。

注意点

今回は同時接続時にスループットがどれほど出るかを計測しています。この記事で速いという表現はスループットが高いという意味です。
この値は高いほうが良いのですが、値が低いものは機能が豊富である傾向があるため、そのトレードオフで考えるべきです。今回の結果はフレームワーク選定の一つの材料として考えるのが良いと思います。フレークワークはそれぞれに思想や特徴が異なりますので、実現したいものや環境によって使い分けていく道具であると考えています。

環境

今回の環境は、下記のようになっており、MySQLにはpostsテーブルのみ25000レコードがある状態です。

Server: Dell SC440 Pentium Dual  CPU  E2180  @ 2.00GHz / 2G Memory / SATA HDD
OS: Ubuntu11 64bit
PHP 5.3.5 with APC3.1.9(shmを300Mにした以外は全てデフォルト設定)
Apache 2.2.17
MySQL 5.1.54

postsテーブルのスキーマ

CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `text` text,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

計測対象

この状態で、下記フレームワークを同一条件で比較しました。

Agavi 1.0.6
CakePHP 1.3.11
CakePHP 2.0-beta
Codeigniter 2.0.2
Lithium 0.10
Pinoco 0.5.2(PHPTALテンプレート)
Silex (Doctrine + Twig(キャッシュオプション有効))
Symfony 2.0
Yii 1.1.8
ZendFW 1.11.10

Seigeという計測ツールを使い下記のオプションのように、同時接続数10で3秒間に何アクセスさばけるかという計測を行いました。
siege -b -c 10 -t 3S http://localhost

ちなみに素のPHPで書いたコードで計測すると、
1170 trans/sec
という結果がでました。

結果(スループット)

結果は下記の通りです。値が高いものほど速いです。

Codeigniter2とPinocoがダントツで速いですね。PinocoMVCを指向してないフレームワークのため、この結果は納得。Pinocoは面白い思想のフレームワークなので一度見てみるといいですよ。 Codeigniterはそれなりに機能もあるのにこの速度、素晴らしい。Codeigniterは今回ちょっと実装してみてシンプルで習得も簡単そうなので良いなと思いました。
YiiはHelloWorldアプリだとすごく速いと評判だったのですが、DBまで絡めるとCodeigniter2の約半分程度のスループットになりました。
LithiumとCakePHP2.0-betaは同じぐらいです。LithiumMySQLドライバがまだ開発途上中っぽいので今後は改善されていくかもしれません。CakePHP2.0-betaはまだベータ版のため、リリースまでにもっと速くなると思います。どちらも同じような機能を持っていますが、Lithiumアスペクト指向フレームワークという特徴があります。CakePHP2はCakePHPをさらに使いやすくしたものです。CakePHPはドキュメントも豊富で、プラグインもたくさんあるため、CakePHP2も同じような状況になりそうです。自分も便利なCakePHPプラグインをたくさん使っているのでまだまだ手放せません。CakePHP2になってさらに速くなるので楽しみ。
SilexはTwig(キャッシュ有効)とDoctrineを使うパターンで計測しました。マイクロフレームワークなので今回のような簡単なアプリには向いていますが、TwigやDoctrineの恩恵を受けるとあまり速度はあがりませんでした。TwigとDoctrineをはずしてPDOでDBアクセスするパターンですと40%ほど速度アップします。Silexはとてもシンプルにアプリケーションがかけますし、記述方法も面白いので一度コードを見てみると良いと思います。
Symfony2.0は、機能の豊富さから考えてこの位置にいるのは妥当かなと思います。Symfony2.0はDIコンテナやMongoDBなどにも簡単に対応できるDoctrine2、継承が出来るテンプレートTwigなど新しい機能を盛り込んでいるので、その恩恵とコストを天秤にかけて判断するのが良いかと思います。ただ、Symfony2.0はESIと呼ばれる高機能なキャッシュもあるので、キャッシュを効かせやすいサイトだと今回の速度結果も問題にならないと思います。

[追記:2011/8/6]
ZendFWも計測しました。 Cake2やLithiumとほぼ同じ速さでした。
AgaviFWはCake2やLithiumよりちょっと速いですね。キャッシュは無効にして計測しました。Call数は多めなのですが、大きなボトルネックがないので実効速度が速いです。

結果(function call数)

スループット以外に、XHProfというツールを使ってどれだけfunction callが発生したかも計測しました。基本的にはcall数が少ないほうが良いです。
ただ、Yiiはコール数は少ないですがデータ処理周りにボトルネックがありスループットがあまり出ないという結果が分かりました。

貢献

@hidenorigotoさんには、私が作ったSymfony2.0のアプリを改修してもらい速度アップしました。
@brtriverさんには、Silexのアプリを実装してもらいました。
@tanakahisateruさんには、YiiとPinocoのアプリを実装してもらいました(@tanakahisateruさんはPinocoの作者です)
@kenji_sさんには、CodeIgniter2のブログチュートリアルの記事を教えて頂きました。
id:satoruyoshida さんにはZendFwのアプリを実装してもらいました
@mugesoさんには、Agaviのアプリを実装してもらいました
@shin1x1さんには、なぐさめてもらいました

その他にも、Twitterで色々とアドバイスいただいた皆様、ありがとうございました。

最後に

今回はフェーズ1ということで、ある程度やりきれる形をとりました。今後は他のFWも含めて、もう少し複雑なアプリで評価していきたいと思います。

参考

@koriymさんの記事も参考になります。
PHP Hello Worldコールグラフ(2011)

@kenji_sさんがCIのARを使わないパターンで計測しています。
CodeIgniter と Pinoco をベンチーマークしてみた