|
|
@@ -3,11 +3,37 @@
|
|
|
|
|
|
package codec
|
|
|
|
|
|
+// bench_test is the "helper" file for all benchmarking tests.
|
|
|
+//
|
|
|
+// There are also benchmarks which depend on just codec and the stdlib,
|
|
|
+// and benchmarks which depend on external libraries.
|
|
|
+// It is an explicit goal that you can run benchmarks without external
|
|
|
+// dependencies (which is why the 'x' build tag was explicitly introduced).
|
|
|
+//
|
|
|
+// There are 2 ways of running tests:
|
|
|
+// - generated
|
|
|
+// - not generated
|
|
|
+//
|
|
|
+// Consequently, we have 4 groups:
|
|
|
+// - codec_bench (gen, !gen)
|
|
|
+// - stdlib_bench (!gen only)
|
|
|
+// - x_bench (!gen only)
|
|
|
+// - x_bench_gen (gen only)
|
|
|
+//
|
|
|
+// We also have 4 matching suite files.
|
|
|
+// - z_all_bench (rename later to z_all_codec_bench???)
|
|
|
+// - z_all_stdlib_bench
|
|
|
+// - z_all_x_bench
|
|
|
+// - z_all_x_bench_gen
|
|
|
+//
|
|
|
+// Finally, we have a single test (TestBenchInit) that
|
|
|
+// will log information about whether each format can
|
|
|
+// encode or not, how long to encode (unscientifically),
|
|
|
+// and the encode size.
|
|
|
+//
|
|
|
+// This test MUST be run always, as it calls init() internally
|
|
|
+
|
|
|
import (
|
|
|
- "bytes"
|
|
|
- "encoding/gob"
|
|
|
- "encoding/json"
|
|
|
- "encoding/xml"
|
|
|
"reflect"
|
|
|
"runtime"
|
|
|
"testing"
|
|
|
@@ -17,19 +43,16 @@ import (
|
|
|
// Sample way to run:
|
|
|
// go test -bi -bv -bd=1 -benchmem -bench=.
|
|
|
|
|
|
-const benchUnscientificRes = true
|
|
|
-const benchVerify = true
|
|
|
-
|
|
|
-func init() {
|
|
|
- testPreInitFns = append(testPreInitFns, benchPreInit)
|
|
|
- testPostInitFns = append(testPostInitFns, benchPostInit)
|
|
|
-}
|
|
|
+const (
|
|
|
+ benchUnscientificRes = true
|
|
|
+ benchVerify = true
|
|
|
+ benchRecover = true
|
|
|
+ benchShowJsonOnError = true
|
|
|
+)
|
|
|
|
|
|
var (
|
|
|
- benchTs *TestStruc
|
|
|
-
|
|
|
- approxSize int
|
|
|
-
|
|
|
+ benchTs *TestStruc
|
|
|
+ approxSize int
|
|
|
benchCheckers []benchChecker
|
|
|
)
|
|
|
|
|
|
@@ -43,8 +66,9 @@ type benchChecker struct {
|
|
|
decodefn benchDecFn
|
|
|
}
|
|
|
|
|
|
-func benchReinit() {
|
|
|
- benchCheckers = nil
|
|
|
+func init() {
|
|
|
+ testPreInitFns = append(testPreInitFns, benchPreInit)
|
|
|
+ // testPostInitFns = append(testPostInitFns, codecbenchPostInit)
|
|
|
}
|
|
|
|
|
|
func benchPreInit() {
|
|
|
@@ -54,27 +78,26 @@ func benchPreInit() {
|
|
|
// if bytesLen < approxSize {
|
|
|
// bytesLen = approxSize
|
|
|
// }
|
|
|
+}
|
|
|
|
|
|
- benchCheckers = append(benchCheckers,
|
|
|
- benchChecker{"msgpack", fnMsgpackEncodeFn, fnMsgpackDecodeFn},
|
|
|
- benchChecker{"binc", fnBincEncodeFn, fnBincDecodeFn},
|
|
|
- benchChecker{"simple", fnSimpleEncodeFn, fnSimpleDecodeFn},
|
|
|
- benchChecker{"cbor", fnCborEncodeFn, fnCborDecodeFn},
|
|
|
- benchChecker{"json", fnJsonEncodeFn, fnJsonDecodeFn},
|
|
|
- benchChecker{"std-json", fnStdJsonEncodeFn, fnStdJsonDecodeFn},
|
|
|
- benchChecker{"gob", fnGobEncodeFn, fnGobDecodeFn},
|
|
|
- benchChecker{"std-xml", fnStdXmlEncodeFn, fnStdXmlDecodeFn},
|
|
|
- )
|
|
|
+func benchReinit() {
|
|
|
+ benchCheckers = nil
|
|
|
}
|
|
|
|
|
|
-func benchPostInit() {
|
|
|
- // if benchDoInitBench {
|
|
|
- // runBenchInit()
|
|
|
- // }
|
|
|
+func benchmarkDivider() {
|
|
|
+ // logTv(nil, "-------------------------------\n")
|
|
|
+ println()
|
|
|
}
|
|
|
|
|
|
+// func Test0(t *testing.T) {
|
|
|
+// testOnce.Do(testInitAll)
|
|
|
+// }
|
|
|
+
|
|
|
func TestBenchInit(t *testing.T) {
|
|
|
testOnce.Do(testInitAll)
|
|
|
+ if !testing.Verbose() {
|
|
|
+ return
|
|
|
+ }
|
|
|
// logTv(t, "..............................................")
|
|
|
logT(t, "BENCHMARK INIT: %v", time.Now())
|
|
|
// logTv(t, "To run full benchmark comparing encodings, use: \"go test -bench=.\"")
|
|
|
@@ -108,8 +131,10 @@ func fnBenchNewTs() interface{} {
|
|
|
// const benchCheckDoDeepEqual = false
|
|
|
|
|
|
func benchRecoverPanic(t interface{}) {
|
|
|
- if r := recover(); r != nil {
|
|
|
- logT(t, "(recovered) panic: %v\n", r)
|
|
|
+ if benchRecover {
|
|
|
+ if r := recover(); r != nil {
|
|
|
+ logT(t, "(recovered) panic: %v\n", r)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -117,7 +142,7 @@ func doBenchCheck(t *testing.T, name string, encfn benchEncFn, decfn benchDecFn)
|
|
|
// if benchUnscientificRes {
|
|
|
// logTv(t, "-------------- %s ----------------", name)
|
|
|
// }
|
|
|
- defer benchRecoverPanic(nil)
|
|
|
+ defer benchRecoverPanic(t)
|
|
|
runtime.GC()
|
|
|
tnow := time.Now()
|
|
|
buf, err := encfn(benchTs, nil)
|
|
|
@@ -146,6 +171,13 @@ func doBenchCheck(t *testing.T, name string, encfn benchEncFn, decfn benchDecFn)
|
|
|
logT(t, "\t%10s: len: %d bytes,\t encode: %v,\t decode: %v,\tencoded == decoded", name, encLen, encDur, decDur)
|
|
|
} else {
|
|
|
logT(t, "\t%10s: len: %d bytes,\t encode: %v,\t decode: %v,\tencoded != decoded: %v", name, encLen, encDur, decDur, err)
|
|
|
+ // if benchShowJsonOnError && strings.Contains(name, "json") {
|
|
|
+ // fmt.Printf("\n\n%s\n\n", buf)
|
|
|
+ // //fmt.Printf("\n\n%#v\n\n", benchTs)
|
|
|
+ // //fmt.Printf("\n\n%#v\n\n", &ts2)
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+
|
|
|
// if strings.Contains(name, "json") {
|
|
|
// println(">>>>>")
|
|
|
// f1, _ := os.Create("1.out")
|
|
|
@@ -228,149 +260,3 @@ func fnBenchmarkDecode(b *testing.B, encName string, ts interface{},
|
|
|
failT(b, "Error decoding into new TestStruc: %s: %v", encName, err)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-// ------------ tests below
|
|
|
-
|
|
|
-func fnMsgpackEncodeFn(ts interface{}, bsIn []byte) (bs []byte, err error) {
|
|
|
- return sTestCodecEncode(ts, bsIn, fnBenchmarkByteBuf, testMsgpackH, &testMsgpackH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnMsgpackDecodeFn(buf []byte, ts interface{}) error {
|
|
|
- return sTestCodecDecode(buf, ts, testMsgpackH, &testMsgpackH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnBincEncodeFn(ts interface{}, bsIn []byte) (bs []byte, err error) {
|
|
|
- return sTestCodecEncode(ts, bsIn, fnBenchmarkByteBuf, testBincH, &testBincH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnBincDecodeFn(buf []byte, ts interface{}) error {
|
|
|
- return sTestCodecDecode(buf, ts, testBincH, &testBincH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnSimpleEncodeFn(ts interface{}, bsIn []byte) (bs []byte, err error) {
|
|
|
- return sTestCodecEncode(ts, bsIn, fnBenchmarkByteBuf, testSimpleH, &testSimpleH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnSimpleDecodeFn(buf []byte, ts interface{}) error {
|
|
|
- return sTestCodecDecode(buf, ts, testSimpleH, &testSimpleH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnCborEncodeFn(ts interface{}, bsIn []byte) (bs []byte, err error) {
|
|
|
- return sTestCodecEncode(ts, bsIn, fnBenchmarkByteBuf, testCborH, &testCborH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnCborDecodeFn(buf []byte, ts interface{}) error {
|
|
|
- return sTestCodecDecode(buf, ts, testCborH, &testCborH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnJsonEncodeFn(ts interface{}, bsIn []byte) (bs []byte, err error) {
|
|
|
- return sTestCodecEncode(ts, bsIn, fnBenchmarkByteBuf, testJsonH, &testJsonH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnJsonDecodeFn(buf []byte, ts interface{}) error {
|
|
|
- return sTestCodecDecode(buf, ts, testJsonH, &testJsonH.BasicHandle)
|
|
|
-}
|
|
|
-
|
|
|
-func fnGobEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
|
|
|
- buf := fnBenchmarkByteBuf(bsIn)
|
|
|
- err := gob.NewEncoder(buf).Encode(ts)
|
|
|
- return buf.Bytes(), err
|
|
|
-}
|
|
|
-
|
|
|
-func fnGobDecodeFn(buf []byte, ts interface{}) error {
|
|
|
- return gob.NewDecoder(bytes.NewReader(buf)).Decode(ts)
|
|
|
-}
|
|
|
-
|
|
|
-func fnStdXmlEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
|
|
|
- buf := fnBenchmarkByteBuf(bsIn)
|
|
|
- err := xml.NewEncoder(buf).Encode(ts)
|
|
|
- return buf.Bytes(), err
|
|
|
-}
|
|
|
-
|
|
|
-func fnStdXmlDecodeFn(buf []byte, ts interface{}) error {
|
|
|
- return xml.NewDecoder(bytes.NewReader(buf)).Decode(ts)
|
|
|
-}
|
|
|
-
|
|
|
-func fnStdJsonEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
|
|
|
- if testUseIoEncDec >= 0 {
|
|
|
- buf := fnBenchmarkByteBuf(bsIn)
|
|
|
- err := json.NewEncoder(buf).Encode(ts)
|
|
|
- return buf.Bytes(), err
|
|
|
- }
|
|
|
- return json.Marshal(ts)
|
|
|
-}
|
|
|
-
|
|
|
-func fnStdJsonDecodeFn(buf []byte, ts interface{}) error {
|
|
|
- if testUseIoEncDec >= 0 {
|
|
|
- return json.NewDecoder(bytes.NewReader(buf)).Decode(ts)
|
|
|
- }
|
|
|
- return json.Unmarshal(buf, ts)
|
|
|
-}
|
|
|
-
|
|
|
-// ----------- DECODE ------------------
|
|
|
-
|
|
|
-func Benchmark__Msgpack____Encode(b *testing.B) {
|
|
|
- fnBenchmarkEncode(b, "msgpack", benchTs, fnMsgpackEncodeFn)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Binc_______Encode(b *testing.B) {
|
|
|
- fnBenchmarkEncode(b, "binc", benchTs, fnBincEncodeFn)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Simple_____Encode(b *testing.B) {
|
|
|
- fnBenchmarkEncode(b, "simple", benchTs, fnSimpleEncodeFn)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Cbor_______Encode(b *testing.B) {
|
|
|
- fnBenchmarkEncode(b, "cbor", benchTs, fnCborEncodeFn)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Json_______Encode(b *testing.B) {
|
|
|
- fnBenchmarkEncode(b, "json", benchTs, fnJsonEncodeFn)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Std_Json___Encode(b *testing.B) {
|
|
|
- fnBenchmarkEncode(b, "std-json", benchTs, fnStdJsonEncodeFn)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Gob________Encode(b *testing.B) {
|
|
|
- fnBenchmarkEncode(b, "gob", benchTs, fnGobEncodeFn)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Std_Xml____Encode(b *testing.B) {
|
|
|
- fnBenchmarkEncode(b, "std-xml", benchTs, fnStdXmlEncodeFn)
|
|
|
-}
|
|
|
-
|
|
|
-// ----------- DECODE ------------------
|
|
|
-
|
|
|
-func Benchmark__Msgpack____Decode(b *testing.B) {
|
|
|
- fnBenchmarkDecode(b, "msgpack", benchTs, fnMsgpackEncodeFn, fnMsgpackDecodeFn, fnBenchNewTs)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Binc_______Decode(b *testing.B) {
|
|
|
- fnBenchmarkDecode(b, "binc", benchTs, fnBincEncodeFn, fnBincDecodeFn, fnBenchNewTs)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Simple_____Decode(b *testing.B) {
|
|
|
- fnBenchmarkDecode(b, "simple", benchTs, fnSimpleEncodeFn, fnSimpleDecodeFn, fnBenchNewTs)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Cbor_______Decode(b *testing.B) {
|
|
|
- fnBenchmarkDecode(b, "cbor", benchTs, fnCborEncodeFn, fnCborDecodeFn, fnBenchNewTs)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Json_______Decode(b *testing.B) {
|
|
|
- fnBenchmarkDecode(b, "json", benchTs, fnJsonEncodeFn, fnJsonDecodeFn, fnBenchNewTs)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Std_Json___Decode(b *testing.B) {
|
|
|
- fnBenchmarkDecode(b, "std-json", benchTs, fnStdJsonEncodeFn, fnStdJsonDecodeFn, fnBenchNewTs)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Gob________Decode(b *testing.B) {
|
|
|
- fnBenchmarkDecode(b, "gob", benchTs, fnGobEncodeFn, fnGobDecodeFn, fnBenchNewTs)
|
|
|
-}
|
|
|
-
|
|
|
-func Benchmark__Std_Xml____Decode(b *testing.B) {
|
|
|
- fnBenchmarkDecode(b, "std-xml", benchTs, fnStdXmlEncodeFn, fnStdXmlDecodeFn, fnBenchNewTs)
|
|
|
-}
|