2016-09-23

MessagePackを触ってみた

MessagePackとはシリアライズ(バイナリエンコード)の方法の一つで

ProtocolBuffersと似たような性質を持ちますが、ProtocolBuffersと違って という特徴を持ちます。TreasureDataのバックエンドであるPlazmaDBやfluentdでも利用されている技術になります。

ということで今回はMessagePackを触ってみました。

RubyでMessagePackを試す

以下でGemをインストール

gem intall msgpack

シリアライズして標準出力に出力するRubyの例

#!/usr/bin/env ruby

require 'json'
require 'msgpack'

hash = {
  name: "John Doe",
  id: 1234,
  email: "jdoe@example.com",
  phone:[{
    number: "555-4321",
    type: "HOME"
  }]
}
STDOUT.binmode
print hash.to_msgpack

MessagePack形式の標準入力をデシリアライズした結果をJSONで出力する例

#!/usr/bin/env ruby

require 'json'
require 'msgpack'

STDIN.binmode
bin_body = STDIN.read
hash = MessagePack::unpack(bin_body)
puts hash.to_json

サイズメリットはこんな感じ

-rw-r--r--  1 mtajitsu  staff   103B  9 21 22:05 json
-rw-r--r--  1 mtajitsu  staff    78B  9 21 22:02 msgpack

コストメリットは超ざっくりですが、以下のスクリプトでベンチマークを取りました。

#!/usr/bin/env ruby

require 'msgpack'
require 'benchmark'
require 'json'

hash = {
  name: "John Doe",
  id: 1234,
  email: "jdoe@example.com",
  phone:[{
    number: "555-4321",
    type: "HOME"
  }]
}

result = Benchmark.realtime do
  10_000_000.times do
    hash.to_msgpack
  end
end
puts "MessagePack:Serialize #{result}s"

result = Benchmark.realtime do
  10_000_000.times do
    hash.to_json
  end 
end
puts "JSON:Serialize #{result}s"

STDIN.binmode
bin_body = STDIN.read
result = Benchmark.realtime do
  10_000_000.times do
    MessagePack.unpack(bin_body)
  end
end
puts "MessagePack:Deserialize #{result}s"

result = Benchmark.realtime do
  10_000_000.times do
    JSON.parse('{"name":"John Doe","id":1234,"email":"jdoe@example.com","phone":[{"number":"555-4321","type":"HOME"}]}')
  end 
end
puts "JSON:Deserialize #{result}s"

実行結果↓

$ ./speed.rb < msgpack
MessagePack:Serialize     16.359407644020393s
JSON:Serialize            70.65841750899563s
MessagePack:Deserialize   41.31627137801843s
JSON:Deserialize          85.64288567798212s

JSONと比較するとシリアライズがかなり高速です。デシリアライズもJSONの2倍高速。

MessagePack IDLも試してみる

MessagePackにはProtocolBuffersと同様にIDLもあります。

まずはHaskellのインストール

$ brew cask install haskell-platform

MessagePack IDLのインストール&設定

$ cabal update
$ cabal install msgpack-idl

がうまくいかず…orz

Resolving dependencies...
cabal: Could not resolve dependencies:
trying: base-4.9.0.0/installed-4.9... (dependency of msgpack-idl-0.2.1)
trying: transformers-0.5.2.0/installed-0.5... (dependency of cmdargs-0.10.14)
trying: peggy-0.3.2 (dependency of msgpack-idl-0.2.1)
next goal: monad-control (dependency of peggy-0.3.2)
rejecting: monad-control-1.0.1.0/installed-1xo..., monad-control-1.0.1.0,
monad-control-1.0.0.5, monad-control-1.0.0.4, monad-control-1.0.0.3,
monad-control-1.0.0.2, monad-control-1.0.0.1, monad-control-1.0.0.0 (conflict:
peggy => monad-control==0.3.*)
rejecting: monad-control-0.3.3.1, monad-control-0.3.3.0 (conflict:
transformers==0.5.2.0/installed-0.5..., monad-control => transformers>=0.2 &&
<0.5)
rejecting: monad-control-0.3.2.3, monad-control-0.3.2.2, monad-control-0.3.2.1
(conflict: transformers==0.5.2.0/installed-0.5..., monad-control =>
transformers>=0.2 && <0.4)
rejecting: monad-control-0.3.2, monad-control-0.3.1.4 (conflict:
base==4.9.0.0/installed-4.9..., monad-control => base>=3 && <4.7)
rejecting: monad-control-0.3.1.3, monad-control-0.3.1.2,
monad-control-0.3.1.1, monad-control-0.3.1 (conflict:
base==4.9.0.0/installed-4.9..., monad-control => base>=3 && <4.6)
rejecting: monad-control-0.3.0.1, monad-control-0.3 (conflict:
base==4.9.0.0/installed-4.9..., monad-control => base>=3 && <4.5)
rejecting: monad-control-0.2.0.3, monad-control-0.2.0.2,
monad-control-0.2.0.1, monad-control-0.2, monad-control-0.1 (conflict: peggy
=> monad-control==0.3.*)
Dependency tree exhaustively searched.

git cloneでcabal installしてもダメ。なぜ…

参考URL

このエントリーをはてなブックマークに追加