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

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

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

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

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

ベンチマークコード
#!/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 ();

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

# 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);
    },
});

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

# 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);
    },
});

__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 YAML::Tiny YAML::Syck   YAML::XS
YAML         371/s         --       -80%       -96%       -97%
YAML::Tiny  1813/s       388%         --       -81%       -87%
YAML::Syck  9434/s      2442%       420%         --       -34%
YAML::XS   14205/s      3727%       683%        51%         --
Serialize結果
              Rate       YAML YAML::Tiny   YAML::XS YAML::Syck
YAML         598/s         --       -83%       -95%       -97%
YAML::Tiny  3546/s       493%         --       -73%       -80%
YAML::XS   12987/s      2073%       266%         --       -29%
YAML::Syck 18182/s      2942%       413%        40%         --

なるほどという結果です.
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という安心感がある.現代では安定している.

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



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

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