aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json/bench_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding/json/bench_test.go')
-rw-r--r--src/encoding/json/bench_test.go68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/encoding/json/bench_test.go b/src/encoding/json/bench_test.go
index 42439eb705..bd322db2e6 100644
--- a/src/encoding/json/bench_test.go
+++ b/src/encoding/json/bench_test.go
@@ -13,9 +13,14 @@ package json
import (
"bytes"
"compress/gzip"
+ "fmt"
+ "internal/testenv"
"io/ioutil"
"os"
+ "reflect"
+ "runtime"
"strings"
+ "sync"
"testing"
)
@@ -265,3 +270,66 @@ func BenchmarkUnmapped(b *testing.B) {
}
})
}
+
+func BenchmarkTypeFieldsCache(b *testing.B) {
+ var maxTypes int = 1e6
+ if testenv.Builder() != "" {
+ maxTypes = 1e3 // restrict cache sizes on builders
+ }
+
+ // Dynamically generate many new types.
+ types := make([]reflect.Type, maxTypes)
+ fs := []reflect.StructField{{
+ Type: reflect.TypeOf(""),
+ Index: []int{0},
+ }}
+ for i := range types {
+ fs[0].Name = fmt.Sprintf("TypeFieldsCache%d", i)
+ types[i] = reflect.StructOf(fs)
+ }
+
+ // clearClear clears the cache. Other JSON operations, must not be running.
+ clearCache := func() {
+ fieldCache = sync.Map{}
+ }
+
+ // MissTypes tests the performance of repeated cache misses.
+ // This measures the time to rebuild a cache of size nt.
+ for nt := 1; nt <= maxTypes; nt *= 10 {
+ ts := types[:nt]
+ b.Run(fmt.Sprintf("MissTypes%d", nt), func(b *testing.B) {
+ nc := runtime.GOMAXPROCS(0)
+ for i := 0; i < b.N; i++ {
+ clearCache()
+ var wg sync.WaitGroup
+ for j := 0; j < nc; j++ {
+ wg.Add(1)
+ go func(j int) {
+ for _, t := range ts[(j*len(ts))/nc : ((j+1)*len(ts))/nc] {
+ cachedTypeFields(t)
+ }
+ wg.Done()
+ }(j)
+ }
+ wg.Wait()
+ }
+ })
+ }
+
+ // HitTypes tests the performance of repeated cache hits.
+ // This measures the average time of each cache lookup.
+ for nt := 1; nt <= maxTypes; nt *= 10 {
+ // Pre-warm a cache of size nt.
+ clearCache()
+ for _, t := range types[:nt] {
+ cachedTypeFields(t)
+ }
+ b.Run(fmt.Sprintf("HitTypes%d", nt), func(b *testing.B) {
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ cachedTypeFields(types[0])
+ }
+ })
+ })
+ }
+}