openpearのライブラリNet_URL_Dispatcherを使用してみました。

phpのディスパッチャーが欲しいなと思い色々探していました。

下記のサイトを発見しましたので早速ダウンロードして使用しました。
http://d.hatena.ne.jp/heavenshell/20090103/1230985262

環境

OS:CentOS5.4
PHP:5.2.1

早速実行

<?php
require_once 'Net/URL/Dispatcher.php';
$dispatcher = new Net_URL_Dispatcher();
$dispatcher->setDirectory('/var/www');
$dispatcher->connect(':controller/:action/*params')->dispatch();

上記のスクリプトを書いてhttp://URL/index.php/hoge/fugaにアクセスすると、
/var/www/controllers/HogeController.phpのFugaActionにディスパッチします。

そこで、上記URLのindex.phpいらないなぁーと思った時は下記で対応出来る事が確認出来ました。

<?php
require_once 'Net/URL/Dispatcher.php';
$dispatcher = new Net_URL_Dispatcher();
$dispatcher->setDirectory('/var/www');
$dispatcher->setPathinfo($_SERVER['REQUEST_URI']);
$dispatcher->connect(':controller/:action/*params')->dispatch();

.htaccess(symfonyからインスパイア(笑))

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteRule ^$ index.html [QSA]
  RewriteRule ^([^.]+)$ $1.html [QSA]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

上記のスクリプトを書いてhttp://URL/hoge/fugaにアクセスすると、
/var/www/controllers/HogeController.phpのFugaActionにディスパッチします。

まとめ

URLの正規化したいとか、今後他の言語のフレームワークで開発するかもしれないからとかにディスパッチャーは使えるのかな。クラスで色々書けるのは好きな人とかですかね。

追記

ライブラリの386行目にcontroller用のディレクトリー名(controllers)が固定で書かれているので、setter等があれば良いなと思いました。


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

最先端PHPフレームワークLithiumのチュートリアルを実際に体験してみました。

MongoDB等のデータベースを使用したPHPフレームワークが無いかと調べたところ、通称CakePHP3と呼ばれるフレームワークLithiumがあるのを知り、実際にインストールしてみる事にしました。

チュートリアル(ブログの様な記事投稿システム)もあるので今回実際に体験してみましたので、簡単に流れを記事にしました。

チュートリアル
http://rad-dev.org/lithium/wiki/drafts/blog-tutorial

環境

OS:CentOS5.4
PHP:5.3.1
MongoDB:1.2.2
Lithium:0.9


lithiumのダウンロード&解凍

最新版はlithium-0.9になりますね。

wget http://d10xg45o6p6dbl.cloudfront.net/projects/l/lithium/lithium-0.9.zip
unzip lithium-0.9.zip
mv lithium-0.9 lithium


apacheのドキュメントルート設定を、解凍したディレクトリ内にあるapp/webrootに設定します。
(apacheのrestartも忘れずに)
また、MongoDBをインストールしMongoDBのプロセスも立ち上げておきます。


ブラウザからアクセスすると下記の画面が現れます。


0.8と若干画面が変わりましたね。



チュートリアルその1

まず、さきほどの初期画面に表示されている指示に従います。

chmod -R 0777 /var/www/lithium/app/resources


その後チュートリアルに戻り下記のコマンドでphpからMongoDBを操作するプラグインをインストールします。

sudo pecl install mongo


app/config/connections.phpに下記を追加します。

// MongoDB Connection
    Connections::add('default', array('type' =>  'MongoDb', 'database' => 'blog', 'host' => 'localhost'));


app/config/bootstrap.phpの46行目のコメントを外します。

require __DIR__ . '/connections.php';


すると初期画面が下記のようになり、初期設定が完了した事がわかります。



チュートリアルその2

実際にMVCを作成するプロセスです。

まずはModelを作成します。
app/models/Post.phpを作成し下記の記述をします。

<?php
    namespace app\models;

    class Post extends \lithium\data\Model {
    }

これでModelの作成完了です。


次にControllerの作成です。
app/controllers/PostsController.phpを作成し下記の記述をします。

<?php
namespace app\controllers;
use app\models\Post;

class PostsController extends \lithium\action\Controller {

    public function index() {
        $posts = Post::all();
        return compact('posts');
    }
    public function add() {
        $success = false;
        if ($this->request->data) {
            $post = Post::create($this->request->data);
            $success = $post->save();
        }
        return compact('success');
    }
}

これでControllerの作成完了です。


次にViewを作成します。

まずブログの記事一覧を表示する、index.html.phpを作成します。

