お世話になっております。
しゃまとんです。
ちょっとしたお知らせです。
タイトルの通りなんですが、golangで使えるMessagePackのシリアライザを作りました。
(🎉個人的にはパンパカパーン🎉)
まず、MessagePackとはデータのシリアライズフォーマットの1つで効率の良い形式として知られています。よくJSONと比較・検証されて使われていることが多いですね。
現在は多くの言語で使えるようになっており、言語間で何かデータのやり取りをするときに候補の1つになっています。
公式にもある通り、JSONよりも軽量で速いのが特徴です。
もちろんGo言語でもMessagePackが扱えるパッケージがすでにいくつか存在しており、使いたければ使える状況になっています。自分自身も使っていたのですが、とあるきっかけからpackageを覗いてみたところ、なんとなくもう少し速くできそうかなぁ…と思いました。
で、簡単な検証用ベンチマークコードを書いてみたところ、速くなりそうかなぁ…ということで書き始めたのが最初でした。コードを書き換えてはベンチマークを確認して…実装して…を繰り返しすすめていき、現在(2018.09時点)v1.0としてリリースできました。
エンドポイントの名称は迷ったんですが、いろいろ考えてEncode / Decodeにしました。
呼び出しはこんな感じで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package main; import ( "github.com/shamaton/msgpack" ) func main() { type Struct struct { String string } v := Struct{String: "msgpack"} d, err := msgpack.Encode(v) if err != nil { panic(err) } r := Struct{} err = msgpack.Decode(d, &r) if err != nil { panic(err) } } |
単純に使うだけならEncode/Decodeを呼び出すだけです!
引数は標準のパッケージencoding/jsonと同じ形にしてます。(置き換えが容易かも…!)
で、肝心のパフォーマンスですが、まずはシリアライズ。
自分が知っている範囲で他のMessagePackやJSON等の別フォーマットと比較してみます。ベンチマークはおそらくユーザーが呼び出すであろうエンドポイントでとってみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ go test -bench CompareEncode -benchmem goos: darwin goarch: amd64 pkg: github.com/shamaton/msgpack_bench BenchmarkCompareEncodeShamaton-4 1000000 1255 ns/op 320 B/op 3 allocs/op BenchmarkCompareEncodeVmihailenco-4 300000 4645 ns/op 968 B/op 14 allocs/op BenchmarkCompareEncodeArrayShamaton-4 1000000 1110 ns/op 256 B/op 3 allocs/op BenchmarkCompareEncodeArrayVmihailenco-4 300000 4387 ns/op 968 B/op 14 allocs/op BenchmarkCompareEncodeUgorji-4 1000000 1921 ns/op 986 B/op 11 allocs/op BenchmarkCompareEncodeZeroformatter-4 1000000 1890 ns/op 744 B/op 13 allocs/op BenchmarkCompareEncodeJson-4 500000 3428 ns/op 1224 B/op 16 allocs/op BenchmarkCompareEncodeGob-4 200000 11537 ns/op 2824 B/op 50 allocs/op BenchmarkCompareEncodeProtocolBuffer-4 500000 2338 ns/op 792 B/op 29 allocs/op PASS ok github.com/shamaton/msgpack_bench 14.481s |
Shamatonとついているものが今回リリースしたものになります。ArrayShamatonというのはMessagePackのフォーマットが軽量なパターンを採用しているものです(UnityではMessagePack-CSharpでおなじみですね?)。今回のケースでは通常のEncodeでも他のパッケージよりも性能よく動作させられたっぽいです。
次にデシリアライズです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ go test -bench CompareDecode -benchmem goos: darwin goarch: amd64 pkg: github.com/shamaton/msgpack_bench BenchmarkCompareDecodeShamaton-4 1000000 1393 ns/op 512 B/op 6 allocs/op BenchmarkCompareDecodeVmihailenco-4 300000 5393 ns/op 1056 B/op 33 allocs/op BenchmarkCompareDecodeArrayShamaton-4 2000000 990 ns/op 512 B/op 6 allocs/op BenchmarkCompareDecodeArrayVmihailenco-4 300000 4397 ns/op 992 B/op 22 allocs/op BenchmarkCompareDecodeUgorji-4 500000 2587 ns/op 845 B/op 12 allocs/op BenchmarkCompareDecodeZeroformatter-4 1000000 2350 ns/op 976 B/op 29 allocs/op BenchmarkCompareDecodeJson-4 200000 8904 ns/op 1216 B/op 43 allocs/op BenchmarkCompareDecodeGob-4 50000 34805 ns/op 10172 B/op 275 allocs/op BenchmarkCompareDecodeProtocolBuffer-4 1000000 1759 ns/op 656 B/op 19 allocs/op PASS ok github.com/shamaton/msgpack_bench 16.946s |
こちらも性能良く動作させられたっぽいです。ただProtocol Bufferはデータの形次第でパフォーマンス良くなることがありました(struct onlyな構成など)。まぁprotoファイルとかを準備しないといけないので、その点よいかなーと。
結果を見る感じだとArray呼び出しがパフォーマンスがやはり良いので、使えるならAsArrayを使うのが良さそうかなと思います。ベンチマークですが、こちらにコードがあるので何かあれば教えてください。
ということで、単純な呼び出しでMessagePack系では割と速いシリアライザを作ることが出来ました。よかったよかった。それと今回の実装でzeroformatter側にも反映できそうなところもわかったので、対応できればなーと思っています。
あと余談ですが、タグでシリアライズ対象の設定ができたりとか、拡張エンコード・デコードにも対応させたりもしてます。(この辺はREADMEとかExampleに書く予定です)
よかったら使ってみてください!
以上です。
I’ve just published MessagePack Serializer(v1.0.0) for golang. Its performance is faster than the others. You can use simply. Please see and try it!! 🎉🎉🎉https://t.co/X4P5qNWOzH#Golang
— しゃまとん ʕ ◔ϖ◔ʔ (@shamaton) 2018年9月28日