そもそも今回やりたかったことは、
- Perlのハッシュを直列化する
- ただし、ハッシュの値はスカラーまたは配列のどちらか
- ある事情により、ハッシュキーでソートしてから直列化したい
とは言っても、どのモジュールを使えばベストなのかで迷ったので、ベンチマークを取って、一番速いモジュールを採用することにしました。
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 件のコメント:
コメントを投稿