app/views/posts/index.html.php

<?php foreach($posts as $post): ?>
<article>
<h1><?=$post->title ?></h1>
<p><?=$post->body ?></p>
</article>
<?php endforeach; ?>

次にブログの書込み用の画面を作成します。

app/views/posts/add.html.php

<?php if ($success): ?>
<p>Post Successfully Saved</p>
<?php endif; ?>
<?=$this->form->create(); ?>
<?=$this->form->field('title');?>
<?=$this->form->field('body', array('type' => 'textarea'));?>
<?=$this->form->submit('Add Post'); ?>
<?=$this->form->end(); ?>

チュートリアル(その3)

MVCの作成は終わりました。
実際にブラウザからアクセスしてみたいと思います。

http://sample.com/posts/add
下記の様な投稿画面が表示されました。
綺麗なフォームが簡単に生成されるヘルパーの様ですね。
入力欄が大きいので、iPhoneからの投稿も楽でした。


http://sample.com/posts
下記は記事一覧画面ですね。


まとめ

Lithiumはファイル数やディレクトリの配置を見てとても軽量で薄い印象を受けましたが、それと同時にパワフルなフレームワークだなと思いました。
MongoDBを採用しているのも評価出来ます。
後は日本語のノウハウが欲しいところです!

時間がある時に少しずつ勉強していきたいと思います。

追記

mixiのコミュニティを作成してみました。
情報交換したいです。
宜しくお願いしますー。
http://mixi.jp/view_community.pl?id=4975003


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

MongoDB,CouchDB,MySQL,memcacheデータをPHPから読み込み&書き込み速度を検証してみました!(その2)

前回、MongoDB,CouchDB,MySQL,memcacheの読み込み&書き込み速度を検証してみました。
MongoDB,CouchDB,MySQL,memcacheデータをPHPから読み込み&書き込み速度を検証してみました! - @camelmasaの開発日記

下記の原因で予想していたような結果を出す事が出来ませんでした。
・MongoDBでコネクションプーリングをしていなかった。
CouchDBのHTTPリクエスト方法が遅かった。

id:yssk22さんのコメントにより上記の部分を修正する事が出来ましたので再度検証してみました。


gt
CouchDB:0.10.1
MySQL:5.1.43
memcache:1.2.8

CPU:AMD(の何か)
メモリ:4GB
(ざっくり検証です。)


読み込み時のソース

前回と一緒で"test"データベースの"test"テーブル(コレクション)の"test"データをphpから読み込みするプログラムです。

couchdb.php

<?php

$ch = curl_init("http://192.168.0.30:5984/");
$fp = fopen("test/1ab25e328d1f36b2895671666491e48f", "w");

curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);

curl_exec($ch);

前回、PEARパッケージであるHTTP_Requestを用いて検証して物凄く遅かったのですが、cURL関数を使って通信する事で速度が飛躍的に向上する事が期待できます。


mongodb.php

<?php

$mongo = new Mongo();

$db = $mongo->selectDB("test");
$col = $db->selectCollection("test");
$cursor = $col->findOne();

前回コネクションプーリングしていなかったので今回はコネクションプーリングして検証します。
コンストラクタの第3引数にtrueをする事でプーリングを確保出来ます。


mysql.php

<?php
<?php
$link = mysql_pconnect('localhost', 'user', 'pass');
mysql_select_db('mytest', $link);
$result = mysql_query('SELECT `test` FROM `test` LIMIT 0,1;');


memcache.php

<?php

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$memcache->get('test');

読み込み結果

couchdb.php

ab -c 100 -n 1000 'http://192.168.0.30/couchdb.php'

Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /couchdb.php
Document Length:        41 bytes

