金曜日, 13 7 月 2007

PHPベンチマーク: Zend Framework vs Symfony vs CakePHP vs CodeIgniter vs PHP on TRAX この記事(PHPベンチマーク: Zend Framework vs Symfony vs CakePHP vs CodeIgniter vs PHP on TRAX)を「はてなブックマーク」に追加 この記事をクリップ! この記事(PHPベンチマーク: Zend Framework vs Symfony vs CakePHP vs CodeIgniter vs PHP on TRAX)を「del.icio.us」に追加

先日、Zend Frameworkが正式に1.0.0としてリリースされました。
公式だし今後使っていこうかなと思ったんですが、最近人気のある他のPHPフレームワークと比べて
パフォーマンスの面でどう違うか気になったので簡単なベンチマークをとって比較してみました。

今回使用したフレームワークはZend FrameworkSymfonyCakePHPCodeIgniterPHP on TRAXの5つです。
各フレームワークで行った処理はコントローラを呼び出しビューに遷移させて
"Hello World!"を表示させるだけのかなりシンプルな内容です。
DBへの接続やモデルの作成は行わず、自動レイアウト機能があるものはオフにするか全て削除しています。
使用したソースはこちらからダウンロードできます。

ベンチマークを行った環境はCeleron 1.7GHz、メモリ1GBのLinux上でApache2.0系、PHP-5.2.3を使用し、
各フレームワークのバージョンは一般配布されているstable系の最新版を使用しました。
(Zend Framework 1.0.0、Symfony 1.0.5、CakePHP 1.1.16.5421、CodeIgniter 1.5.3、PHP on TRAX 0.14.0)
ベンチマークの方法はab(Apache付属のベンチツール)を-c 100 -n 1000のオプションで
ローカルホストから呼び出す形で行いました。
それを各々5回ずつ行い、そのRequsts per secondの平均を結果として出しています。

以下がベンチマーク結果です。

Zend Framework 16.7 Request/Sec 2.8 %
Symfony 10.7 Request/Sec 1.8 %
CakePHP 12.8 Request/Sec 2.2 %
CodeIgniter 33.2 Request/Sec 5.7 %
PHP on TRAX 7.8 Request/Sec 1.3 %
(参考)フレームワーク無し 586.1 Request/Sec 100.0 % -


またAPCを有効にした状態でもベンチマークを取ったのでそれも載せておきます。
本当はeAcceleratorを使いたかったのですが、有効にするとZend、Symfony、TRAXで
エラーが発生したため今回は使用しませんでした。

Zend Framework 65.1 Request/Sec 9.5 %
Symfony 45.9 Request/Sec 6.7 %
CakePHP 63.9 Request/Sec 9.3 %
CodeIgniter 133.7 Request/Sec 19.5 %
PHP on TRAX 54.2 Request/Sec 7.9 %
(参考)フレームワーク無し 684.3 Request/Sec 100.0 % -


結果はAPCの有無に関わらずCodeIgniterがぶっちぎりの優勝で次いでZendという事になりました。
SymfonyとCakePHPはAPC無しでは差は小さいですが、APCを有効にするとCakePHPが大きく勝るようです。
TRAXはAPC無しではかなり遅いですが、有効にすると劇的にパフォーマンスが向上しました。

ついでにXdebugを使い各フレームワークの関数コールをトレースしステップ数を計ってみました。
以下がその結果です。

Zend Framework 446 Steps
Symfony 934 Steps
CakePHP 854 Steps
CodeIgniter 310 Steps
PHP on TRAX 510 Steps


やはりCodeIgniterが一番ステップ数が少ないという結果になりました。
そのおかげで高いスループットを実現出来ているんでしょうね。

ベンチマークを行った結果、残念ながらZendが一番という事にはなりませんでしたが、
悪い結果ではなかったので使ってみる価値はあるんじゃないかなと思います。
しかも日本語ドキュメントがかなり完成されているのでその点も魅力的なのではないでしょうか。


注) 今回行ったベンチマークはごく単純なものなので
  実際のシステムで必ずしもこの結果の通りになるとは限りません。
  またパフォーマンスが高いというだけで有用なフレームワークというわけでもありません。
  あくまで参考としてお考え下さい。

追記) CakePHPのソースについてモデル生成が有効になっていたため、
  ソースを修正しベンチマークを再度行って結果を修正しました。
Posted by tsujitako at 8:40 午前 in PHP/

金曜日, 12 1 月 2007

memcachedを使ったPHPのシングルトン実装 この記事(memcachedを使ったPHPのシングルトン実装)を「はてなブックマーク」に追加 この記事をクリップ! この記事(memcachedを使ったPHPのシングルトン実装)を「del.icio.us」に追加

PHPのクラスに備わっているstaticはJava(Servlet)のそれとは違いHTTPのリクエストが完了すると破棄されてしまいます。
そのためstaticフィールドを使ったシングルトンの実装を行ったとしてもリクエストがある度にインスタンスが生成され独立したプロセスから同一のインスタンスにアクセスすることは不可能です。

そこで今回memcachedを利用しPHPの各プロセスから同一のインスタンスを参照できるようにしてみたいと思います。
といってもシリアライズさせているので厳密には別のインスタンスになりますが…。

ちなみにmemcachedとはオブジェクトをメモリにキャッシュさせるPHPとは独立したサーバプログラムです。
利用できる言語はPHPだけに限らずPerl、Ruby、Java、Pythonなどにも対応しています。
インストールは./configure && make && make installで簡単ですが、あらかじめlibeventのインストールしておく必要があります。

