Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

TinyCDB vs QDBM vs MemcachedのPerformance比較

NoSQLデータベースファーストガイド

NoSQLデータベースファーストガイド

Index

  • Standalone KVSのPerformance比較
  • Performanceの結果
  • MachineSpec
  • TinyCDB
    • Feature
    • Setup
    • Write Performance
    • Read Perfomance
  • QDBM
    • Feature
    • Setup
    • Write Performance
    • Read Perfomance
  • Memcached
    • Feature
    • Setup
    • Write Performance
    • Read Perfomance

Standalone KVSの性能比較

TinyCDB - a Constant DataBase はてなブックマーク - TinyCDB - a Constant DataBase
データベースライブラリ QDBM はてなブックマーク - データベースライブラリ QDBM
memcached - a distributed memory object caching system はてなブックマーク - memcached - a distributed memory object caching system
業種別企業の平均年齢と年収の辞書データを公開しました - Yuta.Kikuchiの日記 はてなブックマーク - 業種別企業の平均年齢と年収の辞書データを公開しました - Yuta.Kikuchiの日記


こんにちは、名ばかりのDataScientist@yutakikucです。今日はクライアントサイドでcache機構や簡易HashDBを持ちたいときにどういったKVSを使えば良いかを考える材料の記事を書きたいと思っています。紹介する技術は昔から世に浸透しているものばかりなので、記事としては今更感があります(笑)。比較対象はTinyCDB、QDBM、Memcachedです。※Memcachedだけは分散型として利用できますが、ここではStandaloneとして使います。それぞれDataの構築方法が異なるので、Performance性能だけでなく用途による判断も必要になります。( 例えばTinyCDBとQDBMは辞書データとしての活用でMemcachedはパフォーマンス改善のCache機構とする等。) DataのRead/Writeは全てPerlで記述しており、呼び出しはコマンドラインで行います。またPerformanceの比較には以前公開した業種別平均年齢と年収のデータを利用します。

Performanceの結果

結果を先に書いておきます。実験の詳細を確認したい人だけ後の内容をご確認下さい。

Write Performance

100回のDataWriteの実行速度をtimeコマンドで3回取得し、totalを平均しました。書き込みに関してはTinyCDBの圧勝でした。

Type 100 Write
TinyCDB 0.945sec
QDBM 3.233sec
Memcached 37.4460sec
Read Performance

ReadのPerformanceを測定するために3種類の実験を行いました。1.Dataの全てを100回取得、2.一つのkeyを100回取得、3.一つのkeyを10000回取得です。Readに関してはQDBMが圧勝でした。

Type 100 AllKey Read 100 1key Read 10000 1key Read
TinyCDB 24.4400sec 0.0556sec 1.5953sec
QDBM 2.8396sec 0.0540sec 0.8083sec
Memcached 11.3850sec 0.0976sec 1.4546sec

MachineSpec

OS
$ cat /etc/redhat-release

CentOS release 6.3 (Final)
CPU
$ cat /proc/cpuinfo

processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 23
model name	: Intel(R) Core(TM)2 Duo CPU     E7600  @ 3.06GHz
stepping	: 10
cpu MHz		: 3062.000
cache size	: 6144 KB
fpu		: yes
fpu_exception	: yes
cpuid level	: 5
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx lm constant_tsc up rep_good pni monitor ssse3 lahf_lm
bogomips	: 6124.00
clflush size	: 64
cache_alignment	: 64
address sizes	: 36 bits physical, 48 bits virtual
power management:
Memory
$ cat /proc/meminfo

MemTotal:         979736 kB
MemFree:           72540 kB
Buffers:           97492 kB
Cached:           102664 kB
SwapCached:          180 kB
Active:           369708 kB
Inactive:         381532 kB
Active(anon):     274872 kB
Inactive(anon):   277520 kB
Active(file):      94836 kB
Inactive(file):   104012 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1966072 kB
SwapFree:        1963348 kB
Dirty:               140 kB
Writeback:             0 kB
AnonPages:        550920 kB
Mapped:            35672 kB
Shmem:              1308 kB
Slab:             117112 kB
SReclaimable:      61656 kB
SUnreclaim:        55456 kB
KernelStack:        3072 kB
PageTables:        15088 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2455940 kB
Committed_AS:     927992 kB
VmallocTotal:   34359738367 kB
VmallocUsed:        7892 kB
VmallocChunk:   34359715388 kB
HardwareCorrupted:     0 kB
AnonHugePages:    438272 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        8128 kB
DirectMap2M:      999424 kB

TinyCDB

Feature

