@blog.justoneplanet.info

日々勉強

CentOSにMongoDBをインストールする

■インストール

yumリポジトリの追加

以下のコマンドでリポジトリを追加する。

vi /etc/yum.repos.d/mongo.repo

以下のようにファイルの中身を記述する。

[10gen]
name=10gen Repository
baseurl=http://downloads.mongodb.org/distros/centos/5.4/os/i386/
gpgcheck=0

保存したら以下のコマンドを実行する。

yum install mongo-stable*

起動

以下のコマンドで起動してみる。

/etc/init.d/mongod start

以下のコマンドで起動したか確認する。

lsof -i:27017

以下のコマンドで自動起動を設定する。

chkconfig mongod on
chkconfig mongod --list

参考

CentOS and Fedora Packages

amazon linuxにインストールする

wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.0.2.tgz
tar xvzf mongodb-linux-x86_64-2.0.2.tgz
mv mongodb-linux-x86_64-2.0.2 /var/lib/mongodb
mkdir /mnt/db
/var/lib/mongodb/bin/mongod --fork --logpath ~/mongod.log --dbpath /mnt/db/

■PHPから扱う準備

以下のコマンドでpecl_mongoをインストールする。

pecl clear-cache
pecl install mongo

以下のコマンドで設定ファイルを生成する。

cp /etc/php.d/curl.ini /etc/php.d/mongo.ini
vi /etc/php.d/mongo.ini

設定ファイルは以下のような記述だ。

; Enable mongo extension module
extension=mongo.so

設定が終わったらhttpdをreloadする。

/etc/init.d/httpd reload

参考

PHP & MongoDB Sitting in a Tree: Part 1

英語だが非常に参考になるドキュメントだ。

■ベンチマーク

以下のコードを使用してベンチマークしてみた。

$dbh = new Mongo();
$dbh = $dbh->testdb;
$col = $dbh->bench;
$start = microtime(true);
for($i = 0; $i < 1000; $i++){
    $col->insert(
        array(
            'key'   => "key{$i}",
            'value' => "abcdefghijklmnopqrstuvwxyz"
        ),
        true
    );
}
$end = microtime(true);
print($end - $start);0.66766786575317
$dbh->close();

但し、2回目以降は0.2秒以下になる。

データを取り出す

本当にデータが挿入されているのか不安になったので、以下のコードを使用してデータを覗いてみた。

$res = $col->find();
$s = 0;
foreach($res as $doc){
    print("<pre>{$s}");
    var_dump($doc);
    print('</pre>');
    $s++;
}
$dbh->close();

ベンチマークをしておいて言うのもオカシイが、データストアにおいて全く同じ条件というものは再現できないので単純に比較してはならない。用途に応じた選択が必要である。

amazon Linuxにインストールする

amazon Linuxにインストールする場合は以下のようにする。

curl -O  http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.0.2.tgz
tar xzf mongodb-linux-x86_64-2.0.2.tgz
mv mongodb-linux-x86_64-2.0.2 /var/lib/mongodb
cd /var/lib/mongodb/bin
mkdir /mnt/db
./mongod --fork --logpath /var/log/mongod.log --dbpath /mnt/db/

memcachedをインストールする

