プロセス間で巨大なサイズの変数を共有したい

tokyocabinet, kyotocabinet, memcached, redis これらは普通のハッシュに比べると数十倍〜数百倍遅かった。
こうなったらKVSを諦め、変数をどうやって他のプロセスと共有するかを考えた方がいいのかもしれない。
その方法はないのか?

http://nihen.hatenablog.com/entry/2013/10/22/125410

      • -

共有メモリで調べていたらここに行き着いた
http://search.cpan.org/~andya/IPC-ShareLite-0.17/lib/IPC/ShareLite.pm


ちょっとテストしたが、すばらしい結果を得た。
10万件の読み書きなら、0.1秒くらいでおわる。

tokyocabinet, kyotocabinet, memcached, redisといったKVSとは雲泥の差。

use IPC::ShareLite;
use Data::Dumper;
use Storable qw( freeze thaw );
use strict;
use warnings;
use IO::Prompt::Simple;
use Time::HiRes;

my $share = IPC::ShareLite->new(
-key => 1971,
-create => 'yes',
-destroy => 'no'
) or die $!;


my $start_time = Time::HiRes::time;

## write
if(0){
my $r;
#$r->{"idx1"} = 1;
for(my $i=0; $i<100000; $i++){
$r->{"idx$i"} = "$i";
}
$share->store(freeze($r));
}

## read
if(1){
my $r2 = thaw($share->fetch());
#print Dumper $r2;
print Dumper $r2->{"idx1"};

for(my $i=0; $i<100000; $i++){
my $aa = $r2->{"idx$i"};
}
#print "-- info --\n";
#print "size:",$share->size,"\n";
#print "num_segments:",$share->num_segments,"\n";
#my $usage = $share->size * $share->num_segments;
#print "usage:$usage\n";
#
#print Dumper $share;
}

my $end_time = Time::HiRes::time;
print "total time:",($end_time-$start_time),"\n";
print "end of perl\n";

                  • -

追記

上の方法だと1GBいかないうちに容量いっぱいになりましたエラーがでて大きなデータを保持できなかった。

さらに共有メモリでググっていると、いい感じの情報が

http://ja.wikipedia.org/wiki/%E5%85%B1%E6%9C%89%E3%83%A1%E3%83%A2%E3%83%AA

Linuxカーネル 2.6 では、RAMディスク形式の共有メモリとして /dev/shm が導入された。より正確に言えば、誰でも書き込めるメモリ内のディレクトリであり、その容量の上限は /etc/default/tmpfs で指定できる。/dev/shm 機能サポートはカーネルの設定ファイルで指定でき、デフォルトでは無効となっている。なお、RedHatDebian ベースのディストリビューションではデフォルトで有効になっている。

試しに df したら、

tmpfs 16G 4.0K 16G 1% /dev/shm

ってのがすでに用意されている

今からこれを試す

試した

use Data::Dumper;
use strict;
use warnings;
use Time::HiRes;
use Storable qw(nstore retrieve);

my $h;

my $start_time = Time::HiRes::time;

## write
if(0){
for(my $i=0; $i<1000000; $i++){
$h->{"idx$i"} = "$i";
}
#nstore $h, './normal_file.dat';
nstore $h, '/dev/shm/shm_file.dat';
}

## read
if(1){
#$h = retrieve ('./normal_file.dat');
$h = retrieve ('/dev/shm/shm_file.dat');
for(my $i=0; $i<1000000; $i++){
my $aa = $h->{"idx$i"};
}
}

my $end_time = Time::HiRes::time;
print "total time:",($end_time-$start_time),"\n";
print "end of perl\n";

が、fileと/dev/shmとでほぼ同じ時間だった。というか、fileでも十分はやかった。

/dev/shmで速度が変わらないってのが気になるが、とりあえず今回の件は解決。
結論は、Storable で普通にファイルに書き出し/読み込みすればKVSとかより断然早く変数の他プロセス間共有ができる。

                    • -

追記

時間測定したら、/dev/shmで読み書きするのと普通の領域でするのと全然変わりがなかった。

それと、最初の目的から外れている。
メモリの内容を他のプロセスから読むことがしたいこと。