cdb - Wikipedia はてなブックマーク - cdb - Wikipedia
TinyCDBはConstantDatabaseの一種で4GByteまでのハッシュDBを構築することができます。ConstantなんでDataのinsertやdeleteといった細かい操作ができないので、全Dataを再構築する必要があります。FileにDataを書き込むのでServerがrestartされてもDataは消えません。

Setup
$ wget "http://www.corpit.ru/mjt/tinycdb/tinycdb-0.78.tar.gz"
$ tar -xzf tinycdb-0.78.tar.gz
$ cd tinycdb-0.78
$ make clean piclib
$ sudo make install-piclib
$ make clean
$ sudo make install
$ wget "http://search.cpan.org/CPAN/authors/id/A/AJ/AJGB/CDB-TinyCDB-0.05.tar.gz"
$ tar -xzf CDB-TinyCDB-0.05.tar.gz
$ cd CDB-TinyCDB-0.05
$ perl Makefile.PL
$ make
$ make test
$ sudo make install

以下のperl記述でuseの箇所にエラーが出なければ設定完了です。

#!/usr/bin/env perl
use CDB::TinyCDB;
Write Performance

Data/corps_age_income.txt at master · yutakikuchi/Data · GitHub はてなブックマーク - Data/corps_age_income.txt at master · yutakikuchi/Data · GitHub
上のテキストファイルの企業名Keyに年収データValueとして100回TinyCDBに格納します。

#!/usr/bin/env perl
#文字コードはutf-8を使用

use warnings;
use strict;
use CDB::TinyCDB;

my $cdb = CDB::TinyCDB->create( 'my-new.cdb', 'my-new.cdb.$$' );
my $filename = 'corps_age_income.txt';
for( my $i=0; $i<100; $i++ ) {
   open( FH,$filename );
   my @data = <FH>;
   foreach my $line( @data ) {
      chomp $line;
      my @tokens = split( /\t/, $line );
      unless ( defined( $tokens[2] ) && defined( $tokens[4] ) ) { 
         next;
      }
      $cdb->put_add( $tokens[2], $tokens[4] );
   }
   close( FH );
}
$cdb->finish();
$ time perl tinycdb_write.pl  
perl tinycdb_write.pl 0.52s user 0.10s system 67% cpu 0.909 total
$ time perl tinycdb_write.pl
perl tinycdb_write.pl  0.51s user 0.16s system 70% cpu 0.940 total
$ time perl tinycdb_write.pl
perl tinycdb_write.pl  0.65s user 0.10s system 76% cpu 0.986 total
Read Performance

上で作成したmy-new.cdbファイルを100回Readします。まずは全データの読み取りを行います。

#!/usr/bin/env perl
#文字コードはutf-8を使用

use warnings;
use strict;
use CDB::TinyCDB;

for( my $i=0; $i<100; $i++ ) {
   my $cdb = CDB::TinyCDB->load( 'my-new.cdb' );
   while( my( $key, $value ) = $cdb->each ) {
   }
}
$ time perl tinycdb_read.pl
perl tinycdb_read.pl  17.86s user 0.71s system 77% cpu 23.979 total
$ time perl tinycdb_read.pl
perl tinycdb_read.pl  18.02s user 0.74s system 77% cpu 24.310 total
$ time perl tinycdb_read.pl
perl tinycdb_read.pl  18.63s user 0.77s system 77% cpu 25.031 total

次に特定のkeyのみ取得します。key=ヤフー(株)に設定します。

#!/usr/bin/env perl
#文字コードはutf-8を使用

use warnings;
use strict;
use CDB::TinyCDB;

for( my $i=0; $i<100; $i++ ) {
   my $cdb = CDB::TinyCDB->load( 'my-new.cdb' );
   $cdb->get('ヤフー(株)');
}
$ time perl tinycdb_read.pl
perl tinycdb_read.pl  0.03s user 0.03s system 79% cpu 0.067 total
$ time perl tinycdb_read.pl
perl tinycdb_read.pl  0.01s user 0.02s system 66% cpu 0.051 total
$ time perl tinycdb_read.pl
perl tinycdb_read.pl  0.03s user 0.01s system 84% cpu 0.049 total

取得回数を100→10000に変更して実行してみます。

$ time perl tinycdb_read.pl
perl tinycdb_read.pl  0.64s user 0.47s system 71% cpu 1.554 total
$ time perl tinycdb_read.pl
perl tinycdb_read.pl  0.70s user 0.68s system 77% cpu 1.773 total
$ time perl tinycdb_read.pl
perl tinycdb_read.pl  0.59s user 0.51s system 75% cpu 1.459 total