あまり興味がないが仕事で使うので試してみた。♪(´ε` )

■インストール

以下のコマンドを実行してmemcachedをインストールする。

yum install memcached
/etc/init.d/memcached start
chkconfig memcached on

設定ファイルは以下のコマンドで編集できる。編集が必要な場合は書き換えると良い。

vi /etc/sysconfig/memcached

PHPから使いたいので以下のようにpeclコマンドでインストールする。

pecl clear-cache
pecl install memcache
cp /etc/php.d/curl.ini /etc/php.d/memcache.ini
vi /etc/php.d/memcache.ini

以下のようにファイルを記述する。

; Enable memcache extension module
extension=memcache.so

ファイルを上書き保存したらhttpをreloadする。

/etc/init.d/httpd reload

■ベンチマーク

以下のコードを使用し簡単にベンチマークしてみた。

$memcache = new Memcache();
$memcache->connect('localhost', 11211);
$start = microtime(true);
for($i = 0; $i < 1000; $i++){
    $memcache->set("k{$i}", "abcdefghijklmnopqrstuvwxyz");
}
$end = microtime(true);
print($end - $start);// 0.07976508140564

さすがメモリにしかデータがないだけあって爆速だ。

GDとImageMagickの速度を比較してみた

■GD

以下のようなコードを用いてGDで合成画像を1000枚生成した時の時間を調べた。

$layers = array(
    0 => 'dress_back.png',
    1 => 'dress_back.png',
    2 => 'body.png',
    3 => 'dress.png',
    4 => 'bag.png',
    5 => 'bag.png',
    6 => 'face.png',
    7 => 'hear.png',
    8 => 'teara.png',
);
$start = microtime(true);
for($i = 0; $i < 10; $i++){
    $image = imagecreatefrompng("background.png");
    foreach($layers as $key => $value){
        $layer = imagecreatefrompng($value);
        imagecopy($image, $layer, 0, 0, 0, 0, 410, 454);
    }
    imagegif($image, "image{$i}.gif");
}
$end = microtime(true);
print($end - $start);

/*
 * windows
 * 10 => 0.27269101142883
 * 100 => 2.1620790958405
 * 1000 => 24.812913894653
 *
 * linux
 * 10 => 0.21701502799988
 * 100 => 2.1362149715424
 * 1000 => 21.695859193802
 */

■ImageMagic

以下のようなコードを用いてImageMagickで合成画像を1000枚生成した時の時間を調べた。

$layers = array(
    0 => 'dress_back.png',
    1 => 'dress_back.png',
    2 => 'body.png',
    3 => 'dress.png',
    4 => 'bag.png',
    5 => 'bag.png',
    6 => 'face.png',
    7 => 'hear.png',
    8 => 'teara.png',
);
set_time_limit(0);
//$path = 'C:\xampp\htdocs\local.sample.org\public_html\\';
$path = '/home/local.sample.org/trunk/public_html/imagick/';
$start = microtime(true);
for($i = 0; $i < 1000; $i++){
    $image = new Imagick("{$path}background.png");
    foreach($layers as $key => $value){
        $layer = new Imagick($path . $value);
        $image->compositeImage($layer, $layer->getImageCompose(), 0, 0);
    }
    $image->writeImage("{$path}image{$i}.gif");
}
$end = microtime(true);
print($end - $start);

/*
 * windows
 * 10 => 2.2297260761261
 * 100 => 24.065160989761
 * 1000 => 247.36853098869
 *
 * linux
 * 10 => 0.33637809753418
 * 100 => 3.3278291225433
 * 1000 => 33.274304866791
 */

■結果

Linuxの場合は1.5倍ImageMagickが遅かった。Windowsの場合は10倍ImageMagickが遅かった。

PHP5.3の名前空間を使ってみる

そういえば今まであんまり使わなかったけど、PHP5.3の名前空間を使ってみる。

namespace Lib\Mobile;

class Emoji{
    public function getEmoji(){
        return '絵文字一覧です';
    }
}

上述のように定義した場合は、以下のように使用することができる。

require_once 'Emoji.php';

$emoji = new Lib\Mobile\Emoji();
var_dump($emoji->getEmoji());// 絵文字一覧です

また、以下のようにuseを使用してインポートを先頭で明示することもできる。

require_once 'Emoji.php';
use Lib\Mobile as MobileLib;

$emoji = new MobileLib\Emoji();
var_dump($emoji->getEmoji());// 絵文字一覧です

asを使用しなかった場合は以下のように最後の単語がasの後にあるようなイメージだ。

require_once 'Emoji.php';
use Lib\Mobile;

$emoji = new Mobile\Emoji();
var_dump($emoji->getEmoji());// 絵文字一覧です

なんとなーく現時点では使いそうもないなーφ(-ω-。`)。

PHP5.3の遅延静的束縛を使ってみる

そういえば今まであんまり使わなかったけど、遅延静的束縛というものを使ってみる。

class Animal{
    public function cry(){
        print(self::_getVoice());
    }
    protected static function _getVoice(){
        return '(「・ω・)「がおー';
    }
}
class Dog extends Animal{
    protected static function _getVoice(){
        return 'bow!';
    }
}
$pochi = new Dog();
$pochi->cry();// (「・ω・)「がおー

マニュアルを参照すると以下のような記述がされている。

静的遅延束縛は直近の “非転送コール”(self:: や parent::、static:: による静的なコール、 あるいはクラス階層の中での forward_static_call() によるコール) のクラス名を保存します。 静的メソッドの場合、これは明示的に指定されたクラス (通常は :: 演算子の左側に書かれたもの) となります。静的メソッド以外の場合は、そのオブジェクトのクラスとなります。 get_called_class() 関数を使うとコール元のクラス名を文字列で取得できます。 static:: はこのクラスのスコープとなります。

