YAMLやYAML::Syckでutf8でdecodeしながら読む

メモ。

YAML::Syckの場合
 use YAML::Syck();

 my $file = 'data.yaml';
 local $YAML::Syck::ImplicitUnicode = 1;
 my $data = YAML::Syck::LoadFile($file);

$YAML::Syck::ImplicitUnicodeを使うことでデコードしながら読むことができる。

YAMLの場合
 my $data = YAML::LoadFile($file);
 my $yaml = YAML::Dump($data);
 utf8::decode($yaml);
 $data = YAML::Load($yaml);
YAML parser - Bulknews::Subtech - subtech

miyagawaさんとこの記事でこう書かれてたんだけど、コレって普通にファイル読み込んだ方が早いんじゃないの?と思ってちょっと実験。

 use YAML();
 use Path::Class();

 my $file = 'data.yaml';
 my $yaml = Path::Class::File->new($file)->slurp;
 utf8::decode($yaml);
 my $data = YAML::Load($yaml);

で、ベンチマークとってみる。YAML::Syckもついでに比較してみる。

use YAML();
use YAML::Syck();
use Path::Class();

sub open_load {
    my $file = 'data.yaml';
    my $yaml = Path::Class::File->new($file)->slurp;
    utf8::decode($yaml);
    my $data = YAML::Load($yaml);
}

sub dump_load {
    my $file = 'data.yaml';
    my $data = YAML::LoadFile($file);
    my $yaml = YAML::Dump($data);
    utf8::decode($yaml);
    $data = YAML::Load($yaml);
}

sub syck_load {
    my $file = 'data.yaml';
    local $YAML::Syck::ImplicitUnicode = 1;
    my $data = YAML::Syck::LoadFile($file);
}

# 初回動作はノイズになるので一度実行しておく
open_load;
dump_load;
syck_load;

use Benchmark qw(cmpthese timethese :hireswallclock);
cmpthese(100,{
    open_load => \&open_load,
    dump_load => \&dump_load,
    syck_load => \&syck_load,
});

__END__

            Rate dump_load open_load syck_load
dump_load 13.7/s        --      -60%      -98%
open_load 34.6/s      152%        --      -96%
syck_load  794/s     5691%     2194%        --

検証に使ったdata.yamlCatalystの設定ファイルくらいの構造。

やっぱLoadFile & Dumpコンボより普通にオープンする方が早いね。# 何か別の問題があるかもしれないけど・・・

ってか改めて思ったけどYAML::Syckは劇的に早い。そりゃもう早い。マジはやい。よく呼ばれるような部分ではYAML::Syckだね、これ真理。