QDBM

Feature

QDBM - Wikipedia はてなブックマーク - QDBM - Wikipedia
Specification of QDBM Version 1 (Japanese) はてなブックマーク - Specification of QDBM Version 1 (Japanese)
GDBMなどのDBM系の一種。Hash/B+Treeモードを設定することができます。理論的にはレコードの合計サイズが1TBまでのデータベースを構築することが出来ます。Dataの追加や消去は可能です。TinyCDBと同様にFileにDataを書き込むのでServerがrestartされてもDataは消えません。

Setup
$ wget "http://fallabs.com/qdbm/qdbm-1.8.78.tar.gz"
$ tar -xzf qdbm-1.8.78.tar.gz
$ cd qdbm-1.8.78
$ ./configure
$ make && make check
$ sudo make install

$ cd perl
$ ./configure
$ make && make check
$ sudo make install

以下のperlファイルでuseの箇所にエラーがでなければ設定完了です。

#!/usr/bin/env perl
use Depot;
Write Performance

TinyCDBと同様に企業名Keyに年収データValueとして100回QDBMに格納します。

#!/usr/bin/env perl

use warnings;
use strict;
use Depot;

tie my %qdbm, 'Depot', 'my-new.qdbm', Depot::OWRITER | Depot::OCREAT;
my $filename = 'corps_age_income.txt';
for( my $i=0; $i<100; $i++ ) {
   open( FH,$filename );
   my @data = <FH>;
   foreach my $line( @data ) {
      chomp $line;
      my @tokens = split( /\t/, $line );
      unless ( defined( $tokens[2] ) && defined( $tokens[4] ) ) { 
         next;
      }
      $qdbm{$tokens[2]} =  $tokens[4];
   }
   close( FH );
}
untie %qdbm;
$ time perl qdbm_write.pl  
perl qdbm_write.pl 1.64s user 0.86s system 77% cpu 3.234 total
$ time perl qdbm_write.pl  
perl qdbm_write.pl 1.64s user 0.77s system 73% cpu 3.273 total
$ time perl qdbm_write.pl 
perl qdbm_write.pl 1.63s user 0.69s system 72% cpu 3.194 total
Read Performance

上で作成したmy-new.qdbmファイルを100回Readします。まずは全データの読み取りを行います。

#!/usr/bin/env perl
#文字コードはutf-8を使用

use warnings;
use strict;
use Depot;

for( my $i=0; $i<100; $i++ ) {
   tie my %qdbm, 'Depot', 'my-new.qdbm', Depot::OREADER or die;
   foreach my $key( keys %qdbm ) {
      my $value = $qdbm{$key};
   }
}
$ time perl qdbm_read.pl
perl qdbm_read.pl  1.98s user 0.39s system 81% cpu 2.927 total
$ time perl qdbm_read.pl
perl qdbm_read.pl  1.89s user 0.36s system 78% cpu 2.849 total
$ time perl qdbm_read.pl
perl qdbm_read.pl  1.84s user 0.38s system 80% cpu 2.743 total

次に特定のkeyのみ取得します。key=ヤフー(株)に設定します。

#!/usr/bin/env perl
#文字コードはutf-8を使用

use warnings;
use strict;
use Depot;

for( my $i=0; $i<100; $i++ ) {
   tie my %qdbm, 'Depot', 'my-new.qdbm', Depot::OREADER or die;
   my $value = $qdbm{'ヤフー(株)'};
}
$ time perl qdbm_read.pl
perl qdbm_read.pl  0.02s user 0.02s system 69% cpu 0.058 total
$ time perl qdbm_read.pl
perl qdbm_read.pl  0.02s user 0.02s system 78% cpu 0.051 total
$ time perl qdbm_read.pl
perl qdbm_read.pl  0.02s user 0.02s system 73% cpu 0.053 total

取得回数を100→10000に変更して実行してみます。

$ time perl qdbm_read.pl
perl qdbm_read.pl  0.51s user 0.16s system 81% cpu 0.811 total
$ time perl qdbm_read.pl
perl qdbm_read.pl  0.54s user 0.19s system 89% cpu 0.814 total
$ time perl qdbm_read.pl
perl qdbm_read.pl  0.51s user 0.14s system 81% cpu 0.800 total

Memcached

Feature

第1回 memcachedの基本:memcachedを知り尽くす|gihyo.jp … 技術評論社 はてなブックマーク - 第1回 memcachedの基本:memcachedを知り尽くす|gihyo.jp … 技術評論社
memcachedは分散機能を持ったキャッシュ機構。メモリにデータを乗せるので高速に処理されますが書き込み可能なDataSizeはMemorySizeに依存します。Dataの書き換えは簡単にできますが、memcachedの再起動がされるとDataは消去されます。