selfでは直近のクラスが参照されるので、上述の例の場合はselfはAnimalクラスということになる。pochiにもっと犬らしくして欲しい時は以下のようにstaticを用いて記述する。

<?php
class Animal{
    public function cry(){
        print(static::_getVoice());
    }
    protected static function _getVoice(){
        return '(「・ω・)「がおー';
    }
}
class Dog extends Animal{
    protected static function _getVoice(){
        return 'bow!';
    }
}
$pochi = new Dog();
$pochi->cry();// bow!

親クラスから子クラスのメソッドが呼び出される感じなのでアクセス権はprotected以上でないと「Fatal error: Call to private method」となる。

Pythonでは以下のように問題なく、selfを使用することができる。

class Animal:
    def cry(self):
        print(self._getVoice())
    def _getVoice(self):
        return 'gao!'

class Dog(Animal):
    def _getVoice(self):
        return 'bow!'

pochi = Dog()
pochi.cry()# bow!

Javaの場合はそもそもselfがない。クラス名を直接指定する必要があり、明示しない時はカレントクラスのメソッドがコールされる。

static class Animal{
    public static String cry(){
        return getVoice();// 明示しない場合はAnimal.となる
    }
    protected static String getVoice(){
        return "(「・ω・)「がおー";
    }
}
static class Dog extends Animal{
    protected static String getVoice(){
        return "bow!";
    }
}
Dog pochi = new Dog();
Log.e("cry", pochi.cry());// (「・ω・)「がおー

Tokyo Tyrantを使ってみる

仕事で使うかもしれないので一応やってみる。

■インストール

wget http://fallabs.com/tokyocabinet/tokyocabinet-1.4.46.tar.gz
wget http://fallabs.com/tokyotyrant/tokyotyrant-1.1.41.tar.gz
tar xvzf tokyocabinet-1.4.46.tar.gz
tar xvzf tokyotyrant-1.1.41.tar.gz
cd tokyocabinet-1.4.46
./configure
make
make install
cd ../tokyotyrant-1.1.41
./configure

エラー1

tokyo cabinetが先にインストールされていないと以下のエラーがでる。

checking for tcutil.h... no
configure: error: tcutil.h is required
make
make install

ちょっと動かしてみる。

ttserver

■PHPから使う

pecl install tokyo_tyrant-beta
cp /etc/php.d/curl.ini /etc/php.d/tt.ini

元の記述を削除して、以下の記述に書き換える。

extension=tokyo_tyrant.so

■ベンチマーク

以下のコードを使用して簡単にベンチマークしてみた。

$start = microtime(true);
$tt    = new TokyoTyrant("localhost");
for($i = 0; $i < 10000; $i++){
    $tt->put("k{$i}", "abcdefghijglmnopqrstuvwxyz");
}
$end = microtime(true);
print($end - $start);//0.65114498138428

ベンチマークをしておいて言うのもオカシイが、データストアにおいて全く同じ条件というものは再現できないので単純に比較してはならない。用途に応じた選択が必要である。

PHPのマジックメソッド

ヒョッコリまとめておくことにした

■__constructと__destruct

まぁ、説明するまでもないヤツ( ̄△ ̄;)エッ・・?

<?php
class Dog
{
    private $_name;
    public function __construct($name)
    {
        $this->_name = $name;
    }
    public function __destruct()
    {
        echo "{$this->_name}, Bye!";
    }
}
$pochi = new Dog('pochi');
unset($pochi);// pochi, Bye!
print('end...');

まぁ、こんな感じ。実用性のあるコードを書くとしたら以下のようなコードが良いかもしれない。

class Db
{
    private $dbh;
    public function __construct()
    {
        $this->_dbh = $this->_connect();
    }
    public function __destruct()
    {
        unset($this->_dbh);
    }
}

これにより接続をどこかでunsetすればリソースが早く開放できる。

■__setと__get

これらは明示されていないプロパティへの操作がトリガとなる。