Concurrency Level:      100
Time taken for tests:   3.152094 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      232000 bytes
HTML transferred:       41000 bytes
Requests per second:    317.25 [#/sec] (mean)
Time per request:       315.209 [ms] (mean)
Time per request:       3.152 [ms] (mean, across all concurrent requests)
Transfer rate:          71.70 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    2   7.9      0      31
Processing:    26  302 112.4    248     813
Waiting:       26  302 112.5    248     813
Total:         26  305 112.7    248     813

Percentage of the requests served within a certain time (ms)
  50%    248
  66%    262
  75%    349
  80%    443
  90%    515
  95%    525
  98%    534
  99%    538
 100%    813 (longest request)


mongodb.php

ab -c 100 -n 1000 'http://192.168.0.30/mongodb.php'

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mongodb.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.404074 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190570 bytes
HTML transferred:       0 bytes
Requests per second:    712.21 [#/sec] (mean)
Time per request:       140.407 [ms] (mean)
Time per request:       1.404 [ms] (mean, across all concurrent requests)
Transfer rate:          132.47 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    2   7.2      0      30
Processing:    10  129  88.5    124     844
Waiting:        9  128  88.4    124     843
Total:         29  131  88.9    124     865

Percentage of the requests served within a certain time (ms)
  50%    124
  66%    125
  75%    130
  80%    130
  90%    145
  95%    152
  98%    191
  99%    750
 100%    865 (longest request)


mysql.php

ab -c 100 -n 1000 'http://192.168.0.30/mysql.php'

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mysql.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.533586 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    652.07 [#/sec] (mean)
Time per request:       153.359 [ms] (mean)
Time per request:       1.534 [ms] (mean, across all concurrent requests)
Transfer rate:          120.63 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    3   6.2      0      25
Processing:    13  142 125.8    135    1512
Waiting:        9  141 126.1    134    1510
Total:         20  146 126.1    138    1528

Percentage of the requests served within a certain time (ms)
  50%    138
  66%    147
  75%    149
  80%    151
  90%    155
  95%    159
  98%    165
  99%    182
 100%   1528 (longest request)


memcache.php

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /memcache.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.305582 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190950 bytes
HTML transferred:       0 bytes
Requests per second:    765.94 [#/sec] (mean)
Time per request:       130.558 [ms] (mean)
Time per request:       1.306 [ms] (mean, across all concurrent requests)
Transfer rate:          142.47 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    4   6.7      1      28
Processing:    26  121  30.1    129     188
Waiting:       25  116  29.5    124     187
Total:         26  126  33.2    132     193

Percentage of the requests served within a certain time (ms)
  50%    132
  66%    141
  75%    148
  80%    153
  90%    164
  95%    171
  98%    179
  99%    183
 100%    193 (longest request)

読み込み結果検証

Time taken for testsが
memcache>MOngoDB>MySQL>CouchDB
の順番になりましたね。

これは納得がいく順番ですね。


前回同じ条件でのcouchdb.phpが9.587989 secondsでしたが、今回は3.152094 secondsと飛躍的に増加しました!

又MongoDBをコネクションプーリングする事でも処理が早くなりました。
下記が接続時のログですが、1000回のアクセスにも係わらず21回しか新規の接続をしていない事が確認できます。

Fri Feb 26 12:25:52 db version v1.2.2, pdfile version 4.5
Fri Feb 26 12:25:52 git version: 8a4fb8b1c7cb78648c55368d806ba35054f6be54
Fri Feb 26 12:25:52 sys info: Linux domU-12-31-39-01-70-B4 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:39:36 EST 2008 i686 BOOST_LIB_VERSION=1_37
Fri Feb 26 12:25:52 waiting for connections on port 27017
Fri Feb 26 12:27:02 connection accepted from 192.168.0.30:51154 #1
Fri Feb 26 12:27:02 connection accepted from 192.168.0.30:51155 #2
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51156 #3
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51157 #4
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51158 #5
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51159 #6
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51160 #7
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51161 #8
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51162 #9
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51163 #10
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51164 #11
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51165 #12
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51166 #13
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51167 #14
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51168 #15
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51169 #16
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51170 #17
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51171 #18
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51172 #19
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51173 #20
Fri Feb 26 12:27:03 connection accepted from 192.168.0.30:51442 #21
Fri Feb 26 12:27:04 end connection 192.168.0.30:51161


次は書き込み時の検証してみます。


書き込み時のソース

couchdb_write.php

<?php

$ch = curl_init("http://192.168.0.30:5984/");
$fp = fopen("test", "w");

curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"test":"test"}');

curl_exec($ch);


mongodb_write.php

<?php

$mongo = new Mongo('192.168.0.30:27017',true,true);

$db = $mongo->selectDB("test");
$col = $db->selectCollection("test");
$col->insert(array("test" => "test"));


mysql_write.php

<?php
$link = mysql_pconnect('localhost', 'user', 'pass');
mysql_select_db('mytest', $link);
$result = mysql_query("INSERT INTO `test` VALUES ('test');");


memcache_write.php

<?php

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$memcache->set("test", "test");

書き込み結果

couchdb_write.php

ab -c 100 -n 1000 'http://192.168.0.30/couchdb_write.php'

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /couchdb_write.php
Document Length:        64 bytes

Concurrency Level:      100
Time taken for tests:   3.193331 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      255255 bytes
HTML transferred:       64064 bytes
Requests per second:    313.15 [#/sec] (mean)
Time per request:       319.333 [ms] (mean)
Time per request:       3.193 [ms] (mean, across all concurrent requests)
Transfer rate:          77.98 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   38  31.2     33     117
Processing:   110  268  92.0    239     561
Waiting:        3  237  90.8    217     537
Total:        112  306 106.7    275     642

Percentage of the requests served within a certain time (ms)
  50%    275
  66%    300
  75%    315
  80%    353
  90%    507
  95%    556
  98%    595
  99%    616
 100%    642 (longest request)


mongodb_write.php

ab -c 100 -n 1000 'http://192.168.0.30/mongodb_write.php'

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mongodb_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.227498 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    814.67 [#/sec] (mean)
Time per request:       122.750 [ms] (mean)
Time per request:       1.227 [ms] (mean, across all concurrent requests)
Transfer rate:          150.71 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   11   7.7     11      30
Processing:    25  105  18.4    109     131
Waiting:        3   94  19.8     92     121
Total:         25  116  19.9    119     160

Percentage of the requests served within a certain time (ms)
  50%    119
  66%    126
  75%    131
  80%    133
  90%    138
  95%    141
  98%    145
  99%    150
 100%    160 (longest request)


mysql_write.php

ab -c 100 -n 1000 'http://192.168.0.30/mysql_write.php'

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mysql_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.480484 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    675.45 [#/sec] (mean)
Time per request:       148.048 [ms] (mean)
Time per request:       1.480 [ms] (mean, across all concurrent requests)
Transfer rate:          124.96 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.6      0       9
Processing:     5  139  57.9    151     619
Waiting:        5  139  58.0    151     619
Total:          5  140  57.8    151     625

Percentage of the requests served within a certain time (ms)
  50%    151
  66%    154
  75%    155
  80%    157
  90%    186
  95%    213
  98%    224
  99%    332
 100%    625 (longest request)


memcache_write.php

ab -c 100 -n 1000 'http://192.168.0.30/memcache_write.php'

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /memcache_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.244228 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190190 bytes
HTML transferred:       0 bytes
Requests per second:    803.71 [#/sec] (mean)
Time per request:       124.423 [ms] (mean)
Time per request:       1.244 [ms] (mean, across all concurrent requests)
Transfer rate:          148.69 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    8  10.6      1      37
Processing:    15  112  35.4    124     192
Waiting:        7  106  33.5    118     191
Total:         32  120  39.1    129     199

Percentage of the requests served within a certain time (ms)
  50%    129
  66%    143
  75%    150
  80%    156
  90%    165
  95%    175
  98%    185
  99%    190
 100%    199 (longest request)

全体を通したまとめ

書き込み時のTime taken for testsが
MongoDB>memcache>MySQL>CouchDB
の順番になりましたね。

こちらも納得がいく順番ですね!

MongoDB早いですね!!!流石です。
CouchDBはこれぐらいの速さなのですかね?
色々なドキュメントを見ると、MongoDBより遅いという記事を見ますが…。

あとがき

今度はこうしたらCouchDBが早くなるよ!的なアドバイス欲しいな〜。(あるかな?)

上記のテストサーバーは家でそのままにしてあるので、こんなテストして!っていう場合コメント下さい。
最後にid:yssk22さん有難う御座います!


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

MongoDB,CouchDB,MySQL,memcacheデータをPHPから読み込み&書き込み速度を検証してみました!

前回、前前回とMongoDB,CouchDBのインストール方法やphpからの使用方法を記事にしました。
CentOS5.4にCouchDBをインストールする方法! - @camelmasaの開発日記
CouchDBをphpから操作する方法。 - @camelmasaの開発日記
CentOS5.4にMongoDBをインストールする方法! - @camelmasaの開発日記
MongoDBをphpから操作する方法。 - @camelmasaの開発日記

MongoDBとCouchDBMySQL(MyISAM)とmemcacheを加えて読み込み(SELECT)と書き込み(INSERT)の速度を検証してみたいと思います。


環境

OS:CentOS5.4
PHP:5.3.1
MongoDB:1.2.2
CouchDB:0.10.1
MySQL:5.1.43
memcache:1.2.8

CPU:AMD(の何か)
メモリ:4GB
(ざっくりと検証です。)


読み取り時のソース

簡単に、"test"データベースの"test"テーブル(コレクション)の"test"データをphpから読み込みするプログラムです。
こんなソースで良いのか。


couchdb.php

<?php

require_once "HTTP/Request.php";

$http = new HTTP_Request('http://192.168.80.139:5984/test/93e4b62c166489b5ff94600e3003db88');
$response = $http->sendRequest();

mongodb.php

<?php

$mongo = new Mongo();

$db = $mongo->selectDB("test");
$col = $db->selectCollection("test");
$cursor = $col->findOne();

mysql.php

<?php
$link = mysql_pconnect('localhost', 'user', 'pass');
mysql_select_db('mytest', $link);
$result = mysql_query('SELECT `test` FROM `test`;');

memcache.php

<?php

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$memcache->get('test');

読み込み結果

couchdb.php

ab -c 100 -n 1000 'http://192.168.0.30/couchdb.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /couchdb.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   9.587989 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    104.30 [#/sec] (mean)
Time per request:       958.799 [ms] (mean)
Time per request:       9.588 [ms] (mean, across all concurrent requests)
Transfer rate:          19.29 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.5      0       9
Processing:    22  926 923.1    650    9554
Waiting:       21  860 568.4    650    5877
Total:         22  927 923.5    650    9555

Percentage of the requests served within a certain time (ms)
  50%    650
  66%    662
  75%    783
  80%   1099
  90%   1565
  95%   1735
  98%   3220
  99%   5656
 100%   9555 (longest request)


mongodb.php

ab -c 100 -n 1000 'http://192.168.0.30/mongodb.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mongodb.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.939626 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    515.56 [#/sec] (mean)
Time per request:       193.963 [ms] (mean)
Time per request:       1.940 [ms] (mean, across all concurrent requests)
Transfer rate:          95.38 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.5      0       8
Processing:    35  187  35.4    201     236
Waiting:       35  187  35.4    201     235
Total:         35  187  35.2    201     244

Percentage of the requests served within a certain time (ms)
  50%    201
  66%    202
  75%    204
  80%    204
  90%    207
  95%    208
  98%    209
  99%    226
 100%    244 (longest request)


mysql.php

ab -c 100 -n 1000 'http://192.168.0.30/mysql.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mysql.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.421236 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    703.61 [#/sec] (mean)
Time per request:       142.124 [ms] (mean)
Time per request:       1.421 [ms] (mean, across all concurrent requests)
Transfer rate:          130.17 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   5.1      0      22
Processing:     7  131 142.4    129    1404
Waiting:        7  131 142.3    129    1403
Total:         19  133 142.6    129    1416

Percentage of the requests served within a certain time (ms)
  50%    129
  66%    130
  75%    136
  80%    138
  90%    141
  95%    144
  98%    173
  99%   1339
 100%   1416 (longest request)


memcache.php

ab -c 100 -n 1000 'http://192.168.0.30/memcache.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /memcache.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.453866 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      191900 bytes
HTML transferred:       0 bytes
Requests per second:    687.82 [#/sec] (mean)
Time per request:       145.387 [ms] (mean)
Time per request:       1.454 [ms] (mean, across all concurrent requests)
Transfer rate:          128.62 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   15  10.2     14      45
Processing:    20  124  36.9    138     479
Waiting:       16  109  35.7    119     462
Total:         27  139  41.8    147     496

Percentage of the requests served within a certain time (ms)
  50%    147
  66%    163
  75%    172
  80%    176
  90%    186
  95%    191
  98%    198
  99%    203
 100%    496 (longest request)

読み込み結果検証

Requests per secondの順位下記。
MySQL(MyISAM)>memcache>MongoDB>>>CouchDB

MySQLが一番早い結果になるとは思わなかったです。(なって欲しくなかった)
でもFacebookでのMySQL運用術はKVSの様にシンプルなのかな。
(http://hyuki.com/yukiwiki/wiki.cgi?HowFriendFeedUsesMySqlToStoreSchemaLessData)

CouchDBはRESTでのデータ取得をPEARでやってしまってるので遅いのかな?
毎度毎度その処理部分のPHPコンパイルする分遅くなっているのでしょう。

MongoDBもmemcache並に早いですね。
MySQLがmemcacheより早いのは意外です。解せぬ〜。

次は書き込み時の速さを見てみます。


書き込み時のソース

couchdbはinsertの方法が調べれず…><
誰か教えて!ヘルプ!


mongodb_write.php

<?php

$mongo = new Mongo();

$db = $mongo->selectDB("test");
$col = $db->selectCollection("test");
$col->insert(array("test" => "test"));


mysql_write.php

<?php
        $link = mysql_pconnect('localhost', 'root', '');
        mysql_select_db('mytest', $link);
        $result = mysql_query("INSERT INTO `test` VALUES ('test');");


memcache_write.php

<?php

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$memcache->set("test", "test");

書き込み結果

mongodb_write.php

ab -c 100 -n 1000 'http://192.168.0.30/mongodb_write.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mongodb_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   9.325888 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190190 bytes
HTML transferred:       0 bytes
Requests per second:    107.23 [#/sec] (mean)
Time per request:       932.589 [ms] (mean)
Time per request:       9.326 [ms] (mean, across all concurrent requests)
Transfer rate:          19.84 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    4   9.7      0      36
Processing:    30  728 1111.7    176    9092
Waiting:        3  725 1112.6    176    9091
Total:         31  732 1111.0    177    9108

Percentage of the requests served within a certain time (ms)
  50%    177
  66%    910
  75%    937
  80%    938
  90%   1030
  95%   3103
  98%   3148
  99%   4285
 100%   9108 (longest request)


mysql_write.php

ab -c 100 -n 1000 'http://192.168.0.30/mysql_write.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mysql_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.484070 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    673.82 [#/sec] (mean)
Time per request:       148.407 [ms] (mean)
Time per request:       1.484 [ms] (mean, across all concurrent requests)
Transfer rate:          124.66 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.6      0       8
Processing:    41  142 165.8    129    1478
Waiting:       40  142 165.8    129    1478
Total:         41  143 165.8    129    1479

Percentage of the requests served within a certain time (ms)
  50%    129
  66%    131
  75%    132
  80%    133
  90%    139
  95%    144
  98%    161
  99%   1476
 100%   1479 (longest request)


memcache_write.php

ab -c 100 -n 1000 'http://192.168.0.30/memcache_write.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /memcache_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.701421 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190380 bytes
HTML transferred:       0 bytes
Requests per second:    587.74 [#/sec] (mean)
Time per request:       170.142 [ms] (mean)
Time per request:       1.701 [ms] (mean, across all concurrent requests)
Transfer rate:          108.73 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   17  11.0     18      44
Processing:    34  143  24.8    148     267
Waiting:        3  126  25.6    132     261
Total:         34  160  28.3    163     301

Percentage of the requests served within a certain time (ms)
  50%    163
  66%    175
  75%    181
  80%    185
  90%    192
  95%    195
  98%    201
  99%    205
 100%    301 (longest request)

全体を通したまとめ

大分ざっくりとした検証で納得がいくのかわかりませんが個人的には概ね満足。
インストール〜設定〜動作等で見えた部分は勉強になりました。

検証前は圧倒的にmemcacheが一番早いだろうと思ったのですが、読み書きともMySQLとほぼ同じ位で驚きました。
その後僅差でMongoDB。
CouchDBはhttp通信をphpでしてしまってるので良い結果が得られなかった感じですか。
(couchdb.so作って!)

恐らく皆さんが書いているように、RDBMSも単体では速度的に問題なくて、複雑なSQLを処理しようとするとボトルネックになるのでしょうか。
スケーリングを意識したSQLを書く事で、KVS並に高速化になるのかもしれません。
参考:http://hyuki.com/yukiwiki/wiki.cgi?HowFriendFeedUsesMySqlToStoreSchemaLessData


あとがき

うーん…。
こうしたらMongoDBが早くなるよ!的なアドバイス欲しいな〜。

上記のテストサーバーは家でそのままにしてあるので、こんなテストして!っていう場合コメント下さい。
テストしてブログに書きます。


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

MongoDBをphpから操作する方法。

前回の記事でMongoDBをインストールしましたので、MongoDBをphpから操作してみました。
CentOS5.4にMongoDBをインストールする方法! - @camelmasaの開発日記


testデータベース&testコレクションの作成

testデータベース&testコレクションの作成には下記のスクリプトを使用しました。
(Mongoクラスのコンストラクタは適切な値を設定して下さい。)

<?php

$mongo = new Mongo("192.168.80.139:27017");

$db = $mongo->selectDB("test");
$col = $db->createCollection("test");
$col->insert(array("test" => "test"));

スクリプトを実行すると、/data/db内にデータベースファイルが作成されます。

-rwxr-xr-x 1 root root         5  2月 22 15:14 mongod.lock
-rw------- 1 root root  67108864  2月 21 21:52 test.0
-rw------- 1 root root 134217728  2月 21 21:52 test.1
-rw------- 1 root root  16777216  2月 21 21:52 test.ns

SQLiteの様にデータベースの持ち運びも楽そうですね。
(しかしファイルサイズが大きいかも…)


PECLパッケージPECL::Package::mongoのインストール

phpから操作する為にPECL::Package::mongoをインストールします。

pecl install mongo

その後php.iniにextension=mongo.soを追加します。

extension=mongo.so

これでPECLパッケージPECL::Package::mongoのインストールが出来ました。
(ブラウザからphpを実行する場合は、httpデーモンをリスタートすると有効になります。)


phpからMongoDBを操作

PECLパッケージPECL::Package::mongoがインストール&設定が出来たので、


mongodb.phpの編集

<?php

$mongo = new Mongo();

$db = $mongo->selectDB("test");
$col = $db->selectCollection("test");
$cursor = $col->findOne();

var_dump($cursor);

上記のphpの実行結果です。

php mongodb.php
array(2) {
  ["_id"]=>
  object(MongoId)#6 (0) {
  }
  ["test"]=>
  string(4) "test"
}

phpからMongoDBのtestデータベース内のtestコレクションのデータを取得する事が出来ました!


まとめ

PPECLパッケージPECL::Package::mongoでMongoDBの値の取得を行う事が出来ました。
次こそはCouchDB,MongoDB,MySQLphpで実行した実行速度を計測してみたいと思います。


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

CouchDBをphpから操作する方法。

前回の記事でCouchDBをインストールしましたので、CouchDBphpから操作してみました。
CentOS5.4にCouchDBをインストールする方法! - @camelmasaの開発日記


testデータベース&testフィールドの作成

管理画面(_utils)の左上に表示されている"Create Database"リンクを押してデータベースを作成する事が出来ます。

画面の指示に従ってフィールド名も入力すると下記の画面が表示されました。

これでtestデータベース&testフィールドが作成出来ました。簡単ですね。


PECLパッケージphp_couchdbのインストール

phpから操作する為にcouchdb.soという野良PECLパッケージがあったので使用してみました。
Topdog.za.net :: PHP CouchDB Extension


…しかし下記のエラーが表示されてしまい、PHPでエラーになってしまいます。

PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib/php/modules/couchdb.so' - /usr/lib/php/modules/couchdb.so: undefined symbol: php_json_encode in Unknown on line 0

vim /usr/include/php/ext/json/php_json.h

*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2009 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author: Omar Kilani <omar@php.net>                                   |
  +----------------------------------------------------------------------+
*/

/* $Id: php_json.h 283185 2009-06-30 17:52:21Z stas $ */

#ifndef PHP_JSON_H
#define PHP_JSON_H

#define PHP_JSON_VERSION "1.2.1"
#include "ext/standard/php_smart_str.h"

extern zend_module_entry json_module_entry;
#define phpext_json_ptr &json_module_entry

#if defined(PHP_WIN32) && defined(JSON_EXPORTS)
#define PHP_JSON_API __declspec(dllexport)
#else
#define PHP_JSON_API PHPAPI
#endif

#ifdef ZTS
#include "TSRM.h"
#endif

ZEND_BEGIN_MODULE_GLOBALS(json)
        int error_code;
ZEND_END_MODULE_GLOBALS(json)

#ifdef ZTS
# define JSON_G(v) TSRMG(json_globals_id, zend_json_globals *, v)
#else
# define JSON_G(v) (json_globals.v)
#endif

PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_DC);
PHP_JSON_API void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC);

#endif  /* PHP_JSON_H */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */


…うーん。エラーの原因がわからない。
alpha版なので、もっと作りこんでほしいなあと思う。
MongoDBの場合はPECL::MONGOがあってPHPer歓喜なんだけども。
別の方法でCouchDBにアクセスしてみる事にします。


PEARパッケージHTTP_Requestのインストール

CouchDBはHTTPリクエストでデータが取得出来るので、PEARパッケージHTTP_Requestをインストールして実行する事にしました。

pear install HTTP_Request

couchdb.phpの編集

<?php

require_once "HTTP/Request.php";

$http = new HTTP_Request('http://192.168.80.139:5984/test/93e4b62c166489b5ff94600e3003db88');
$response = $http->sendRequest();

var_dump($http->getResponseBody());

上記のphpの実行結果です。

php couchdb.php

string(101) "{"_id":"93e4b62c166489b5ff94600e3003db88","_rev":"2-f62fade7a96a75f5bb109036ad107af0","test":"test"}
"

phpからCouchDBのtestデータベース内のtestフィールドのデータを取得する事が出来ました!


まとめ

PEAR::HTTP_RequestでCouchDBの値の取得を行う事が出来ました。
他に方法を知っている方がいらっしゃいましたら情報くださ〜い!


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

phpでFizzBuzz問題を解いてみました。

プログラマーと名乗っておきながらFizzBuzz問題が上手く解けなかったので復習。

<?php

for($i=1;$i<=100;$i++){
        $j++;$k++;

        if($j == 3){
                echo "Fizz";
                $j = 0;
        }

        if($k == 5){
                echo "Buzz";
                $k = 0;
        }

        if($j != 0 && $k != 0)
                echo $i;

        echo "\n";
}


もっと綺麗に書くなら下記。

<?php

for($i=1;$i<=100;$i++){

        if($i%3 == 0)
                echo "Fizz";

        if($i%5 == 0)
                echo "Buzz";

        if($i%3 != 0 && $i%5 != 0)
                echo $i;

        echo "\n";
}

%は高専時代にテストででたきりで、仕事では普段使わないですよね。


追記

世界のナベアツ…。なにこれ面白そう。
Fizz Buzz - Wikipedia

3の倍数と3の数字のつく時だけアホになりま〜す。

<?php

for($i=1;$i<=100;$i++){

        echo "世界のナベアツ<";

        if($i%3 == 0 || strstr($i, '3') )
                echo $i."!!!";

        else
                echo $i;

        echo "\n";
}

実行結果

世界のナベアツ<1
世界のナベアツ<2
世界のナベアツ<3!!!
世界のナベアツ<4
世界のナベアツ<5
世界のナベアツ<6!!!
世界のナベアツ<7
世界のナベアツ<8
世界のナベアツ<9!!!
世界のナベアツ<10
世界のナベアツ<11
世界のナベアツ<12!!!
世界のナベアツ<13!!!
世界のナベアツ<14
世界のナベアツ<15!!!
世界のナベアツ<16
世界のナベアツ<17
世界のナベアツ<18!!!
世界のナベアツ<19
世界のナベアツ<20
世界のナベアツ<21!!!
世界のナベアツ<22
世界のナベアツ<23!!!
世界のナベアツ<24!!!
世界のナベアツ<25
世界のナベアツ<26
世界のナベアツ<27!!!
世界のナベアツ<28
世界のナベアツ<29
世界のナベアツ<30!!!
世界のナベアツ<31!!!
世界のナベアツ<32!!!
世界のナベアツ<33!!!
世界のナベアツ<34!!!
世界のナベアツ<35!!!
世界のナベアツ<36!!!
世界のナベアツ<37!!!
世界のナベアツ<38!!!
世界のナベアツ<39!!!
世界のナベアツ<40
世界のナベアツ<41
世界のナベアツ<42!!!
世界のナベアツ<43!!!
世界のナベアツ<44
世界のナベアツ<45!!!
世界のナベアツ<46
世界のナベアツ<47
世界のナベアツ<48!!!
世界のナベアツ<49
世界のナベアツ<50
世界のナベアツ<51!!!
世界のナベアツ<52
世界のナベアツ<53!!!
世界のナベアツ<54!!!
世界のナベアツ<55
世界のナベアツ<56
世界のナベアツ<57!!!
世界のナベアツ<58
世界のナベアツ<59
世界のナベアツ<60!!!
世界のナベアツ<61
世界のナベアツ<62
世界のナベアツ<63!!!
世界のナベアツ<64
世界のナベアツ<65
世界のナベアツ<66!!!
世界のナベアツ<67
世界のナベアツ<68
世界のナベアツ<69!!!
世界のナベアツ<70
世界のナベアツ<71
世界のナベアツ<72!!!
世界のナベアツ<73!!!
世界のナベアツ<74
世界のナベアツ<75!!!
世界のナベアツ<76
世界のナベアツ<77
世界のナベアツ<78!!!
世界のナベアツ<79
世界のナベアツ<80
世界のナベアツ<81!!!
世界のナベアツ<82
世界のナベアツ<83!!!
世界のナベアツ<84!!!
世界のナベアツ<85
世界のナベアツ<86
世界のナベアツ<87!!!
世界のナベアツ<88
世界のナベアツ<89
世界のナベアツ<90!!!
世界のナベアツ<91
世界のナベアツ<92
世界のナベアツ<93!!!
世界のナベアツ<94
世界のナベアツ<95
世界のナベアツ<96!!!
世界のナベアツ<97
世界のナベアツ<98
世界のナベアツ<99!!!
世界のナベアツ<100

追記

@kimuryから指摘があったので転載。
http://twitter.com/kimury

<?php

for ($i=1;$i<=100;$i++) { 
    $s=($i%3==0)?'Fizz':'';
    $s.=($i%5==0)?'Buzz':'';
    $camekmasa=(empty($s))?$i:$s;
    echo $camekmasa."\n"; }

@kimuryすげー。


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/