その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

PerlのYAMLライブラリ性能比較

なんと2018年の記事です.皆様無事明けられておりますでしょうか.

さてYAML::XSには2017年に色々と変更が入り,実用するにあたり非常に便利な機能が色々と導入されました (具体的に言うと,$YAML::XS::LoadBlessed$YAML::XS::Booleanです).また安定化が図られました *1
というわけで個人的に,最近PerlYAMLをserialize/deserializeするにあたってはYAML::XSを使うことが多くなってきたわけですが,そこでふと各YAMLライブラリの性能について気になったのでベンチマークを取ってみたという次第です.以下はその記録です.

追記

とのことでしたので,YAML::PPについても記載しました.

ベンチマークコード
#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use Benchmark qw(cmpthese);
use YAML ();
use YAML::Tiny ();
use YAML::Syck ();
use YAML::XS ();
use YAML::PP::Loader;
use YAML::PP::Dumper;

my $yaml_text = do { local $/; <DATA> };

my $yaml_pp_loader = YAML::PP::Loader->new;

# Deserialize
cmpthese(10000, {
    'YAML' => sub {
        YAML::Load($yaml_text);
    },
    'YAML::Tiny' => sub {
        YAML::Tiny::Load($yaml_text);
    },
    'YAML::Syck' => sub {
        YAML::Syck::Load($yaml_text);
    },
    'YAML::XS' => sub {
        YAML::XS::Load($yaml_text);
    },
    'YAML::PP' => sub {
        $yaml_pp_loader->load_string($yaml_text);
    },
});

my $hashref = YAML::XS::Load($yaml_text);

my $yaml_pp_dumper = YAML::PP::Dumper->new;

# Serialize
cmpthese(10000, {
    'YAML' => sub {
        YAML::Dump($hashref);
    },
    'YAML::Tiny' => sub {
        YAML::Tiny::Dump($hashref);
    },
    'YAML::Syck' => sub {
        YAML::Syck::Dump($hashref);
    },
    'YAML::XS' => sub {
        YAML::XS::Dump($hashref);
    },
    'YAML::PP' => sub {
        $yaml_pp_dumper->dump_string($hashref);
    },
});

__DATA__
# From: https://github.com/kubernetes/kubernetes/blob/7bbab6234f99af9adb700ff30968794084b6ee12/examples/mysql-wordpress-pd/wordpress-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
        - image: wordpress:4.8.0-apache
          name: wordpress
          env:
            - name: WORDPRESS_DB_HOST
              value: wordpress-mysql
            - name: WORDPRESS_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-pass
                  key: password.txt
          ports:
            - containerPort: 80
              name: wordpress
          volumeMounts:
            - name: wordpress-persistent-storage
              mountPath: /var/www/html
          volumes:
            - name: wordpress-persistent-storage
              persistentVolumeClaim:
                claimName: wp-pv-claim
Deserialize結果
              Rate   YAML::PP       YAML YAML::Tiny YAML::Syck   YAML::XS
YAML::PP     251/s         --       -29%       -86%       -97%       -98%
YAML         351/s        40%         --       -80%       -96%       -97%
YAML::Tiny  1767/s       604%       403%         --       -81%       -87%
YAML::Syck  9524/s      3696%      2613%       439%         --       -30%
YAML::XS   13699/s      5360%      3803%       675%        44%         --
Serialize結果
              Rate       YAML   YAML::PP YAML::Tiny   YAML::XS YAML::Syck
YAML         588/s         --       -74%       -84%       -96%       -97%
YAML::PP    2299/s       291%         --       -38%       -84%       -87%
YAML::Tiny  3731/s       535%        62%         --       -74%       -79%
YAML::XS   14286/s      2330%       521%       283%         --       -19%
YAML::Syck 17544/s      2884%       663%       370%        23%         --

なるほどという結果です.
DeserializeはYAML::XSが最も速く,SerializeはYAML::Syckが高速という結果になりました.
もちろん対象とするYAMLのデータ構造に依存する結果ではありますが,性能を考えるのであればYAML::XSかYAML::Syckを使っておけば良さそうという感じですね.


それぞれ,

  • YAML: Pure Perl実装.これでしか解釈できない記法が(なぜか!)ある.
  • YAML::Tiny: Pure Perl実装.PPなのでシンプル.
  • YAML::Syck: libsyckのバインディング.XSで比較的高速.*2
  • YAML::XS: libyamlのバインディング.XSで比較的高速.libyamlという安心感がある.現代では安定している.
  • YAML::PP: Pure Perl実装.YAML 1.2をサポートするというモチベーションらしい.

という特徴があるので (そして各々のライブラリで解釈できる構文が異なる場合があり,これは業界ではヤムルの地獄と呼ばれています),状況に応じて使い分ける必要はありそうです.こちらからは以上です.



*1:昔はよく動かなくなっていた印象がある

*2:しかしlibsyckってどこで開発してるんですか?