class Dog
{
    private $_name;
    public function __construct($name)
    {
        $this->_name = $name;
    }
    public function __set($name, $value)
    {
        throw new Exception("Don't tell me that {$name} is {$value}!");
    }
    public function __get($name)
    {
        throw new Exception("Don't ask me about {$name}!");
    }
}
$pochi = new Dog('pochi');
try{
    $pochi->age = 25;
}
catch(Exception $e){
    print($e->getMessage());// Don't tell me that age is 25!
}
try{
    print($pochi->age);
}
catch(Exception $e){
    print($e->getMessage());// Don't ask me about gender!
}

まぁ、こんな感じだね。

■__issetと__unset

プロパティに対してのisset()やunset()がトリガとなる。

class Dog
{
    private $_name;
    public function __construct($name)
    {
        $this->_name = $name;
    }
    public function __isset($name)
    {
        throw new Exception('__isset');
    }
    public function __unset($name)
    {
        throw new Exception('__unset');
    }
}

$pochi = new Dog('pochi');
try{
    if(isset($pochi->age)){
        // something
    }
}
catch(Exception $e){
    print($e->getMessage());// __isset
}
try{
    unset($pochi->age);
}
catch(Exception $e){
    print($e->getMessage());// __unset
}

■__callと__callStatic

定義されていないインスタンスメソッドやクラスメソッドの呼び出しがトリガとなる。通常、定義されていないメソッドをコールするとエラーが発生する一方で、この2つのメソッドを定義するとエラーが発生しなくなる。従って何らかの処理を挟んだ後、該当しない場合は例外を発生させたほうが良い。

class Dog
{
    private $_name;
    public function __construct($name)
    {
        $this->_name = $name;
    }
    public function __call($method, $args)
    {
        throw new Exception('__call');
    }
    public static function __callStatic($method, $args)
    {
        throw new Exception('__callStatic');
    }
}

$pochi = new Dog('pochi');
try{
    $pochi->cry('bow!');
}
catch(Exception $e){
    print($e->getMessage());// __call
}
try{
    Dog::getData();
}
catch(Exception $e){
    print($e->getMessage());// __callStatic
}

■__sleepと__wakeup

オブジェクトがserializeやunserializeがトリガとなる。通常のクラスでは有用性があまり分からないが、リソースがプロパティに含まれている場合、serializeはリソース型をシリアライズできない。従って、__sleepと__wakeupを実装すると良いかもしれない。

class Db
{
    private $_host   = 'localhost';
    private $_dbname = 'db';
    private $_dbuser = 'user';
    private $_dbpass = 'pass';
    private $_dbh;
    public function __construct()
    {
        $this->_connect();
    }
    public function __sleep()
    {
        return array('_host', '_dbname', '_dbuser', '_dbpass');
    }
    public function __wakeup()
    {
        $this->_connect();
    }
    public function getConn()
    {
        return $this->_dbh;
    }
    private function _connect()
    {
        try {
            $this->_dbh = new PDO("mysql:host={$this->_host};dbname={$this->_dbname}", $this->_dbuser, $this->_dbpass);
            $this->_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->_dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
        }
        catch(PDOException $e){
            print($e->getMessage());
        }
    }
}
$db = new Db();
var_dump($db->getConn());// object(PDO)#2 (0) { }
$val = serialize($db);
$db = unserialize($val);
var_dump($db->getConn());// object(PDO)#4 (0) { }

ちなみに__sleepと__wakeupを記述せずに実行すると以下のようなエラーがFatalが発生する。

class Db
{
    private $_host   = 'localhost';
    private $_dbname = 'db';
    private $_dbuser = 'user';
    private $_dbpass = 'pass';
    private $_dbh;
    public function __construct()
    {
        $this->_connect();
    }
    public function getConn()
    {
        return $this->_dbh;
    }
    private function _connect()
    {
        try {
            $this->_dbh = new PDO("mysql:host={$this->_host};dbname={$this->_dbname}", $this->_dbuser, $this->_dbpass);
            $this->_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->_dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
        }
        catch(PDOException $e){
            print($e->getMessage());
        }
    }
}
$db = new Db();
var_dump($db->getConn());// object(PDO)#2 (0) { }
$val = serialize($db);// Fatal error: Uncaught exception 'PDOException' with message 'You cannot serialize or unserialize PDO instances'
$db = unserialize($val);
var_dump($db->getConn());

■__invoke

こいつを使うとコールバック関数とかが気持ちよく書ける。

class Group
{
    public function __invoke($params)
    {
        return $params . ', bow!';
    }
}
$group = new Group();
$result = array_map($group, array('Pochi', 'Shiro'));
var_dump($result);
/*
array(2) {
  [0]=>
  string(11) "Pochi, bow!"
  [1]=>
  string(11) "Shiro, bow!"
}
*/

