diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-msgpack/codec/bench_test.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-msgpack/codec/bench_test.go | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/bench_test.go b/vendor/github.com/hashicorp/go-msgpack/codec/bench_test.go new file mode 100644 index 000000000..4d437035e --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/bench_test.go @@ -0,0 +1,319 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +import ( + "bytes" + "encoding/gob" + "encoding/json" + "flag" + "fmt" + "reflect" + "runtime" + "testing" + "time" +) + +// Sample way to run: +// go test -bi -bv -bd=1 -benchmem -bench=. + +var ( + _ = fmt.Printf + benchTs *TestStruc + + approxSize int + + benchDoInitBench bool + benchVerify bool + benchUnscientificRes bool = false + //depth of 0 maps to ~400bytes json-encoded string, 1 maps to ~1400 bytes, etc + //For depth>1, we likely trigger stack growth for encoders, making benchmarking unreliable. + benchDepth int + benchInitDebug bool + benchCheckers []benchChecker +) + +type benchEncFn func(interface{}) ([]byte, error) +type benchDecFn func([]byte, interface{}) error +type benchIntfFn func() interface{} + +type benchChecker struct { + name string + encodefn benchEncFn + decodefn benchDecFn +} + +func benchInitFlags() { + flag.BoolVar(&benchInitDebug, "bg", false, "Bench Debug") + flag.IntVar(&benchDepth, "bd", 1, "Bench Depth: If >1, potential unreliable results due to stack growth") + flag.BoolVar(&benchDoInitBench, "bi", false, "Run Bench Init") + flag.BoolVar(&benchVerify, "bv", false, "Verify Decoded Value during Benchmark") + flag.BoolVar(&benchUnscientificRes, "bu", false, "Show Unscientific Results during Benchmark") +} + +func benchInit() { + benchTs = newTestStruc(benchDepth, true) + approxSize = approxDataSize(reflect.ValueOf(benchTs)) + bytesLen := 1024 * 4 * (benchDepth + 1) * (benchDepth + 1) + if bytesLen < approxSize { + bytesLen = approxSize + } + + benchCheckers = append(benchCheckers, + benchChecker{"msgpack", fnMsgpackEncodeFn, fnMsgpackDecodeFn}, + benchChecker{"binc-nosym", fnBincNoSymEncodeFn, fnBincNoSymDecodeFn}, + benchChecker{"binc-sym", fnBincSymEncodeFn, fnBincSymDecodeFn}, + benchChecker{"simple", fnSimpleEncodeFn, fnSimpleDecodeFn}, + benchChecker{"gob", fnGobEncodeFn, fnGobDecodeFn}, + benchChecker{"json", fnJsonEncodeFn, fnJsonDecodeFn}, + ) + if benchDoInitBench { + runBenchInit() + } +} + +func runBenchInit() { + logT(nil, "..............................................") + logT(nil, "BENCHMARK INIT: %v", time.Now()) + logT(nil, "To run full benchmark comparing encodings (MsgPack, Binc, Simple, JSON, GOB, etc), "+ + "use: \"go test -bench=.\"") + logT(nil, "Benchmark: ") + logT(nil, "\tStruct recursive Depth: %d", benchDepth) + if approxSize > 0 { + logT(nil, "\tApproxDeepSize Of benchmark Struct: %d bytes", approxSize) + } + if benchUnscientificRes { + logT(nil, "Benchmark One-Pass Run (with Unscientific Encode/Decode times): ") + } else { + logT(nil, "Benchmark One-Pass Run:") + } + for _, bc := range benchCheckers { + doBenchCheck(bc.name, bc.encodefn, bc.decodefn) + } + logT(nil, "..............................................") + if benchInitDebug { + logT(nil, "<<<<====>>>> depth: %v, ts: %#v\n", benchDepth, benchTs) + } +} + +func fnBenchNewTs() interface{} { + return new(TestStruc) +} + +func doBenchCheck(name string, encfn benchEncFn, decfn benchDecFn) { + runtime.GC() + tnow := time.Now() + buf, err := encfn(benchTs) + if err != nil { + logT(nil, "\t%10s: **** Error encoding benchTs: %v", name, err) + } + encDur := time.Now().Sub(tnow) + encLen := len(buf) + runtime.GC() + if !benchUnscientificRes { + logT(nil, "\t%10s: len: %d bytes\n", name, encLen) + return + } + tnow = time.Now() + if err = decfn(buf, new(TestStruc)); err != nil { + logT(nil, "\t%10s: **** Error decoding into new TestStruc: %v", name, err) + } + decDur := time.Now().Sub(tnow) + logT(nil, "\t%10s: len: %d bytes, encode: %v, decode: %v\n", name, encLen, encDur, decDur) +} + +func fnBenchmarkEncode(b *testing.B, encName string, ts interface{}, encfn benchEncFn) { + runtime.GC() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := encfn(ts) + if err != nil { + logT(b, "Error encoding benchTs: %s: %v", encName, err) + b.FailNow() + } + } +} + +func fnBenchmarkDecode(b *testing.B, encName string, ts interface{}, + encfn benchEncFn, decfn benchDecFn, newfn benchIntfFn, +) { + buf, err := encfn(ts) + if err != nil { + logT(b, "Error encoding benchTs: %s: %v", encName, err) + b.FailNow() + } + runtime.GC() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ts = newfn() + if err = decfn(buf, ts); err != nil { + logT(b, "Error decoding into new TestStruc: %s: %v", encName, err) + b.FailNow() + } + if benchVerify { + if vts, vok := ts.(*TestStruc); vok { + verifyTsTree(b, vts) + } + } + } +} + +func verifyTsTree(b *testing.B, ts *TestStruc) { + var ts0, ts1m, ts2m, ts1s, ts2s *TestStruc + ts0 = ts + + if benchDepth > 0 { + ts1m, ts1s = verifyCheckAndGet(b, ts0) + } + + if benchDepth > 1 { + ts2m, ts2s = verifyCheckAndGet(b, ts1m) + } + for _, tsx := range []*TestStruc{ts0, ts1m, ts2m, ts1s, ts2s} { + if tsx != nil { + verifyOneOne(b, tsx) + } + } +} + +func verifyCheckAndGet(b *testing.B, ts0 *TestStruc) (ts1m *TestStruc, ts1s *TestStruc) { + // if len(ts1m.Ms) <= 2 { + // logT(b, "Error: ts1m.Ms len should be > 2. Got: %v", len(ts1m.Ms)) + // b.FailNow() + // } + if len(ts0.Its) == 0 { + logT(b, "Error: ts0.Islice len should be > 0. Got: %v", len(ts0.Its)) + b.FailNow() + } + ts1m = ts0.Mtsptr["0"] + ts1s = ts0.Its[0] + if ts1m == nil || ts1s == nil { + logT(b, "Error: At benchDepth 1, No *TestStruc found") + b.FailNow() + } + return +} + +func verifyOneOne(b *testing.B, ts *TestStruc) { + if ts.I64slice[2] != int64(3) { + logT(b, "Error: Decode failed by checking values") + b.FailNow() + } +} + +func fnMsgpackEncodeFn(ts interface{}) (bs []byte, err error) { + err = NewEncoderBytes(&bs, testMsgpackH).Encode(ts) + return +} + +func fnMsgpackDecodeFn(buf []byte, ts interface{}) error { + return NewDecoderBytes(buf, testMsgpackH).Decode(ts) +} + +func fnBincEncodeFn(ts interface{}, sym AsSymbolFlag) (bs []byte, err error) { + tSym := testBincH.AsSymbols + testBincH.AsSymbols = sym + err = NewEncoderBytes(&bs, testBincH).Encode(ts) + testBincH.AsSymbols = tSym + return +} + +func fnBincDecodeFn(buf []byte, ts interface{}, sym AsSymbolFlag) (err error) { + tSym := testBincH.AsSymbols + testBincH.AsSymbols = sym + err = NewDecoderBytes(buf, testBincH).Decode(ts) + testBincH.AsSymbols = tSym + return +} + +func fnBincNoSymEncodeFn(ts interface{}) (bs []byte, err error) { + return fnBincEncodeFn(ts, AsSymbolNone) +} + +func fnBincNoSymDecodeFn(buf []byte, ts interface{}) error { + return fnBincDecodeFn(buf, ts, AsSymbolNone) +} + +func fnBincSymEncodeFn(ts interface{}) (bs []byte, err error) { + return fnBincEncodeFn(ts, AsSymbolAll) +} + +func fnBincSymDecodeFn(buf []byte, ts interface{}) error { + return fnBincDecodeFn(buf, ts, AsSymbolAll) +} + +func fnSimpleEncodeFn(ts interface{}) (bs []byte, err error) { + err = NewEncoderBytes(&bs, testSimpleH).Encode(ts) + return +} + +func fnSimpleDecodeFn(buf []byte, ts interface{}) error { + return NewDecoderBytes(buf, testSimpleH).Decode(ts) +} + +func fnGobEncodeFn(ts interface{}) ([]byte, error) { + bbuf := new(bytes.Buffer) + err := gob.NewEncoder(bbuf).Encode(ts) + return bbuf.Bytes(), err +} + +func fnGobDecodeFn(buf []byte, ts interface{}) error { + return gob.NewDecoder(bytes.NewBuffer(buf)).Decode(ts) +} + +func fnJsonEncodeFn(ts interface{}) ([]byte, error) { + return json.Marshal(ts) +} + +func fnJsonDecodeFn(buf []byte, ts interface{}) error { + return json.Unmarshal(buf, ts) +} + +func Benchmark__Msgpack____Encode(b *testing.B) { + fnBenchmarkEncode(b, "msgpack", benchTs, fnMsgpackEncodeFn) +} + +func Benchmark__Msgpack____Decode(b *testing.B) { + fnBenchmarkDecode(b, "msgpack", benchTs, fnMsgpackEncodeFn, fnMsgpackDecodeFn, fnBenchNewTs) +} + +func Benchmark__Binc_NoSym_Encode(b *testing.B) { + fnBenchmarkEncode(b, "binc", benchTs, fnBincNoSymEncodeFn) +} + +func Benchmark__Binc_NoSym_Decode(b *testing.B) { + fnBenchmarkDecode(b, "binc", benchTs, fnBincNoSymEncodeFn, fnBincNoSymDecodeFn, fnBenchNewTs) +} + +func Benchmark__Binc_Sym___Encode(b *testing.B) { + fnBenchmarkEncode(b, "binc", benchTs, fnBincSymEncodeFn) +} + +func Benchmark__Binc_Sym___Decode(b *testing.B) { + fnBenchmarkDecode(b, "binc", benchTs, fnBincSymEncodeFn, fnBincSymDecodeFn, fnBenchNewTs) +} + +func Benchmark__Simple____Encode(b *testing.B) { + fnBenchmarkEncode(b, "simple", benchTs, fnSimpleEncodeFn) +} + +func Benchmark__Simple____Decode(b *testing.B) { + fnBenchmarkDecode(b, "simple", benchTs, fnSimpleEncodeFn, fnSimpleDecodeFn, fnBenchNewTs) +} + +func Benchmark__Gob________Encode(b *testing.B) { + fnBenchmarkEncode(b, "gob", benchTs, fnGobEncodeFn) +} + +func Benchmark__Gob________Decode(b *testing.B) { + fnBenchmarkDecode(b, "gob", benchTs, fnGobEncodeFn, fnGobDecodeFn, fnBenchNewTs) +} + +func Benchmark__Json_______Encode(b *testing.B) { + fnBenchmarkEncode(b, "json", benchTs, fnJsonEncodeFn) +} + +func Benchmark__Json_______Decode(b *testing.B) { + fnBenchmarkDecode(b, "json", benchTs, fnJsonEncodeFn, fnJsonDecodeFn, fnBenchNewTs) +} |