MessagePackとはシリアライズ(バイナリエンコード)の方法の一つで
- シリアライズ/デシリアライズが高速
- シリアライズされたサイズが小さい
- IDLが不要で汎用的
- ストリーム処理が可能(ProtocolBuffersでも出来るのかもしれませんが)
ということで今回は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してもダメ。なぜ…