Browse Source

codec: bench: streamline benchmarking

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
Ugorji Nwoke 6 years ago
parent
commit
0e7b41a418

+ 43 - 17
codec/bench/bench.sh

@@ -62,13 +62,33 @@ _gen() {
 # go test -tags "alltests x safe codecgen generated" -bench "CodecSuite or AllSuite or XSuite" -benchmem
 #
 
+_suite_tests() {
+    if [[ "${do_x}" = "1" ]]; then
+        printf "\n==== X Baseline ====\n"
+        go test -tags x -v
+    else
+        printf "\n==== Baseline ====\n"
+        go test -v
+    fi
+    if [[ "${do_x}" = "1" ]]; then
+        printf "\n==== X Generated ====\n"
+        go test -tags "x generated" -v
+    else
+        printf "\n==== Generated ====\n"
+        go test -tags "generated" -v
+    fi
+}
+
+_suite_tests_strip_file_line() {
+    # sed -e 's/^\([^a-zA-Z0-9]\+\)[a-zA-Z0-9_]\+\.go:[0-9]\+:/\1/'
+    sed -e 's/[a-zA-Z0-9_]*.go:[0-9]*://g'
+}
+
 _suite_any() {
     local x="$1"
     local g="$2"
     local b="$3"
-    shift
-    shift
-    shift
+    shift; shift; shift
     local a=( "" "safe"  "notfastpath" "notfastpath safe" "codecgen" "codecgen safe")
     if [[ "$g" = "g" ]]; then a=( "generated" "generated safe"); fi
     for i in "${a[@]}"; do
@@ -83,7 +103,7 @@ _suite_any() {
 #     for i in "${a[@]}"
 #     do
 #         echo ">>>> bench TAGS: '$t $i' SUITE: BenchmarkCodecXSuite"
-#         go test -run Nothing -tags "$t $i" -bench BenchmarkCodecXSuite -benchmem "$@"
+#         go test -tags "$t $i" -bench BenchmarkCodecXSuite -benchmem "$@"
 #     done
 # }
 
@@ -93,7 +113,7 @@ _suite_any() {
 #     for i in "${b[@]}"
 #     do
 #         echo ">>>> bench TAGS: '$t $i' SUITE: BenchmarkCodecXGenSuite"
-#         go test -run Nothing -tags "$t $i" -bench BenchmarkCodecXGenSuite -benchmem "$@"
+#         go test -tags "$t $i" -bench BenchmarkCodecXGenSuite -benchmem "$@"
 #     done
 # }
 
@@ -103,26 +123,26 @@ _suite_any() {
 #     for i in "${a[@]}"
 #     do
 #         echo ">>>> bench TAGS: '$t $i' SUITE: BenchmarkCodecQuickAllJsonSuite"
-#         go test -run Nothing -tags "$t $i" -bench BenchmarkCodecQuickAllJsonSuite -benchmem "$@"
+#         go test -tags "$t $i" -bench BenchmarkCodecQuickAllJsonSuite -benchmem "$@"
 #     done
 # }
 
 # _suite_very_quick_json() {
 #     # Quickly get numbers for json, stdjson, jsoniter and json (codecgen)"
 #     echo ">>>> very quick json bench"
-#     go test -run Nothing -tags "alltests x" -bench "__(Json|Std_Json|JsonIter)__" -benchmem "$@"
+#     go test -tags "alltests x" -bench "__(Json|Std_Json|JsonIter)__" -benchmem "$@"
 #     echo
-#     go test -run Nothing -tags "alltests codecgen" -bench "__Json____" -benchmem "$@"
+#     go test -tags "alltests codecgen" -bench "__Json____" -benchmem "$@"
 # }
 
 _suite_very_quick_json_via_suite() {
     # Quickly get numbers for json, stdjson, jsoniter and json (codecgen)"
     echo ">>>> very quick json bench"
     local prefix="BenchmarkCodecVeryQuickAllJsonSuite/json-all-bd1......../"
-    go test -run Nothing -tags "alltests x" -bench BenchmarkCodecVeryQuickAllJsonSuite -benchmem "$@" |
+    go test -tags "alltests x" -bench BenchmarkCodecVeryQuickAllJsonSuite -benchmem "$@" |
         sed -e "s+^$prefix++"
     echo "---- CODECGEN RESULTS ----"
-    go test -run Nothing -tags "alltests codecgen" -bench "__Json____" -benchmem "$@"
+    go test -tags "x generated" -bench "__(Json|Easyjson)__" -benchmem "$@"
 }
 
 _suite_very_quick_json_non_suite() {
@@ -130,9 +150,11 @@ _suite_very_quick_json_non_suite() {
     echo ">>>> very quick json bench"
     for j in "En" "De"; do
         echo "---- codecgen ----"
-        go test -run Nothing -tags "alltests x generated" -bench "__(Json|Easyjson)__.*${j}" -benchmem "$@"
+        # go test -tags "generated" -bench "__(Json|Easyjson)__.*${j}" -benchmem "$@"
+        go test -tags "x generated" -bench "__(Json|Easyjson)__.*${j}" -benchmem "$@"
         echo "---- no codecgen ----"
-        go test -run Nothing -tags "alltests x" -bench "__(Json|Std_Json|JsonIter)__.*${j}" -benchmem "$@"
+        # go test -tags "" -bench "__(Json|Std_Json|JsonIter)__.*${j}" -benchmem "$@"
+        go test -tags "x" -bench "__(Json|Std_Json|JsonIter)__.*${j}" -benchmem "$@"
         echo
     done
 }
@@ -141,20 +163,21 @@ _suite_very_quick_json_only_profile() {
     local a="${1:-Json}"
     shift
     local b="${1}"
-    go test -run Nothing -tags "alltests" -bench "__${a}__.*${b}" \
+    go test -tags "alltests" -bench "__${a}__.*${b}" \
        -benchmem -benchtime 4s \
        -cpuprofile cpu.out -memprofile mem.out -memprofilerate 1
 }
 
 _suite_trim_output() {
-    grep -v -E "^(goos:|goarch:|pkg:|PASS|ok)"
+    grep -v -E "^(goos:|goarch:|pkg:|PASS|ok|=== RUN|--- PASS)"
 }
 
 _usage() {
     printf "usage: bench.sh -[dcbsgjqp] for \n"
     printf "\t-d download\n"
     printf "\t-c code-generate\n"
-    printf "\t-bsgjqp run suite of tests for [codec, codec and x, codec and x (generated), json, json-quick, json-profile]\n"
+    printf "\t-tx tests (show stats for each format and whether encoded == decoded); if x, do external also\n"
+    printf "\t-bsgjqp run test suite for [codec, codec and x, codec and x (generated), json, json-quick, json-profile]\n"
 }
 
 _main() {
@@ -164,15 +187,17 @@ _main() {
         return 1
     fi
     local args=()
-    while getopts "dcbsjqpg" flag
+    local do_x="0"
+    while getopts "dcbsjqpgtx" flag
     do
         case "$flag" in
-            d|c|b|s|j|q|p|g) args+=( "$flag" ) ;;
+            d|c|b|s|j|q|p|g|t|x) args+=( "$flag" ) ;;
             *) _usage; return 1 ;;
         esac
     done
     shift "$((OPTIND-1))"
     
+    [[ " ${args[*]} " == *"x"* ]] && do_x="1"
     [[ " ${args[*]} " == *"d"* ]] && _go_get "$@"
     [[ " ${args[*]} " == *"c"* ]] && _gen "$@"
     [[ " ${args[*]} " == *"b"* ]] && _suite_any - - BenchmarkCodecSuite "$@" | _suite_trim_output
@@ -181,6 +206,7 @@ _main() {
     [[ " ${args[*]} " == *"j"* ]] && _suite_any x - BenchmarkCodecQuickAllJsonSuite "$@" | _suite_trim_output
     [[ " ${args[*]} " == *"q"* ]] && _suite_very_quick_json_non_suite "$@" | _suite_trim_output
     [[ " ${args[*]} " == *"p"* ]] && _suite_very_quick_json_only_profile "$@" | _suite_trim_output
+    [[ " ${args[*]} " == *"t"* ]] && _suite_tests "$@" | _suite_trim_output | _suite_tests_strip_file_line
     true
     # shift $((OPTIND-1))
 }

+ 66 - 180
codec/bench/bench_test.go

@@ -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)
-}

+ 109 - 0
codec/bench/codec_bench_test.go

@@ -0,0 +1,109 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+	"testing"
+)
+
+func init() {
+	testPreInitFns = append(testPreInitFns, codecBenchPreInit)
+	// testPostInitFns = append(testPostInitFns, codecbenchPostInit)
+}
+
+func codecBenchPreInit() {
+	benchCheckers = append(benchCheckers,
+		benchChecker{"msgpack", fnMsgpackEncodeFn, fnMsgpackDecodeFn},
+		benchChecker{"binc", fnBincEncodeFn, fnBincDecodeFn},
+		benchChecker{"simple", fnSimpleEncodeFn, fnSimpleDecodeFn},
+		benchChecker{"cbor", fnCborEncodeFn, fnCborDecodeFn},
+		benchChecker{"json", fnJsonEncodeFn, fnJsonDecodeFn},
+	)
+}
+
+// ------------ 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)
+}
+
+// ----------- ENCODE ------------------
+
+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)
+}
+
+// ----------- 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)
+}

