get/setの帯域消費量

既存memcachedに対して新たにデータを投入する際に、「ネットワークの帯域圧迫しないか?」という心配があったので調べてみた。
以下、Cache::Memcached::Fastを使ってる前提で。

SYNOPSIS

  use Cache::Memcached::Fast;

  my $memd = new Cache::Memcached::Fast({
      servers => [ { address => 'localhost:11211', weight => 2.5 },
                   '192.168.254.2:11211',
                   { address => '/path/to/unix.sock', noreply => 1 } ],
      namespace => 'my:',
      connect_timeout => 0.2,
      io_timeout => 0.5,
      close_on_error => 1,
      compress_threshold => 100_000,
      compress_ratio => 0.9,
      compress_methods => [ \&IO::Compress::Gzip::gzip,
                            \&IO::Uncompress::Gunzip::gunzip ],
      max_failures => 3,
      failure_timeout => 2,
      ketama_points => 150,
      nowait => 1,
      hash_namespace => 1,
      serialize_methods => [ \&Storable::freeze, \&Storable::thaw ],
      utf8 => ($^V ge v5.8.1 ? 1 : 0),
      max_size => 512 * 1024,
  });

compress_methods、serialize_methodsとあるので、これらを使えば計算できそうです(最初はserialize_methodsだけで計算していて、指摘されて気づいたことは内緒)。

compress_methods

  compress_methods => [ \&IO::Compress::Gzip::gzip,
                        \&IO::Uncompress::Gunzip::gunzip ]
  (default: [ sub { ${$_[1]} = Compress::Zlib::memGzip(${$_[0]}) },
              sub { ${$_[1]} = Compress::Zlib::memGunzip(${$_[0]}) } ]
   when Compress::Zlib is available)

デフォルトはCompress::Zlib::memGzipで圧縮しているので、インスタンス作成時に何も指定してなければこれを使って計測すればok。

serialize_methods

  serialize_methods => [ \&Storable::freeze, \&Storable::thaw ],
  (default: [ \&Storable::nfreeze, \&Storable::thaw ])

これもcompress_methodsとおんなじなので割愛。

実際に測ってみる

kotaroito@mac:~> perl -MCompress::Zlib -MStorable=nfreeze -le '$hash={ map { $_ => 1 }(1..10000) }; warn length(Compress::Zlib::memGzip(\ nfreeze $hash)); 
;'
25867 at -e line 1.

注)実際にはcompress_thresholdを超えるbyte数で、かつ圧縮後:圧縮前の比率がcompress_ratioより小さくならないと圧縮されないので、C::M::Fastのnewに与える引数も調べておく必要があります。(Thanks to xaicron)

まとめ

ちゃんとperldocを読めば書いてある。見積りが正しくできる=理解できている、なので何事も見積もってみるのは大事だと思います。