Protocol Buffers が本当に遅いのか実際に確かめてみた
Protocol Buffers で検索すると Protocol Buffersは遅い という MessagePack 作者による2008年の記事が未だに上位に来る。 一方で、Protocol Buffersは遅いのか という反論記事も見つかる。 一体遅いのか速いのかどっちなんだ!!ということで、ベンチマークを取ってみた。
2016年8月現在では、Protocol Buffer の最新バージョンは 3.0.0 であり、MessagePack の C++ バインディングの最新バージョンは 2.0.0 なので、これらのバージョンを使ってベンチマークを取ることにした。
ベンチマーク
元の記事を踏襲して、以下の4つのメッセージを使ってベンチマークを行った。
- Test1: 2つの符号無し整数
- Test2: 2つの符号付き整数
- Test3: 8KBのバイト列
- Test4: Test1 + Test2 + Test3
Test1 と Test2 は 223 個、Test3 と Test4 は 216 個のメッセージをシリアライズして所要時間を計測し、再びそれをデシリアライズして所要時間を計測した。 外乱の影響を抑えるため、それぞれのワークロードを10回ずつ実行して所要時間の最小値を最終結果とした。
環境:
- Linux 4.4.0 on Windows 10 (Hyper-V)
- g++ 5.4.0
- Intel Core i7-5820K CPU @ 3.30GHz
- Memory 4GB
Test1: 2つの符号無し整数
Serialize | Deserialize | Size | |
---|---|---|---|
Protobuf | 107 msec | 145 msec | 32 MB |
MessagePack | 100 msec | 1929 msec | 24 MB |
シリアライズにかかる時間はほとんど同じだったが、MessagePack のデシリアライズが Protobuf の10倍以上遅い。
Test2: 2つの符号付き整数
Serialize | Deserialize | Size | |
---|---|---|---|
Protobuf | 112 msec | 147 msec | 32 MB |
MessagePack | 102 msec | 1954 msec | 24 MB |
Test1 とほぼ同じ結果になった。
上で挙げた記事では Protobuf の符号付き整数のシリアライズ後のサイズが非常に大きいと書いてあるが、sint
を使えば MessagePack と同じサイズになる。
(Protobuf と MessagePack のサイズ差はタグの有無によるもの)
Test3: 8KBのバイト列
Serialize | Deserialize | Size | |
---|---|---|---|
Protobuf | 162 msec | 42 msec | 512 MB |
MessagePack | 121 msec | 79 msec | 512 MB |
バイト列のシリアライズは MessagePack の方が速かった。逆にデシリアライズは Protobuf の方が速い。
Test4: Test1 + Test2 + Test3
Serialize | Deserialize | Size | |
---|---|---|---|
Protobuf | 165 msec | 66 msec | 513 MB |
MessagePack | 123 msec | 83 msec | 513 MB |
Test3 と同じくシリアライズは MessagePack の方が速く、デシリアライズは Protobuf の方が速いという結果になった。
考察
ベンチマークの結果から、バイト列のシリアライズは MessagePack の方が速いが、デシリアライズや整数のシリアライズは Protobuf の方が速いことがわかった。 したがって、2016年の現在においては Protobuf は別に遅くないと思ってよさそう。
ベンチマークプログラム
https://gist.github.com/nojima/005cf04bfa35a1fb971adc43b54abbef