主夫ときどきプログラマ

データベース、Webエンジニアリング、コミュニティ、etc

PHPでmemcachedを使うときのモジュールパフォーマンス比較

PHPにはmemcachedを使うための主要モジュールが2種類あります。
機能的にいくつかの違いがありますが、今回は実行速度について比較してみました。

memcached の実行環境を整える

memcached のインストール

yum でインストールすることができます。今回のOSはFedora14です。

$ sudo yum install memcached
memcached サーバーの起動

インストールが完了すると、他のサービス同様に /etc/rc.d/init.d/memcached に起動スクリプトが設置されるので、

$ sudo /etc/rc.d/init.d/memcached start
$ sudo /sbin/service memcached start

など、各方法で memcached デーモンを起動することができます。一方コマンドからも起動することができます。

$ memcached -p 11211 -m 64m -vv

この状態だとmemcachedが起動しコマンドラインが返ってこないので
デーモン(バックグラウンド)で実行する -d オプションをつけます。

$ memcached -p 11211 -m 64m -d

これで準備完了です。


memcacheモジュールとmemcacedモジュールを比較する

PHPにはemcachedを利用するに当たって、memcacheモジュールとmemcachedモジュールの2種類があります。
これらもyumを使ってインストールできます。

$ sudo yum install php-pecl-memcache
$ sudo yum install php-pecl-memcached

どちらが早いのか検証してみましょう。以下のようなコードを用意しました。
100000件のデータの読み書き速度を比較します。

memcache module
store_mem.php
<?php
$memcache = new Memcache();
$memcache->addServer("localhost", 11211);
$memcache->flush();

for ($i = 0; $i < 100000; $i++) {
    $memcache->set(md5($i), crc32($i), 0, 1800);
}
load_mem.php
<?php
$memcache = new Memcache();
$memcache->addServer("localhost", 11211);

for ($i = 0; $i < 100000; $i++) {
    $memcache->get(md5($i));
}
実行結果
$ time php store_mem.php
real     0m5.773s
user     0m1.187s
sys     0m2.169s

$ time php load_mem.php
real     0m5.489s
user     0m1.259s
sys     0m2.103s
memcached module
store_memd.php
<?php
$memcache = new Memcached();
$memcache->addServer("localhost", 11211);
$memcache->flush();

for ($i = 0; $i < 100000; $i++) {
    $memcache->set(md5($i), crc32($i), 1800);
}
load_memd.php
<?php
$memcache = new Memcached();
$memcache->addServer("localhost", 11211);

for ($i = 0; $i < 100000; $i++) {
    $memcache->get(md5($i));
}
実行結果
$ time php store_memd.php
real     0m5.289s
user     0m1.310s
sys     0m1.497s

$ time php load_memd.php
real     0m4.667s
user     0m0.752s
sys     0m1.809s

memcached モジュールのほうが早いという結果になりました。

保存するデータ型の検証

PHPからmemcacheを使う場合、どのようなデータ型に対応しているのでしょうか。
int, string, array の3種類のデータ型について検証してみました。

<?php
$memcache = new Memcache();
$memcache->addServer('localhost', 11211);
$memcache->flush();

$v1 = 100;
$v2 = 'string';
$v3 = array(1, 2, 3);
$v4 = array('type' => 'reguler', 'color' => 'blue');

$memcache->set(1, $v1);
$memcache->set(2, $v2);
$memcache->set(3, $v3);
$memcache->set(4, $v4);

var_dump($memcache->get(1));
var_dump($memcache->get(2));
var_dump($memcache->get(3));
var_dump($memcache->get(4));
実行結果
int(100)
string(6) "string"
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}
array(2) {
  ["type"]=>
  string(7) "reguler"
  ["color"]=>
  string(4) "blue"
}

整数、文字列、配列などのデータ型を気にすることなく set/get できました。
内部的にはシリアライズされてmemcachedに保存されます。
ここでは試していませんがオブジェクトの保存にも対応しています。ただし読み出し側でもクラス定義の読み込みが必要です。
これは利用がとても簡単になりますね。


memcachedの状態を知る

memcached-tool コマンドでmemcachedの状態を知ることが出来ます。
オプション(引数)はdisplay stats dump の3つ。Host, Port を指定するときは以下のようにします。
memcached-tool [mode]

$ memcached-tool localhost:11211 display
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  2     120B     10827s       1    3874      no        0        0    0
  4     192B    588190s       1       2      no        0        0    0
  5     240B    946076s       2    1069      no        0        0    0
  6     304B    946076s      34   41925      no        0        0    0
  7     384B    946075s       2    2760      no        0        0    0

Full?:空きチャンクの有無
Evicted:期限切れ前に削除した回数

$ memcached-tool stats
#localhost:11211   Field       Value
         accepting_conns           1
               auth_cmds           0
             auth_errors           0
                   bytes    10950856
              bytes_read     6150939
           bytes_written      800696
              cas_badval           0
                cas_hits           0
              cas_misses           0
               cmd_flush           1
                 cmd_get           0
                 cmd_set      100000
             conn_yields           0
   connection_structures          11
        curr_connections          10
              curr_items      100000
               decr_hits           0
             decr_misses           0
             delete_hits           0
           delete_misses           0
               evictions           0
                get_hits           0
              get_misses           0
               incr_hits           0
             incr_misses           0
          limit_maxbytes    67108864
     listen_disabled_num           0
                     pid        5579
            pointer_size          64
               reclaimed           0
           rusage_system    1.773730
             rusage_user    0.308953
                 threads           4
                    time  1327019806
       total_connections          15
             total_items      100000
                  uptime         123
                 version       1.4.5

bytes:現在の使用メモリを表します。期限切れのデータも含まれるためこの値が容量いっぱいでもメモリ不足とは一概には言えません。
evictions:容量(メモリ)不足となり期限切れ前にデータを削除した回数。この回数が多いようだと容量不足となっています。
limit_maxbytes:memcacheの最大容量(バイト)
cmd_get:GETコマンド発行の累計
get_hits:リクエストでキーが見つかった数
get_misses:リクエストでキーが見つからなかった数

$ memcached-tool dump
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 100000
Dumping bucket 2 - 100000 total items
add b3a8c9d7b4dd2c400ce3f7776f1f6cb8 768 1327021567 10
2027185355
add ba7c76b3377564c295f8afdfa298ca38 768 1327021568 10
3177254485
add 00c9157a614a13927382c42cc26dbfd4 768 1327021568 10
3244397292
add 1f376f49e57d4d7787a5b5b4489edd25 768 1327021567 10
1086221540
add 2a1d623c15bbdb68cf45130d7eefd312 768 1327021567 10
4031782350

memcachedのデータが表示されます。