2011年1月18日火曜日

データの直列化(Data::Dumper vs JSON::XS vs Storable)

Perlのデータ構造を直列化(Serialize)したくて、いくつかのモジュールを試してみたので、その結果をこのエントリに記録しておきます。

そもそも今回やりたかったことは、
  1. Perlのハッシュを直列化する
  2. ただし、ハッシュの値はスカラーまたは配列のどちらか
  3. ある事情により、ハッシュキーでソートしてから直列化したい 
だったのですが、データ構造が複雑ではなかったので、最初は自分で直列化していました。でも、ソースがいまいちスッキリしなくて気持ち悪かったので、CPANモジュールに置き換えることにしたんです。

とは言っても、どのモジュールを使えばベストなのかで迷ったので、ベンチマークを取って、一番速いモジュールを採用することにしました。

use strict;
use warnings;
use Data::Dumper;
use JSON::XS;
use Storable 'nfreeze';
$Storable::canonical = 1;
use Benchmark qw(timethese  cmpthese);

my $hash = {
    'z' => 'z',
    'a' => 'a',
    'c' => [ '2','1'],
};

sub my_serialize {
    my $params = $hash;
    my $str = "{";
    foreach my $name ( sort(keys %{$params}) ) {
        if ( ref($params->{$name}) eq 'ARRAY' ) {
            $str .= "'$name'=>[";
            foreach my $value ( @{$params->{$name}} ) {
                $str .= "'$value',";
            }  
            $str .= '],';
        } else {
            $str .= "'$name'=>'$params->{$name}',";
        }  
    }  
    return $str . "}";
}

sub data_dumper {
    my $d = Data::Dumper->new([$hash]);
    return $d->Terse(1)->Indent(0)->Sortkeys(1)->Dump;
}

sub json_xs {
        return JSON::XS->new->canonical->encode($hash);
}

sub storable {
    return nfreeze($hash);
}

my $count = 1000000;
my $comp = timethese(
    $count,
    {
        my_serialize => \&my_serialize,
        data_dumper => \&data_dumper,
        jspn_xs => \&json_xs,
        storable => \&storable,
    }
);

cmpthese $comp;

上記のようなベンチマーク用のコードを用意して、実行してみると、、、


Benchmark: timing 1000000 iterations of data_dumper, jspn_xs, my_serialize, storable...
data_dumper: 43 wallclock secs (41.97 usr +  0.08 sys = 42.05 CPU) @ 23781.21/s (n=1000000)
   jspn_xs:  3 wallclock secs ( 2.04 usr +  0.00 sys =  2.04 CPU) @ 490196.08/s (n=1000000)
my_serialize:  6 wallclock secs ( 5.69 usr +  0.00 sys =  5.69 CPU) @ 175746.92/s (n=1000000)
  storable: 42 wallclock secs (29.85 usr + 12.66 sys = 42.51 CPU) @ 23523.88/s (n=1000000)
                 Rate     storable  data_dumper my_serialize      jspn_xs
storable      23524/s           --          -1%         -87%         -95%
data_dumper   23781/s           1%           --         -86%         -95%
my_serialize 175747/s         647%         639%           --         -64%
jspn_xs      490196/s        1984%        1961%         179%           --

上記のような結果になりました。つまり、今回の条件下では、JSON::XSがData::DumperやStorableの20倍高速に動作することがわかりました。

という訳で、JSON::XSを使うことに決定。

0 件のコメント:

コメントを投稿