speice.io/assets/js/39c8d8a0.ee5aa2e0.js

1 line
23 KiB
JavaScript
Raw Normal View History

"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["156"],{5100:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return o},default:function(){return d},frontMatter:function(){return r},metadata:function(){return s},toc:function(){return h}});var s=n(3303),i=n(5893),a=n(65);let r={slug:"2019/09/binary-format-shootout",title:"Binary format shootout",date:new Date("2019-09-28T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,l={authorsImageUrls:[void 0]},h=[{value:"Prologue: Binary Parsing with Nom",id:"prologue-binary-parsing-with-nom",level:2},{value:"Cap'n Proto",id:"capn-proto",level:2},{value:"Flatbuffers",id:"flatbuffers",level:2},{value:"Simple Binary Encoding",id:"simple-binary-encoding",level:2},{value:"Results",id:"results",level:2},{value:"Serialization",id:"serialization",level:3},{value:"Deserialization",id:"deserialization",level:3},{value:"Conclusion",id:"conclusion",level:2}];function c(e){let t={a:"a",code:"code",del:"del",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["I've found that in many personal projects,\n",(0,i.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Analysis_paralysis",children:"analysis paralysis"})," is particularly deadly.\nMaking good decisions in the beginning avoids pain and suffering later; if extra research prevents\nfuture problems, I'm happy to continue ",(0,i.jsx)(t.del,{children:"procrastinating"})," researching indefinitely."]}),"\n",(0,i.jsx)(t.p,{children:"So let's say you're in need of a binary serialization format. Data will be going over the network,\nnot just in memory, so having a schema document and code generation is a must. Performance is\ncrucial, so formats that support zero-copy de/serialization are given priority. And the more\nlanguages supported, the better; I use Rust, but can't predict what other languages this could\ninteract with."}),"\n",(0,i.jsx)(t.p,{children:"Given these requirements, the candidates I could find were:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://capnproto.org/",children:"Cap'n Proto"})," has been around the longest, and is the most established"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://google.github.io/flatbuffers/",children:"Flatbuffers"})," is the newest, and claims to have a simpler\nencoding"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://github.com/real-logic/simple-binary-encoding",children:"Simple Binary Encoding"})," has the simplest\nencoding, but the Rust implementation is unmaintained"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Any one of these will satisfy the project requirements: easy to transmit over a network, reasonably\nfast, and polyglot support. But how do you actually pick one? It's impossible to know what issues\nwill follow that choice, so I tend to avoid commitment until the last possible moment."}),"\n",(0,i.jsxs)(t.p,{children:['Still, a choice must be made. Instead of worrying about which is "the best," I decided to build a\nsmall proof-of-concept system in each format and pit them against each other. All code can be found\nin the ',(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout",children:"repository"})," for this post."]}),"\n",(0,i.jsx)(t.p,{children:"We'll discuss more in detail, but a quick preview of the results:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Cap'n Proto: Theoretically performs incredibly well, the implementation had issues"}),"\n",(0,i.jsx)(t.li,{children:'Flatbuffers: Has some quirks, but largely lived up to its "zero-copy" promises'}),"\n",(0,i.jsx)(t.li,{children:"SBE: Best median and worst-case performance, but the message structure has a limited feature set"}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"prologue-binary-parsing-with-nom",children:"Prologue: Binary Parsing with Nom"}),"\n",(0,i.jsxs)(t.p,{children:["Our benchmark sys