今までPHPのコールバック関数が気持ち悪くて書きたくなかったが改心しました。

androidでPHPを動かしてみる

androidではPHPも動かせるらしいぞ。PHPでもandroidが動かせるらしいぞ。((o(^-^)o))ワクワク

■準備

提供元不明のアプリケーションをインストールできるように設定しておくこと。ちなみに我が家ではいつも使用しているXperiaはなんとなく使いたくはないのでHT03Aを使用した。

■Scripting Layer for Android

Scripting Layer for Androidをインストールする。pythonやperlをandroid上で動作させるためのものらしい。以下のQRコードをスキャンするだけで良い。

Scripting Layer for Android

■PhpForAndroid.apk

PhpForAndroid.apkをインストールする。以下のQRコードをスキャンするだけで良い。

PhpForAndroid.apk

■サンプルコードの実行

インストール後、「PHP for Android」を起動して「install」をクリックしたら終了し「SL4A」を起動する。ファイルのリストがあるので試しにvibrate.phpを起動すると端末が振動するはずだ。その状態から、「menu」を押して「exit & edit」を選択するとコードを参照できる。

<?php
require_once('Android.php');
$android = new Android();
$android->vibrate();

おー!!!ヽ( ´¬`)ノ

サンプルスクリプトの中の」phpinfo.phpを動かしたところ、PHPのバージョンは5.3.3RC3だった。(。・ω・)ノ゙

■APIリファレンス

APIリファレンスをみて色々探ってみる。

■PHPの実行

コードを書く前に、適当なファイルを開きファイル名を変更しておく。

コード

以下のスクリプトを「menu」→「save & run」で実行してみる。

<?php
require_once('Android.php');
$android = new Android();
$android->phoneCallNumber("09011111111");

おー!電話がかかるではないか!!!キャ━━━━(゚∀゚)━━━━!!

■まとめ

凄く色んな事ができる!しかし意義を感じられないよね?( ´ー`)

ThriftをインストールしてPHPからCassandraを使う