+ 93 - 0
codec/bench/stdlib_bench_test.go

@@ -0,0 +1,93 @@
+// +build !generated
+
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/json"
+	"encoding/xml"
+	"testing"
+)
+
+func init() {
+	testPreInitFns = append(testPreInitFns, stdlibBenchPreInit)
+	// testPostInitFns = append(testPostInitFns, codecbenchPostInit)
+}
+
+func stdlibBenchPreInit() {
+	benchCheckers = append(benchCheckers,
+		benchChecker{"std-json", fnStdJsonEncodeFn, fnStdJsonDecodeFn},
+		benchChecker{"gob", fnGobEncodeFn, fnGobDecodeFn},
+		benchChecker{"std-xml", fnStdXmlEncodeFn, fnStdXmlDecodeFn},
+	)
+}
+
+// ------------ tests below
+
+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)
+}
+
+// ----------- ENCODE ------------------
+
+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__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)
+}

+ 1 - 1
codec/bench/x_bench_gen_test.go

@@ -42,7 +42,7 @@ func benchXGenPreInit() {
 
 func fnEasyjsonEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
 	ts2, ok := ts.(easyjson.Marshaler)
-	if !ok {
+	if !ok || ts2 == nil {
 		return nil, errors.New("easyjson: input is not a easyjson.Marshaler")
 	}
 	if testUseIoEncDec >= 0 {

+ 1 - 0
codec/bench/x_bench_test.go

@@ -1,4 +1,5 @@
 // +build x
+// +build !generated
 
 // Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
 // Use of this source code is governed by a MIT license found in the LICENSE file.

+ 3 - 14
codec/bench/z_all_bench_test.go

@@ -1,9 +1,9 @@
+// +build alltests
+// +build go1.7
+
 // Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
 // Use of this source code is governed by a MIT license found in the LICENSE file.
 
-// +build alltests codecgen
-// +build go1.7
-
 package codec
 
 // see notes in z_all_test.go
@@ -44,11 +44,6 @@ func benchmarkGroupReset() {
 	testMapStringKeyOnly = benchmarkGroupSave.testMapStringKeyOnly
 }
 
-func benchmarkDivider() {
-	// logTv(nil, "-------------------------------\n")
-	println()
-}
-
 func benchmarkOneFn(fns []func(*testing.B)) func(*testing.B) {
 	switch len(fns) {
 	case 0:
@@ -160,18 +155,12 @@ func benchmarkCodecGroup(t *testing.B) {
 	t.Run("Benchmark__Simple_____Encode", Benchmark__Simple_____Encode)
 	t.Run("Benchmark__Cbor_______Encode", Benchmark__Cbor_______Encode)
 	t.Run("Benchmark__Json_______Encode", Benchmark__Json_______Encode)
-	t.Run("Benchmark__Std_Json___Encode", Benchmark__Std_Json___Encode)
-	t.Run("Benchmark__Gob________Encode", Benchmark__Gob________Encode)
-	// t.Run("Benchmark__Std_Xml____Encode", Benchmark__Std_Xml____Encode)
 	benchmarkDivider()
 	t.Run("Benchmark__Msgpack____Decode", Benchmark__Msgpack____Decode)
 	t.Run("Benchmark__Binc_______Decode", Benchmark__Binc_______Decode)
 	t.Run("Benchmark__Simple_____Decode", Benchmark__Simple_____Decode)
 	t.Run("Benchmark__Cbor_______Decode", Benchmark__Cbor_______Decode)
 	t.Run("Benchmark__Json_______Decode", Benchmark__Json_______Decode)
-	t.Run("Benchmark__Std_Json___Decode", Benchmark__Std_Json___Decode)
-	t.Run("Benchmark__Gob________Decode", Benchmark__Gob________Decode)
-	// t.Run("Benchmark__Std_Xml____Decode", Benchmark__Std_Xml____Decode)
 }
 
 func BenchmarkCodecSuite(t *testing.B) { benchmarkSuite(t, benchmarkCodecGroup) }

+ 23 - 0
codec/bench/z_all_stdlib_bench_test.go

@@ -0,0 +1,23 @@
+// +build alltests
+// +build go1.7
+// +build !generated
+
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import "testing"
+
+func benchmarkStdlibGroup(t *testing.B) {
+	benchmarkDivider()
+	t.Run("Benchmark__Std_Json___Encode", Benchmark__Std_Json___Encode)
+	t.Run("Benchmark__Gob________Encode", Benchmark__Gob________Encode)
+	// t.Run("Benchmark__Std_Xml____Encode", Benchmark__Std_Xml____Encode)
+	benchmarkDivider()
+	t.Run("Benchmark__Std_Json___Decode", Benchmark__Std_Json___Decode)
+	t.Run("Benchmark__Gob________Decode", Benchmark__Gob________Decode)
+	// t.Run("Benchmark__Std_Xml____Decode", Benchmark__Std_Xml____Decode)
+}
+
+func BenchmarkStdlibSuite(t *testing.B) { benchmarkSuite(t, benchmarkStdlibGroup) }

+ 4 - 22
codec/bench/z_all_x_bench_gen_test.go

@@ -1,11 +1,11 @@
-// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
-// Use of this source code is governed by a MIT license found in the LICENSE file.
-
 // +build alltests
-// +build x
 // +build go1.7
+// +build x
 // +build generated
 
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
 package codec
 
 // see notes in z_all_bench_test.go
@@ -19,18 +19,9 @@ func benchmarkCodecXGenGroup(t *testing.B) {
 	t.Run("Benchmark__Simple_____Encode", Benchmark__Simple_____Encode)
 	t.Run("Benchmark__Cbor_______Encode", Benchmark__Cbor_______Encode)
 	t.Run("Benchmark__Json_______Encode", Benchmark__Json_______Encode)
-	t.Run("Benchmark__Std_Json___Encode", Benchmark__Std_Json___Encode)
-	t.Run("Benchmark__Gob________Encode", Benchmark__Gob________Encode)
-	t.Run("Benchmark__JsonIter___Encode", Benchmark__JsonIter___Encode)
-	t.Run("Benchmark__Bson_______Encode", Benchmark__Bson_______Encode)
-	t.Run("Benchmark__Mgobson____Encode", Benchmark__Mgobson____Encode)
-	t.Run("Benchmark__VMsgpack___Encode", Benchmark__VMsgpack___Encode)
 	t.Run("Benchmark__Msgp_______Encode", Benchmark__Msgp_______Encode)
 	t.Run("Benchmark__Easyjson___Encode", Benchmark__Easyjson___Encode)
 	t.Run("Benchmark__Ffjson_____Encode", Benchmark__Ffjson_____Encode)
-	// t.Run("Benchmark__Gcbor______Encode", Benchmark__Gcbor______Encode)
-	// t.Run("Benchmark__Xdr________Encode", Benchmark__Xdr________Encode)
-	t.Run("Benchmark__Sereal_____Encode", Benchmark__Sereal_____Encode)
 
 	benchmarkDivider()
 	t.Run("Benchmark__Msgpack____Decode", Benchmark__Msgpack____Decode)
@@ -38,18 +29,9 @@ func benchmarkCodecXGenGroup(t *testing.B) {
 	t.Run("Benchmark__Simple_____Decode", Benchmark__Simple_____Decode)
 	t.Run("Benchmark__Cbor_______Decode", Benchmark__Cbor_______Decode)
 	t.Run("Benchmark__Json_______Decode", Benchmark__Json_______Decode)
-	t.Run("Benchmark__Std_Json___Decode", Benchmark__Std_Json___Decode)
-	t.Run("Benchmark__Gob________Decode", Benchmark__Gob________Decode)
-	t.Run("Benchmark__JsonIter___Decode", Benchmark__JsonIter___Decode)
-	t.Run("Benchmark__Bson_______Decode", Benchmark__Bson_______Decode)
-	t.Run("Benchmark__Mgobson____Decode", Benchmark__Mgobson____Decode)
-	// t.Run("Benchmark__VMsgpack___Decode", Benchmark__VMsgpack___Decode)
 	t.Run("Benchmark__Msgp_______Decode", Benchmark__Msgp_______Decode)
 	t.Run("Benchmark__Easyjson___Decode", Benchmark__Easyjson___Decode)
 	t.Run("Benchmark__Ffjson_____Decode", Benchmark__Ffjson_____Decode)
-	// t.Run("Benchmark__Gcbor______Decode", Benchmark__Gcbor______Decode)
-	// t.Run("Benchmark__Xdr________Decode", Benchmark__Xdr________Decode)
-	// t.Run("Benchmark__Sereal_____Decode", Benchmark__Sereal_____Decode)
 }
 
 func BenchmarkCodecXGenSuite(t *testing.B) { benchmarkSuite(t, benchmarkCodecXGenGroup) }

+ 5 - 4
codec/bench/z_all_x_bench_test.go

@@ -1,9 +1,10 @@
-// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
-// Use of this source code is governed by a MIT license found in the LICENSE file.
-
 // +build alltests
-// +build x
 // +build go1.7
+// +build x
+// +build !generated
+
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
 
 package codec