Cache::FileCacheのHowto

Cacheの実装として、ローカルのファイルシステムを使うもの。使ってみての所感をまとめたい。

導入により享受できる恩恵
  • 当然ながら、DBへの負荷を減らせる
  • ファイルなので複数プロセスで共有可能
  • ローカルにあるのでネットワークトラフィック発生しない
注意すべき点

ファイルI/Oを意識する必要がある
key-value的な発想で使うとSQLより遅くなることもありえる。

たとえば新着日記を100件キャッシュしておこうと思ったときに、
日記IDをkeyにしてしまうのはNGである。このケースだと100回のFile I/Oが発生するためである。

最も効率的にやるには新着日記100件をハッシュリファレンスに入れて、丸っとキャッシュするのがよい。
これであれば、読み出しが1回で済む。

ベンチマーク(set)
use Cache::FileCache;
use Benchmark;

my $fcache1 = new Cache::FileCache({ namespace => 'test1'});
my $fcache2 = new Cache::FileCache({ namespace => 'test2'});

sub set1 {
    $fcache1->set($_, $_) for (1..100);
}

sub set2 {
    my $ref_hash;
    $ref_hash->{$_} = $_ for (1..100);
    $fcache2->set('all', $ref_hash);
}

timethese(100, {
    'set1' => 'set1()',
    'set2' => 'set2()',
});


Benchmark: timing 100 iterations of set1, set2...
      set1: 12 wallclock secs ( 5.84 usr +  5.98 sys = 11.82 CPU) @  8.46/s (n=100)
      set2:  0 wallclock secs ( 0.07 usr +  0.07 sys =  0.14 CPU) @ 714.29/s (n=100)
ベンチマーク(get)
use Cache::FileCache;
use Benchmark;


sub get1 {
    for (1..100) {
        $fcache1->get($_);
    }
}

sub get2 { 
    my $ref_hash = $fcache2->get('all');
    for my $key (keys %$ref_hash) {
        $ref_hash->{$key};
    }
}
timethese(100, {
    'get1' => 'get1()',
    'get2' => 'get2()',
});


Benchmark: timing 100 iterations of get1, get2...
      get1:  8 wallclock secs ( 2.75 usr +  5.48 sys =  8.23 CPU) @ 12.15/s (n=100)
      get2:  0 wallclock secs ( 0.04 usr +  0.08 sys =  0.12 CPU) @ 833.33/s (n=100)
まとめ
  • Cache::FileCache使うなら、欲しい結果を丸っとキャッシュするのがGood.
  • 決してKey-Value Storageのイメージで使わないこと