ThriftでPHPからCassandraが扱えるらしいぞ((o(´∀`)o))ワクワク

■ソースの入手と解凍

wget http://www.meisei-u.ac.jp/mirror/apache/dist//incubator/thrift/0.4.0-incubating/thrift-0.4.0.tar.gz
tar zxvf thrift-0.4.0.tar.gz

■前準備

cd thrift-0.4.0
./configure

エラー1

configureの途中で以下の様なエラーがでた。

checking for boostlib >= 1.33.1... configure: error: We could not detect the boost libraries (version 1.33 or higher). If you have a staged boost library (still not installed) please specify $BOOST_ROOT in your environment and do not give a PATH to --with-boost option.  If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.
対処1

boostlib1.33.1以上が必要らしいので以下のコマンドでインストールする。

yum install boost-devel

■インストール

make
make install

エラー2

makeの途中で以下の様なエラーがでた。

BUILD FAILED
/home/admin/thrift-0.4.0/lib/java/build.xml:96: Class org.apache.tools.ant.taskdefs.ConditionTask doesn't support the nested "typefound" element.
対処1

antのバージョンがイカンらしい。(;>_<;)

As you mention, there is no package for ant 1.7.1 on RHEL 5. Until the Hadoop build is fixed to work on ant 1.6 (which will likely not happen soon if ever), you will need to:

  1. Download the Apache Ant 1.7.1 tarball
  2. Extract it
  3. Setup the environment variable ANT_HOME to point to the location you extracted the tarball
  4. Add $ANT_HOME/bin to the front of your $PATH

以下のサイトを参考にソースからインストールする。

他にもインストールに必要なライブラリがあるらしいのでインストール。

yum install libtool
yum install flex
yum install bison
yum install ruby-devel
yum install libevent-devel

再チャレンジする!

make clean
./configure
make
make install

確認してみる。

thrift -version
Thrift version 0.4.0

キタ━━━━(゚∀゚)━━━━!!

■PHPから使う準備

Cassandraの場所を確認

cassandraの場所を忘れたので確認する。

whereis cassandra
cassandra: /usr/local/cassandra

モジュールを生成

以下のコマンドを実行するとPHP用のモジュールが生成される。

cp /usr/local/cassandra/interface/cassandra.thrift /home/admin/module/cassandra.thrift
thrift --gen php /home/admin/module/cassandra.thrift
ls /home/admin/module/gen-php/cassandra
Cassandra.php  cassandra_constants.php  cassandra_types.php

Thriftのphp用ライブラリをコピー

cp -r /home/admin/thrift-0.4.0/lib/php/src/* /home/admin/gen-php/cassandra/

■PHPから使う

いよいよだ。

ディレクトリ構成

  • ext
  • packages
  • protocol
  • server
  • transport
  • autoload.php
  • Thrift.php

packages/cassandraの中に以下の3ファイルが含まれる。

  • Cassandra.php
  • cassandra_constants.php
  • cassandra_types.php

データの登録

以下のようにしてCassandraにデータを登録することができる。

<?php
require_once 'cassandra/Thrift.php';
require_once 'cassandra/protocol/TBinaryProtocol.php';
require_once 'cassandra/transport/TSocket.php';
require_once 'cassandra/transport/TBufferedTransport.php';
require_once 'cassandra/packages/cassandra/Cassandra.php';
require_once 'cassandra/packages/cassandra/cassandra_types.php';

$socket    = new TSocket('192.168.11.3', 9160);
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol  = new TBinaryProtocolAccelerated($transport);
$client    = new CassandraClient($protocol);
$transport->open();

// set column path
$columnPath = new cassandra_ColumnPath();
$columnPath->column_family = 'Standard1';
$columnPath->column        = 'column';

// set value
$client->insert(
    'Keyspace1',
    'key',
    $columnPath,
    'value',
    time(),
    cassandra_ConsistencyLevel::ONE
);

// close
$transport->close();

データの取得

以下のようにして指定したキーを値を得ることができる。

<?php
require_once 'cassandra/Thrift.php';
require_once 'cassandra/protocol/TBinaryProtocol.php';
require_once 'cassandra/transport/TSocket.php';
require_once 'cassandra/transport/TBufferedTransport.php';
require_once 'cassandra/packages/cassandra/Cassandra.php';
require_once 'cassandra/packages/cassandra/cassandra_types.php';
$socket    = new TSocket('192.168.11.3', 9160);
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol  = new TBinaryProtocolAccelerated($transport);
$client    = new CassandraClient($protocol);
$transport->open();

// set column path
$columnPath = new Cassandra_ColumnPath();
$columnPath->column_family = 'Standard1';
$columnPath->column        = 'column';

// search
$result = $client->get(
    'Keyspace1',
    'key',
    $columnPath,
    null,
    Cassandra_ConsistencyLevel::ONE
);

// close
$transport->close();

// get the result
$data = $result->column->value;
var_dump($data);//value

■ベンチマーク

以下のコードで簡単にベンチマークしてみた。

<?php
require_once 'cassandra/Thrift.php';
require_once 'cassandra/protocol/TBinaryProtocol.php';
require_once 'cassandra/transport/TSocket.php';
require_once 'cassandra/transport/TBufferedTransport.php';
require_once 'cassandra/packages/cassandra/Cassandra.php';
require_once 'cassandra/packages/cassandra/cassandra_types.php';

$socket    = new TSocket('192.168.11.5', 9160);
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol  = new TBinaryProtocolAccelerated($transport);
$client    = new CassandraClient($protocol);
$transport->open();

// set column path
$columnPath = new cassandra_ColumnPath();
$columnPath->column_family = 'Standard1';
$columnPath->column        = 'column';

// set value
$start = microtime(true);
for($i = 0; $i < 1000; $i++){
    $client->insert(
        'Keyspace1',
        'key',
        $columnPath,
        'abcdefghijklmnopqrstuvwxyz',
        time(),
        cassandra_ConsistencyLevel::ONE
    );
}
$end = microtime(true);
print($end - $start);// 0.7892119884491

// close
$transport->close();

1回目の計測値だけ倍程度の時間がかかったが2回目以降は安定して上述の時間と変わらないような処理時間であった。また、他のKVSのベンチマークと単純に比較できない理由として以下のように考えた。

  • Cassandraはテーブルのような高次元のデータ構造を持っている点
  • 今回、CassandraにはPHPで記述されたライブラリを経由してアクセスしている点

ベンチマークをしておいて言うのもオカシイが、データストアにおいて全く同じ条件というものは再現できないので単純に比較してはならない。用途に応じた選択が必要である。