Last active
August 29, 2015 13:56
-
-
Save edsrzf/9314832 to your computer and use it in GitHub Desktop.
Fair serialization benchmarks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/gob" | |
"encoding/json" | |
"io" | |
"io/ioutil" | |
"math" | |
"testing" | |
"time" | |
"github.com/ugorji/go/codec" | |
) | |
type AnonInTestStruc struct { | |
AS string | |
AI64 int64 | |
AI16 int16 | |
AUi64 uint64 | |
ASslice []string | |
AI64slice []int64 | |
} | |
type TestStruc struct { | |
S string | |
I64 int64 | |
I16 int16 | |
Ui64 uint64 | |
Ui8 uint8 | |
B bool | |
By byte | |
Sslice []string | |
I64slice []int64 | |
I16slice []int16 | |
Ui64slice []uint64 | |
Ui8slice []uint8 | |
Bslice []bool | |
Byslice []byte | |
Islice []interface{} | |
Iptrslice []*int64 | |
AnonInTestStruc | |
//M map[interface{}]interface{} `json:"-",bson:"-"` | |
Ms map[string]interface{} | |
Msi64 map[string]int64 | |
Nintf interface{} //don't set this, so we can test for nil | |
T time.Time | |
Nmap map[string]bool //don't set this, so we can test for nil | |
Nslice []byte //don't set this, so we can test for nil | |
Nint64 *int64 //don't set this, so we can test for nil | |
Mtsptr map[string]*TestStruc | |
Mts map[string]TestStruc | |
Its []*TestStruc | |
Nteststruc *TestStruc | |
} | |
var timeLoc = time.FixedZone("", -8*60*60) // UTC-08:00 //time.UTC-8 | |
var timeToCompare1 = time.Date(2012, 2, 2, 2, 2, 2, 2000, timeLoc) | |
func newTestStruc(depth int, bench bool) (ts *TestStruc) { | |
ts = &TestStruc{ | |
S: "some string", | |
I64: math.MaxInt64 * 2 / 3, // 64, | |
I16: 16, | |
Ui64: uint64(int64(math.MaxInt64 * 2 / 3)), // 64, //don't use MaxUint64, as bson can't write it | |
Ui8: 160, | |
B: true, | |
By: 5, | |
Sslice: []string{"one", "two", "three"}, | |
I64slice: []int64{1, 2, 3}, | |
I16slice: []int16{4, 5, 6}, | |
Ui64slice: []uint64{137, 138, 139}, | |
Ui8slice: []uint8{210, 211, 212}, | |
Bslice: []bool{true, false, true, false}, | |
Byslice: []byte{13, 14, 15}, | |
Islice: []interface{}{"true", true, "no", false, uint64(288), float64(0.4)}, | |
Ms: map[string]interface{}{ | |
"true": "true", | |
"int64(9)": false, | |
}, | |
Msi64: map[string]int64{ | |
"one": 1, | |
"two": 2, | |
}, | |
T: timeToCompare1, | |
AnonInTestStruc: AnonInTestStruc{ | |
AS: "A-String", | |
AI64: 64, | |
AI16: 16, | |
AUi64: 64, | |
ASslice: []string{"Aone", "Atwo", "Athree"}, | |
AI64slice: []int64{1, 2, 3}, | |
}, | |
} | |
if depth > 0 { | |
depth-- | |
if ts.Mtsptr == nil { | |
ts.Mtsptr = make(map[string]*TestStruc) | |
} | |
if ts.Mts == nil { | |
ts.Mts = make(map[string]TestStruc) | |
} | |
ts.Mtsptr["0"] = newTestStruc(depth, bench) | |
ts.Mts["0"] = *(ts.Mtsptr["0"]) | |
ts.Its = append(ts.Its, ts.Mtsptr["0"]) | |
} | |
return | |
} | |
const benchDepth = 1 | |
var benchTs = newTestStruc(benchDepth, true) | |
type Encoder interface { | |
Encode(v interface{}) error | |
} | |
func benchEncode(b *testing.B, enc Encoder) { | |
var ts interface{} = benchTs | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
err := enc.Encode(ts) | |
if err != nil { | |
b.Fatal("benchEncode error:", err) | |
} | |
} | |
} | |
func BenchmarkGobEncode(b *testing.B) { | |
enc := gob.NewEncoder(ioutil.Discard) | |
benchEncode(b, enc) | |
} | |
func BenchmarkJSONEncode(b *testing.B) { | |
enc := json.NewEncoder(ioutil.Discard) | |
benchEncode(b, enc) | |
} | |
func BenchmarkMsgpackEncode(b *testing.B) { | |
enc := codec.NewEncoder(ioutil.Discard, &codec.MsgpackHandle{}) | |
benchEncode(b, enc) | |
} | |
type Decoder interface { | |
Decode(v interface{}) error | |
} | |
type loopReader struct { | |
buf []byte | |
repeating int | |
i int | |
} | |
func (r *loopReader) Read(b []byte) (int, error) { | |
n := copy(b, r.buf[r.i:]) | |
r.i += n | |
if r.i >= len(r.buf) { | |
r.i = r.repeating | |
} | |
return n, nil | |
} | |
func loadReader(buf *bytes.Buffer, enc Encoder) io.Reader { | |
err := enc.Encode(benchTs) | |
if err != nil { | |
panic("error encoding decode benchmark") | |
} | |
return &loopReader{buf: buf.Bytes()} | |
} | |
func benchDecode(b *testing.B, dec Decoder) { | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
var ts TestStruc | |
err := dec.Decode(&ts) | |
if err != nil { | |
b.Fatal("benchEncode error:", err) | |
} | |
} | |
} | |
func BenchmarkGobDecode(b *testing.B) { | |
var buf bytes.Buffer | |
enc := gob.NewEncoder(&buf) | |
enc.Encode(benchTs) | |
r := &loopReader{repeating: buf.Len()} | |
r.buf = append(r.buf, buf.Bytes()...) | |
buf.Reset() | |
enc.Encode(benchTs) | |
r.buf = append(r.buf, buf.Bytes()...) | |
dec := gob.NewDecoder(r) | |
benchDecode(b, dec) | |
} | |
func BenchmarkJSONDecode(b *testing.B) { | |
var buf bytes.Buffer | |
enc := json.NewEncoder(&buf) | |
dec := json.NewDecoder(loadReader(&buf, enc)) | |
benchDecode(b, dec) | |
} | |
func BenchmarkMsgpackDecode(b *testing.B) { | |
var buf bytes.Buffer | |
enc := codec.NewEncoder(&buf, &codec.MsgpackHandle{}) | |
dec := codec.NewDecoder(loadReader(&buf, enc), &codec.MsgpackHandle{}) | |
benchDecode(b, dec) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Results on my machine: