« 2007年11月 | メイン | 2008年05月 »

2007年12月16日

Cache::Memcached::Fastを試す

Perlの新しいmemcachedクライアント「Cache::Memcached::Fast」がでていたので試してみた
結論から言うと、これは使えそう。

まず、C::M::Fastはmemcached-1.2.4でサポートされた、append, prepend, cas, gets, gets_multiをサポートする唯一のPerlクライアントです。また、常に問題となるCache分散にKetama consistent hashing algorithmをサポートしているためCacheの組み替えを最小限にしてCacheサーバの追加が行えます。

手元のベンチマークでは50%〜80%、処理によりますが300%以上高速化されてます
インストールは普通にCPANから行えます。ただし、memached-.1.2.4が動いていないとmake testに失敗します。Cache::Memcahedとの互換性もあり、単純な入れ替えで使えるようです。

軽くベンチマークをとってみました。
ベンチマークのスクリプトはid:tokuhiromのスクリプトを拝借しました

use strict;
use warnings;
use Cache::Memcached::GetParserXS;
use Cache::Memcached;
use Cache::Memcached::Fast;
use Benchmark qw/cmpthese/;

my $n = 5000;
my $max = 500;
my @keys = map { "x" . $_ } 0..$max;
my $m = Cache::Memcached->new( +{ servers => ['127.0.0.1:11211'] } );
$m->enable_compress(0);
my $fast = Cache::Memcached::Fast->new( +{ servers => ['127.0.0.1:11211'] } );
$m->set( $_ => rand ) for @keys;

foreach my $num ( qw/1 5 10 100 500/ ) {
    print "### $num\n";
    my @keys = map { "x" . $_ } 0..$num;
    cmpthese(
        $n => +{
            parser_xs => sub {
                $m->get_multi(@keys);
            },
            fast => sub {
                $fast->get_multi(@keys);
            },
        }
    );
}


結果

$ perl memcached_bench.pl
### 1
            Rate parser_xs      fast
parser_xs 1241/s        --      -80%
fast      6173/s      398%        --
### 5
            Rate parser_xs      fast
parser_xs 1176/s        --      -78%
fast      5263/s      347%        --
### 10
            Rate parser_xs      fast
parser_xs 1567/s        --      -63%
fast      4202/s      168%        --
### 100
            Rate parser_xs      fast
parser_xs  557/s        --      -56%
fast      1256/s      125%        --
### 500
           Rate parser_xs      fast
parser_xs 178/s        --      -41%
fast      299/s       68%        --


テストに用いたマシンは、
OS: CentOS 4 ( kernel 2.6.9 )
CPU: Celeron 2.8GHz
Memory: 1GB
です


C::M::Fastのディストリビューションに含まれるcompare.plを動かしてみるとget_multi以外のベンチマークもとれます
以下はその結果

  ./script/compare.pl localhost:11211 100000
Benchmark: timing 100000 iterations of New add(40 bytes), Old add(40 bytes)...
New add(40 bytes): 27.5119 wallclock secs (12.44 usr +  6.34 sys = 18.78 CPU) @ 5324.81/s (n=100000)
Old add(40 bytes): 43.3037 wallclock secs (23.78 usr +  9.32 sys = 33.10 CPU) @ 3021.15/s (n=100000)
                    Rate Old add(40 bytes) New add(40 bytes)
Old add(40 bytes) 3021/s                --              -43%
New add(40 bytes) 5325/s               76%                --
Benchmark: timing 100000 iterations of New set(40 bytes), Old set(40 bytes)...
New set(40 bytes): 27.9549 wallclock secs (12.63 usr +  6.60 sys = 19.23 CPU) @ 5200.21/s (n=100000)
Old set(40 bytes): 43.8092 wallclock secs (23.68 usr +  9.47 sys = 33.15 CPU) @ 3016.59/s (n=100000)
                    Rate Old set(40 bytes) New set(40 bytes)
Old set(40 bytes) 3017/s                --              -42%
New set(40 bytes) 5200/s               72%                --
Benchmark: timing 100000 iterations of New replace(40 bytes), Old replace(40 bytes)...
New replace(40 bytes): 28.2981 wallclock secs (12.81 usr +  6.64 sys = 19.45 CPU) @ 5141.39/s (n=100000)
Old replace(40 bytes): 44.8797 wallclock secs (24.10 usr +  9.42 sys = 33.52 CPU) @ 2983.29/s (n=100000)
                        Rate Old replace(40 bytes) New replace(40 bytes)
Old replace(40 bytes) 2983/s                    --                  -42%
New replace(40 bytes) 5141/s                   72%                    --
Benchmark: timing 100000 iterations of New get, Old get...
   New get: 22.8232 wallclock secs ( 9.93 usr +  6.15 sys = 16.08 CPU) @ 6218.91/s (n=100000)
   Old get: 89.768 wallclock secs (63.76 usr + 17.16 sys = 80.92 CPU) @ 1235.79/s (n=100000)
          Rate Old get New get
Old get 1236/s      --    -80%
New get 6219/s    403%      --
Benchmark: timing 1000 iterations of New get_multi(100 keys), Old get_multi(100 keys)...
New get_multi(100 keys): 1.65893 wallclock secs ( 1.02 usr +  0.19 sys =  1.21 CPU) @ 826.45/s (n=1000)
Old get_multi(100 keys): 2.60043 wallclock secs ( 1.92 usr +  0.29 sys =  2.21 CPU) @ 452.49/s (n=1000)
                         Rate Old get_multi(100 keys) New get_multi(100 keys)
Old get_multi(100 keys) 452/s                      --                    -45%
New get_multi(100 keys) 826/s                     83%                      --
Benchmark: timing 1000 iterations of New get x 100, New get_multi(100), Old get x 100, Old get_multi(100)...
New get x 100: 17.2965 wallclock secs ( 6.62 usr +  4.87 sys = 11.49 CPU) @ 87.03/s (n=1000)
New get_multi(100): 1.24405 wallclock secs ( 0.69 usr +  0.17 sys =  0.86 CPU) @ 1162.79/s (n=1000)
Old get x 100: 88.6322 wallclock secs (61.79 usr + 16.76 sys = 78.55 CPU) @ 12.73/s (n=1000)
Old get_multi(100): 2.33868 wallclock secs ( 1.72 usr +  0.24 sys =  1.96 CPU) @ 510.20/s (n=1000)
                     Rate Old get x 100 New get x 100 Old get_multi(100) New get_multi(100)
Old get x 100      12.7/s            --          -85%               -98%               -99%
New get x 100      87.0/s          584%            --               -83%               -93%
Old get_multi(100)  510/s         3908%          486%                 --               -56%
New get_multi(100) 1163/s         9034%         1236%               128%                 --
Benchmark: timing 100000 iterations of New delete, Old delete...
New delete: 27.032 wallclock secs (13.17 usr +  6.53 sys = 19.70 CPU) @ 5076.14/s (n=100000)
Old delete: 37.7127 wallclock secs (20.63 usr +  9.39 sys = 30.02 CPU) @ 3331.11/s (n=100000)
             Rate Old delete New delete
Old delete 3331/s         --       -34%
New delete 5076/s        52%         --


Tomash++
あと、Brian Akerのlibmemcachedを利用したTim Bunceのperl-libmemcachedに期待しています