次にPHPからmemcachedに接続するためのAPIを持つPECL拡張モジュールをインストールします。
# pear install http://pecl.php.net/get/memcache-2.1.0.tgz
それからphp.iniにエクステンションの記述を追加。
extension="(memcahce.soまでのパス)/memcache.so"
これで準備完了です。

今回シングルトンとして作るクラスは設定情報などを保持するものと想定して作りました。
以下がそのクラスのソースです。
class Repository
{
        private static $memcache;

        private $map;
        private $updated;

        public static function getInstance()
        {
                self::$memcache=new Memcache();
                self::$memcache->connect("localhost",11211);

                $repository=self::$memcache->get("repository");
                if(!$repository)
                        $repository=new Repository();

                return $repository;
        }

        private function __construct()
        {
                $this->map=array();
                $this->updated=false;
        }

        public function set($key,$val)
        {
                $this->map[$key]=$val;
                $this->updated=true;
        }

        public function get($key)
        {
                return $this->map[$key];
        }

        public function __destruct()
        {
                if($this->updated)
                {
                        $this->updated=false;
                        self::$memcache->set("repository",$this);
                }
                self::$memcache->close();
        }
}
説明するほどのものでもないですが。まずgetInstance()内でMemcacheオブジェクトを通じてmemcachedに接続し、"repository"というキーでオブジェクトが存在しているか調べます。
存在していればmemcachedから取得したオブジェクトをそのまま返し、存在していなければ新たにインスタンスを生成して返します。
これで永続化されたオブジェクトを取得することが出来るのですが、その後オブジェクトの状態を変更してもJavaのように参照を保持しているわけではないので永続化されたオブジェクトは更新されません。
そこで__destructを使いオブジェクトが破棄されるタイミングでもし更新されていればmemcachedにオブジェクトを書き出す処理を行っています。
$repository=Repository::getInstance();
$repository->set("test",123);
上ような処理だけでリクエストが終了しても状態は保たれたままその後他のプロセスも同じオブジェクトを参照することが出来ます。
しかもネットワーク越しに同一のオブジェクトを共有できるためWebサーバに負荷が増えてきても容易にスケール出来るのはかなりのメリットではないでしょうか。
ただし今回の実装は排他制御を行っていないのでそのままでは使えませんが…。

参考までに他のシングルトンの実装としてオブジェクトをシリアライズしてファイルに保存するパターンとデータベース(MySQL)に保存するパターンを作りベンチマークを取ってみました。

requests/secリモート接続
memcached334
ファイル439×
DB(MySQL)277
※ab -c 100 -n 1000の結果です。
※MySQLはHEAPテーブルを使用しています。

これを見るとローカルからだけの参照ならファイルにシリアライズさせるパターンが一番速いですが、リモートからの参照となるとMySQLよりmemcachedに保存した方が速いようです。
作成したファイル版とデータベース版のソースも一応置いておきます。(→ファイル版、→データベース版)

パフォーマンスは悪くないのでオブジェクトに限らず画像やテキストなどキャッシュさせれば負荷を軽減させるのに役立つのではないでしょうか。slashdotやmixiも使っているようですし。
Posted by tsujitako at 5:42 午前 in PHP/

金曜日, 7 4 月 2006

画像→HTML変換ツール この記事(画像→HTML変換ツール)を「はてなブックマーク」に追加 この記事をクリップ! この記事(画像→HTML変換ツール)を「del.icio.us」に追加

ヒマ少し時間があったので画像をHTML(アスキーアート?)に変換するツールを作ってみました。
使い方は"画像のURL"に変換したい画像のURLを入れて"文字"に適当な一文字を入れます。
で、"HTML変換"ボタンをクリックするとその画像が"文字"で表されたHTMLとして表示されます。
デフォルトでミクシィのロゴ画像が変換されるようになっているのでとりあえずそのままボタンを押してみてください。

どうしても画像が表示できない環境や画像を含めたHTMLを無理矢理一枚のHTMLに収めたい
かなり特殊な状況下にいる人には使えると思います。

画像のURL:
文字: 大きさ:ピクセル
縮小:%
表示:


ここに表示されます




これが



こうなったりします
Posted by tsujitako at 10:48 午後 in PHP/

水曜日, 12 4 月 2006

Webページ→画像変換ツール この記事(Webページ→画像変換ツール)を「はてなブックマーク」に追加 この記事をクリップ! この記事(Webページ→画像変換ツール)を「del.icio.us」に追加

やることがないちょっと手が空いたので前回に引き続きAjax + PHPで簡単なツールを作ってみました。
今回のツールはWebページのキャプチャ(スクリーンショット)を取ってそれをサムネイル画像に変換するものです。
使い方はとても簡単で"WebページのURL"に適当なサイトのURLを入力し、
"イメージ作成"ボタンを押してしばらくするとそのページが画像として表示されます。
少し変換に時間が掛かるので表示されるまでジッと待っていてください。

最近は検索サイトなどで検索結果とそのページのサムネイルを同時に表示してるところもあるので
実は結構需要があるのかなと思います。手動でキャプチャしてサムネイル作るのも面倒だし。

WebページのURL:
サムネイルの大きさ:


ここに表示されます


うわぁ、まるでポータルサイトの宝石箱やぁぁ
Posted by tsujitako at 11:53 午後 in PHP/