Setup
$ sudo yum install libevent libevent-devel -y
$ ./configure
$ make && sudo make install
$ /usr/local/bin/memcached -vvv
slab class   1: chunk size        96 perslab   10922
slab class   2: chunk size       120 perslab    8738
slab class   3: chunk size       152 perslab    6898
slab class   4: chunk size       192 perslab    5461
$ sudo cpan Cache::Memcached::Fast

以下のperl記述でuseの箇所にエラーが出なければ設定完了です。

#!/usr/bin/env perl
use Cache::Memcached::Fast;
Write Performance

他と同様に企業名Keyに年収データValueとして100回Memcachedに格納します。

#!/usr/bin/env perl
#文字コードはutf-8を使用

use strict;
use warnings;
use Cache::Memcached::Fast;

my $memd = Cache::Memcached::Fast->new({ servers => [ { address => 'localhost:11211' }],});
my $filename = 'corps_age_income.txt';
for( my $i=0; $i<100; $i++ ) {
   open( FH,$filename );
   my @data = <FH>;
   foreach my $line( @data ) {
      chomp $line;
      my @tokens = split( /\t/, $line );
      unless ( defined( $tokens[2] ) && defined( $tokens[4] ) ) { 
         next;
      }
      $memd->set( $tokens[2], $tokens[4] );
   }
   close( FH );
}
$ time perl memcached_write.pl 
perl memcached_write.pl  0.86s user 10.27s system 28% cpu 38.950 total
$ time perl memcached_write.pl
perl memcached_write.pl  0.87s user 9.97s system 29% cpu 37.269 total
$ time perl memcached_write.pl
perl memcached_write.pl  0.79s user 9.85s system 29% cpu 36.119 total
Read Performance

上で格納したMemcachedデータを100回Readします。Memcachedは存在するkeyを知る手段が無いので、元のファイルから取得します。まずは全データの読み取りを行います。

#!/usr/bin/env perl
#文字コードはutf-8を使用

use strict;
use warnings;
use Cache::Memcached::Fast;
use Data::Dumper;

my $memd = Cache::Memcached::Fast->new({ servers => [ { address => 'localhost:11211' }],});
my $filename = 'corps_age_income.txt';
open( FH,$filename );
my @data = <FH>;
my @keys = ();
foreach my $line( @data ) {
   chomp $line;
   my @tokens = split( /\t/, $line );
   unless ( defined( $tokens[2] ) && defined( $tokens[4] ) ) { 
      next;
   }
   push( @keys, $tokens[2] );
} 

for( my $i=0; $i<100; $i++ ) {
   my $ref = $memd->get_multi( @keys );
   foreach my $key ( @keys ) {
      my $result = $ref->{$key};
   }
}
$ time perl memcached_read.pl
perl memcached_read.pl  0.26s user 0.21s system 4% cpu 10.728 total
$ time perl memcached_read.pl 
perl memcached_read.pl  0.27s user 0.20s system 3% cpu 12.500 total
$ time perl memcached_read.pl
perl memcached_read.pl  0.25s user 0.20s system 4% cpu 10.927 total

次に特定のkeyのみ取得します。key=ヤフー(株)に設定します。

#!/usr/bin/env perl
#文字コードはutf-8を使用

use strict;
use warnings;
use Cache::Memcached::Fast;
use Data::Dumper;

my $memd = Cache::Memcached::Fast->new({ servers => [ { address => 'localhost:11211' }],});
for( my $i=0; $i<100; $i++ ) {
   my $ref = $memd->get('ヤフー(株)');
}
$ time perl memcached_read.pl
perl memcached_read.pl  0.04s user 0.03s system 67% cpu 0.098 total
$ time perl memcached_read.pl
perl memcached_read.pl  0.04s user 0.02s system 63% cpu 0.100 total
$ time perl memcached_read.pl
perl memcached_read.pl  0.03s user 0.03s system 65% cpu 0.095 total

取得回数を100→10000に変更して実行してみます。

$ time perl memcached_read.pl
perl memcached_read.pl  0.03s user 0.41s system 30% cpu 1.450 total
$ time perl memcached_read.pl
perl memcached_read.pl  0.04s user 0.41s system 31% cpu 1.439 total
$ time perl memcached_read.pl
perl memcached_read.pl  0.02s user 0.44s system 31% cpu 1.475 total