Skip to content

Instantly share code, notes, and snippets.

@everbeen
Last active November 14, 2023 22:17
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save everbeen/07c38dcbba8d8a9d3c6f to your computer and use it in GitHub Desktop.
Save everbeen/07c38dcbba8d8a9d3c6f to your computer and use it in GitHub Desktop.
BSON vs. Gob vs. MessagePack encoding & decoding benchmark
package main
import (
"bytes"
"encoding/gob"
"fmt"
"github.com/ugorji/go/codec"
"io/ioutil"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"path"
"time"
)
const (
DISK_FILE_DIR = "/Users/Eric/Desktop"
DISK_FILE_NAME = "sampleobj"
MONGO_URL = "mongodb://172.18.1.1"
MONGO_DB = "giraffe"
MONGO_COLL = "benchmark.codec"
)
const (
SAMPLE_STRING = `JavaScript is the behavior, 测试, the third pillar in today's paradigm that looks at web pages as something that consists of clearly distinguishable parts: content (HTML), presentation (CSS) and behavior (JavaScript). Using JavaScript, you can create not only web pages but also desktop widgets, browser and application extensions, and other pieces of software. It's a pretty good deal: you learn one language and then code all kinds of different applications. While there's one chapter specifically dedicated to the web browser environment including DOM, Events and AJAX tutorials, the rest is applicable to the other environments.
Many web developers have tried coding or adopting some bits of JavaScript, but it is time to "man up" and learn the language properly because it is the language of the browser and is, virtually, everywhere. This book starts from zero, not assuming any prior JavaScript programming knowledge and takes you through all the in-depth and exciting futures hidden behind the facade.
Once listed in the "nice to have" sections of job postings, these days the knowledge of JavaScript is a deciding factor when it comes to hiring web developers. After reading this book you'll be prepared to ace your JavaScript job interview and even impress with some bits that the interviewer maybe didn't know. You should read this book if you want to be able to take your JavaScript skills to a new level of sophistication.`
)
type EncodeFunction func(map[string]interface{}) (time.Duration, []byte, error)
type DecodeFunction func([]byte) (time.Duration, map[string]interface{}, error)
var (
sampleObject = map[string]interface{}{
"bookID": "538b5a2404e26d9ad4000003",
"title": "Raspberry Pi Home Automation with Arduino",
"abstract": SAMPLE_STRING,
"time": time.Now().UTC(),
"cover": map[string]interface{}{
"dim": "615,791",
"path": "http://giraffe.oss-cn-qingdao.aliyuncs.com/giraffe/cover/2014/538b614604e26d9ad4000004_7sdqsg.jpg",
},
"publish_year": 2013,
"publish_month": 2,
"publisher": "Packt",
"long": int64(987125478598),
"rate": 5.588888,
"pages": 239,
"price": 5,
"editorRate": -2,
"volume": 0,
"edition": 2,
"category": 1,
"language": "en",
"isbn": []string{"978-1-84969-586-2", "1-84969-586-2"},
"isbn_empty": []string{},
"preview": nil,
"comment": "",
"authors": []string{"", "Andrew K. Dennis", "𠀾\U00020024"},
"formats": []map[string]interface{}{
map[string]interface{}{"format": 1, "path": "abc"},
map[string]interface{}{"format": 2, "path": "defg"},
},
"tags": []interface{}{
"raspberry pi",
map[string]interface{}{
"key": "someKey",
"value": map[string]interface{}{
"sub-key": "someSubKey",
"sub-value": []float64{-9999.0, 88.0},
},
},
-8888,
12.34567,
},
"society": map[string]interface{}{
"purchase": 0,
"favorite": 0,
"wishlist": 2,
"rateTimes": 100,
"rateTotal": 480,
"rate": 4.8,
"comment": 50,
},
}
)
func main() {
gob.Register(time.Time{})
gob.Register([]interface{}{})
gob.Register(map[string]interface{}{})
gob.Register([]map[string]interface{}{})
runEncodings()
runDecodings()
}
func runEncodings() {
type Wrapper struct {
Name string // encoding method name
Extention string // output file extention
Function EncodeFunction // encoding function
}
encodings := []*Wrapper{
&Wrapper{"BSON", "bson", encodeBSON},
&Wrapper{"Gob", "gob", encodeGob},
&Wrapper{"MessagePack", "msgpack", encodeMessagePack},
}
fmt.Println("================ Encoding ================")
for _, w := range encodings {
d, b, err := w.Function(sampleObject)
if err != nil {
fmt.Printf("%-12s ERROR: %@\n", w.Name, err.Error())
continue
}
fmt.Printf("%-12s: time=%#8.3fμs, size=%d\n", w.Name, float64(d)/1e3, len(b))
// write encoding result to disk
fileName := fmt.Sprintf("%s.%s", DISK_FILE_NAME, w.Extention)
outputPath := path.Join(DISK_FILE_DIR, fileName)
err = ioutil.WriteFile(outputPath, b, 0644)
if err != nil {
panic(err)
}
}
fmt.Println("================== Done ==================")
}
func runDecodings() {
type Wrappewr struct {
Name string // decosing method name
Extention string // input file extention
Function DecodeFunction // decoding function
}
decodings := []*Wrappewr{
&Wrappewr{"BSON", "bson", decodeBSON},
&Wrappewr{"Gob", "gob", decodeGob},
&Wrappewr{"MessagePack", "msgpack", decodeMessagePack},
}
fmt.Println("================ Decoding ================")
doc := bson.M{
"_id": time.Now(),
}
for _, w := range decodings {
// read disk file
fileName := fmt.Sprintf("%s.%s", DISK_FILE_NAME, w.Extention)
inputPath := path.Join(DISK_FILE_DIR, fileName)
b, err := ioutil.ReadFile(inputPath)
if err != nil {
fmt.Printf("%-12s ERROR: %@\n", w.Name, err.Error())
continue
}
d, v, err := w.Function(b)
if err != nil {
fmt.Printf("%-12s ERROR: %@\n", w.Name, err.Error())
continue
}
fmt.Printf("%-12s: time=%#8.3fus\n", w.Name, float64(d)/1e3)
doc[w.Name] = v
}
// write results to MongoDB
session, err := mgo.Dial(MONGO_URL)
if err != nil {
panic(err)
}
defer session.Close()
err = session.DB(MONGO_DB).C(MONGO_COLL).Insert(doc)
if err != nil {
panic(err)
}
fmt.Println("================== Done ==================")
}
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
func encodeBSON(obj map[string]interface{}) (time.Duration, []byte, error) {
beginTime := time.Now()
b, err := bson.Marshal(obj)
if err != nil {
return 0.0, nil, err
}
d := time.Now().Sub(beginTime)
return d, b, nil
}
func encodeGob(obj map[string]interface{}) (time.Duration, []byte, error) {
beginTime := time.Now()
buff := new(bytes.Buffer)
encoder := gob.NewEncoder(buff)
err := encoder.Encode(obj)
if err != nil {
return 0.0, nil, err
}
b := buff.Bytes()
d := time.Now().Sub(beginTime)
return d, b, nil
}
func encodeMessagePack(obj map[string]interface{}) (time.Duration, []byte, error) {
beginTime := time.Now()
var handler codec.MsgpackHandle
buff := new(bytes.Buffer)
encoder := codec.NewEncoder(buff, &handler)
err := encoder.Encode(obj)
if err != nil {
return 0.0, nil, err
}
b := buff.Bytes()
d := time.Now().Sub(beginTime)
return d, b, nil
}
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
func decodeBSON(b []byte) (time.Duration, map[string]interface{}, error) {
beginTime := time.Now()
var v map[string]interface{}
err := bson.Unmarshal(b, &v)
if err != nil {
return 0.0, nil, err
}
d := time.Now().Sub(beginTime)
return d, v, nil
}
func decodeGob(b []byte) (time.Duration, map[string]interface{}, error) {
beginTime := time.Now()
var v map[string]interface{}
buff := bytes.NewBuffer(b)
decoder := gob.NewDecoder(buff)
err := decoder.Decode(&v)
if err != nil {
return 0.0, nil, err
}
d := time.Now().Sub(beginTime)
return d, v, nil
}
func decodeMessagePack(b []byte) (time.Duration, map[string]interface{}, error) {
beginTime := time.Now()
var handler codec.MsgpackHandle
var v map[string]interface{}
decoder := codec.NewDecoderBytes(b, &handler)
err := decoder.Decode(&v)
if err != nil {
return 0.0, nil, err
}
d := time.Now().Sub(beginTime)
return d, v, nil
}
Desktop ➤ ./main
================ Encoding ================
BSON : time= 58.922μs, size=2382
Gob : time= 412.141μs, size=2759
MessagePack : time= 51.395μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 61.721us
Gob : time= 260.801us
MessagePack : time= 82.010us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 60.732μs, size=2382
Gob : time= 420.968μs, size=2759
MessagePack : time= 57.369μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 60.554us
Gob : time= 273.868us
MessagePack : time= 82.861us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 66.724μs, size=2382
Gob : time= 425.433μs, size=2759
MessagePack : time= 57.988μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 62.214us
Gob : time= 252.656us
MessagePack : time= 82.146us
================== Done ==================
Desktop ➤
Desktop ➤ ./main
================ Encoding ================
BSON : time= 63.632μs, size=2382
Gob : time= 396.575μs, size=2759
MessagePack : time= 52.121μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 63.454us
Gob : time= 269.334us
MessagePack : time= 78.278us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 64.367μs, size=2382
Gob : time= 396.325μs, size=2759
MessagePack : time= 62.658μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 62.867us
Gob : time= 268.532us
MessagePack : time= 79.308us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 69.458μs, size=2382
Gob : time= 423.515μs, size=2759
MessagePack : time= 56.863μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 62.490us
Gob : time= 252.000us
MessagePack : time= 90.509us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 58.875μs, size=2382
Gob : time= 403.429μs, size=2758
MessagePack : time= 50.493μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 59.615us
Gob : time= 256.975us
MessagePack : time= 94.732us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 64.077μs, size=2382
Gob : time= 398.299μs, size=2759
MessagePack : time= 52.327μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 93.343us
Gob : time= 325.189us
MessagePack : time= 69.840us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 65.793μs, size=2382
Gob : time= 411.302μs, size=2759
MessagePack : time= 53.875μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 61.903us
Gob : time= 275.300us
MessagePack : time= 65.369us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 60.651μs, size=2382
Gob : time= 409.052μs, size=2758
MessagePack : time= 51.147μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 59.323us
Gob : time= 256.700us
MessagePack : time= 83.984us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 60.576μs, size=2382
Gob : time= 424.650μs, size=2758
MessagePack : time= 51.628μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 60.147us
Gob : time= 258.529us
MessagePack : time= 84.448us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 64.550μs, size=2382
Gob : time= 392.359μs, size=2759
MessagePack : time= 51.921μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 62.711us
Gob : time= 296.202us
MessagePack : time= 103.330us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 64.432μs, size=2382
Gob : time= 426.694μs, size=2759
MessagePack : time= 52.000μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 76.070us
Gob : time= 271.120us
MessagePack : time= 67.436us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 60.628μs, size=2382
Gob : time= 408.804μs, size=2759
MessagePack : time= 50.180μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 62.212us
Gob : time= 274.868us
MessagePack : time= 82.234us
================== Done ==================
Desktop ➤ ./main
================ Encoding ================
BSON : time= 66.879μs, size=2382
Gob : time= 418.987μs, size=2759
MessagePack : time= 63.126μs, size=2156
================== Done ==================
================ Decoding ================
BSON : time= 68.319us
Gob : time= 271.848us
MessagePack : time= 82.848us
================== Done ==================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment