Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
bench_test.go584 linesDownload Raw Back to json
1// Copyright 2011 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4 5// Large data benchmark.6// The JSON data is a summary of agl's changes in the7// go, webkit, and chromium open source projects.8// We benchmark converting between the JSON form9// and in-memory data structures.10 11//go:build !goexperiment.jsonv212 13package json14 15import (16	"bytes"17	"fmt"18	"internal/testenv"19	"internal/zstd"20	"io"21	"os"22	"reflect"23	"regexp"24	"runtime"25	"strings"26	"sync"27	"testing"28)29 30type codeResponse struct {31	Tree     *codeNode `json:"tree"`32	Username string    `json:"username"`33}34 35type codeNode struct {36	Name     string      `json:"name"`37	Kids     []*codeNode `json:"kids"`38	CLWeight float64     `json:"cl_weight"`39	Touches  int         `json:"touches"`40	MinT     int64       `json:"min_t"`41	MaxT     int64       `json:"max_t"`42	MeanT    int64       `json:"mean_t"`43}44 45var codeJSON []byte46var codeStruct codeResponse47 48func codeInit() {49	f, err := os.Open("internal/jsontest/testdata/golang_source.json.zst")50	if err != nil {51		panic(err)52	}53	defer f.Close()54	gz := zstd.NewReader(f)55	data, err := io.ReadAll(gz)56	if err != nil {57		panic(err)58	}59 60	codeJSON = data61 62	if err := Unmarshal(codeJSON, &codeStruct); err != nil {63		panic("unmarshal code.json: " + err.Error())64	}65 66	if data, err = Marshal(&codeStruct); err != nil {67		panic("marshal code.json: " + err.Error())68	}69 70	if !bytes.Equal(data, codeJSON) {71		println("different lengths", len(data), len(codeJSON))72		for i := 0; i < len(data) && i < len(codeJSON); i++ {73			if data[i] != codeJSON[i] {74				println("re-marshal: changed at byte", i)75				println("orig: ", string(codeJSON[i-10:i+10]))76				println("new: ", string(data[i-10:i+10]))77				break78			}79		}80		panic("re-marshal code.json: different result")81	}82}83 84func BenchmarkCodeEncoder(b *testing.B) {85	b.ReportAllocs()86	if codeJSON == nil {87		b.StopTimer()88		codeInit()89		b.StartTimer()90	}91	b.RunParallel(func(pb *testing.PB) {92		enc := NewEncoder(io.Discard)93		for pb.Next() {94			if err := enc.Encode(&codeStruct); err != nil {95				b.Fatalf("Encode error: %v", err)96			}97		}98	})99	b.SetBytes(int64(len(codeJSON)))100}101 102func BenchmarkCodeEncoderError(b *testing.B) {103	b.ReportAllocs()104	if codeJSON == nil {105		b.StopTimer()106		codeInit()107		b.StartTimer()108	}109 110	// Trigger an error in Marshal with cyclic data.111	type Dummy struct {112		Name string113		Next *Dummy114	}115	dummy := Dummy{Name: "Dummy"}116	dummy.Next = &dummy117 118	b.RunParallel(func(pb *testing.PB) {119		enc := NewEncoder(io.Discard)120		for pb.Next() {121			if err := enc.Encode(&codeStruct); err != nil {122				b.Fatalf("Encode error: %v", err)123			}124			if _, err := Marshal(dummy); err == nil {125				b.Fatal("Marshal error: got nil, want non-nil")126			}127		}128	})129	b.SetBytes(int64(len(codeJSON)))130}131 132func BenchmarkCodeMarshal(b *testing.B) {133	b.ReportAllocs()134	if codeJSON == nil {135		b.StopTimer()136		codeInit()137		b.StartTimer()138	}139	b.RunParallel(func(pb *testing.PB) {140		for pb.Next() {141			if _, err := Marshal(&codeStruct); err != nil {142				b.Fatalf("Marshal error: %v", err)143			}144		}145	})146	b.SetBytes(int64(len(codeJSON)))147}148 149func BenchmarkCodeMarshalError(b *testing.B) {150	b.ReportAllocs()151	if codeJSON == nil {152		b.StopTimer()153		codeInit()154		b.StartTimer()155	}156 157	// Trigger an error in Marshal with cyclic data.158	type Dummy struct {159		Name string160		Next *Dummy161	}162	dummy := Dummy{Name: "Dummy"}163	dummy.Next = &dummy164 165	b.RunParallel(func(pb *testing.PB) {166		for pb.Next() {167			if _, err := Marshal(&codeStruct); err != nil {168				b.Fatalf("Marshal error: %v", err)169			}170			if _, err := Marshal(dummy); err == nil {171				b.Fatal("Marshal error: got nil, want non-nil")172			}173		}174	})175	b.SetBytes(int64(len(codeJSON)))176}177 178func benchMarshalBytes(n int) func(*testing.B) {179	sample := []byte("hello world")180	// Use a struct pointer, to avoid an allocation when passing it as an181	// interface parameter to Marshal.182	v := &struct {183		Bytes []byte184	}{185		bytes.Repeat(sample, (n/len(sample))+1)[:n],186	}187	return func(b *testing.B) {188		for i := 0; i < b.N; i++ {189			if _, err := Marshal(v); err != nil {190				b.Fatalf("Marshal error: %v", err)191			}192		}193	}194}195 196func benchMarshalBytesError(n int) func(*testing.B) {197	sample := []byte("hello world")198	// Use a struct pointer, to avoid an allocation when passing it as an199	// interface parameter to Marshal.200	v := &struct {201		Bytes []byte202	}{203		bytes.Repeat(sample, (n/len(sample))+1)[:n],204	}205 206	// Trigger an error in Marshal with cyclic data.207	type Dummy struct {208		Name string209		Next *Dummy210	}211	dummy := Dummy{Name: "Dummy"}212	dummy.Next = &dummy213 214	return func(b *testing.B) {215		for i := 0; i < b.N; i++ {216			if _, err := Marshal(v); err != nil {217				b.Fatalf("Marshal error: %v", err)218			}219			if _, err := Marshal(dummy); err == nil {220				b.Fatal("Marshal error: got nil, want non-nil")221			}222		}223	}224}225 226func BenchmarkMarshalBytes(b *testing.B) {227	b.ReportAllocs()228	// 32 fits within encodeState.scratch.229	b.Run("32", benchMarshalBytes(32))230	// 256 doesn't fit in encodeState.scratch, but is small enough to231	// allocate and avoid the slower base64.NewEncoder.232	b.Run("256", benchMarshalBytes(256))233	// 4096 is large enough that we want to avoid allocating for it.234	b.Run("4096", benchMarshalBytes(4096))235}236 237func BenchmarkMarshalBytesError(b *testing.B) {238	b.ReportAllocs()239	// 32 fits within encodeState.scratch.240	b.Run("32", benchMarshalBytesError(32))241	// 256 doesn't fit in encodeState.scratch, but is small enough to242	// allocate and avoid the slower base64.NewEncoder.243	b.Run("256", benchMarshalBytesError(256))244	// 4096 is large enough that we want to avoid allocating for it.245	b.Run("4096", benchMarshalBytesError(4096))246}247 248func BenchmarkMarshalMap(b *testing.B) {249	b.ReportAllocs()250	m := map[string]int{251		"key3": 3,252		"key2": 2,253		"key1": 1,254	}255	b.RunParallel(func(pb *testing.PB) {256		for pb.Next() {257			if _, err := Marshal(m); err != nil {258				b.Fatal("Marshal:", err)259			}260		}261	})262}263 264func BenchmarkCodeDecoder(b *testing.B) {265	b.ReportAllocs()266	if codeJSON == nil {267		b.StopTimer()268		codeInit()269		b.StartTimer()270	}271	b.RunParallel(func(pb *testing.PB) {272		var buf bytes.Buffer273		dec := NewDecoder(&buf)274		var r codeResponse275		for pb.Next() {276			buf.Write(codeJSON)277			// hide EOF278			buf.WriteByte('\n')279			buf.WriteByte('\n')280			buf.WriteByte('\n')281			if err := dec.Decode(&r); err != nil {282				b.Fatalf("Decode error: %v", err)283			}284		}285	})286	b.SetBytes(int64(len(codeJSON)))287}288 289func BenchmarkUnicodeDecoder(b *testing.B) {290	b.ReportAllocs()291	j := []byte(`"\uD83D\uDE01"`)292	b.SetBytes(int64(len(j)))293	r := bytes.NewReader(j)294	dec := NewDecoder(r)295	var out string296	b.ResetTimer()297	for i := 0; i < b.N; i++ {298		if err := dec.Decode(&out); err != nil {299			b.Fatalf("Decode error: %v", err)300		}301		r.Seek(0, 0)302	}303}304 305func BenchmarkDecoderStream(b *testing.B) {306	b.ReportAllocs()307	b.StopTimer()308	var buf bytes.Buffer309	dec := NewDecoder(&buf)310	buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n")311	var x any312	if err := dec.Decode(&x); err != nil {313		b.Fatalf("Decode error: %v", err)314	}315	ones := strings.Repeat(" 1\n", 300000) + "\n\n\n"316	b.StartTimer()317	for i := 0; i < b.N; i++ {318		if i%300000 == 0 {319			buf.WriteString(ones)320		}321		x = nil322		switch err := dec.Decode(&x); {323		case err != nil:324			b.Fatalf("Decode error: %v", err)325		case x != 1.0:326			b.Fatalf("Decode: got %v want 1.0", i)327		}328	}329}330 331func BenchmarkCodeUnmarshal(b *testing.B) {332	b.ReportAllocs()333	if codeJSON == nil {334		b.StopTimer()335		codeInit()336		b.StartTimer()337	}338	b.RunParallel(func(pb *testing.PB) {339		for pb.Next() {340			var r codeResponse341			if err := Unmarshal(codeJSON, &r); err != nil {342				b.Fatalf("Unmarshal error: %v", err)343			}344		}345	})346	b.SetBytes(int64(len(codeJSON)))347}348 349func BenchmarkCodeUnmarshalReuse(b *testing.B) {350	b.ReportAllocs()351	if codeJSON == nil {352		b.StopTimer()353		codeInit()354		b.StartTimer()355	}356	b.RunParallel(func(pb *testing.PB) {357		var r codeResponse358		for pb.Next() {359			if err := Unmarshal(codeJSON, &r); err != nil {360				b.Fatalf("Unmarshal error: %v", err)361			}362		}363	})364	b.SetBytes(int64(len(codeJSON)))365}366 367func BenchmarkUnmarshalString(b *testing.B) {368	b.ReportAllocs()369	data := []byte(`"hello, world"`)370	b.RunParallel(func(pb *testing.PB) {371		var s string372		for pb.Next() {373			if err := Unmarshal(data, &s); err != nil {374				b.Fatalf("Unmarshal error: %v", err)375			}376		}377	})378}379 380func BenchmarkUnmarshalFloat64(b *testing.B) {381	b.ReportAllocs()382	data := []byte(`3.14`)383	b.RunParallel(func(pb *testing.PB) {384		var f float64385		for pb.Next() {386			if err := Unmarshal(data, &f); err != nil {387				b.Fatalf("Unmarshal error: %v", err)388			}389		}390	})391}392 393func BenchmarkUnmarshalInt64(b *testing.B) {394	b.ReportAllocs()395	data := []byte(`3`)396	b.RunParallel(func(pb *testing.PB) {397		var x int64398		for pb.Next() {399			if err := Unmarshal(data, &x); err != nil {400				b.Fatalf("Unmarshal error: %v", err)401			}402		}403	})404}405 406func BenchmarkUnmarshalMap(b *testing.B) {407	b.ReportAllocs()408	data := []byte(`{"key1":"value1","key2":"value2","key3":"value3"}`)409	b.RunParallel(func(pb *testing.PB) {410		x := make(map[string]string, 3)411		for pb.Next() {412			if err := Unmarshal(data, &x); err != nil {413				b.Fatalf("Unmarshal error: %v", err)414			}415		}416	})417}418 419func BenchmarkIssue10335(b *testing.B) {420	b.ReportAllocs()421	j := []byte(`{"a":{ }}`)422	b.RunParallel(func(pb *testing.PB) {423		var s struct{}424		for pb.Next() {425			if err := Unmarshal(j, &s); err != nil {426				b.Fatalf("Unmarshal error: %v", err)427			}428		}429	})430}431 432func BenchmarkIssue34127(b *testing.B) {433	b.ReportAllocs()434	j := struct {435		Bar string `json:"bar,string"`436	}{437		Bar: `foobar`,438	}439	b.RunParallel(func(pb *testing.PB) {440		for pb.Next() {441			if _, err := Marshal(&j); err != nil {442				b.Fatalf("Marshal error: %v", err)443			}444		}445	})446}447 448func BenchmarkUnmapped(b *testing.B) {449	b.ReportAllocs()450	j := []byte(`{"s": "hello", "y": 2, "o": {"x": 0}, "a": [1, 99, {"x": 1}]}`)451	b.RunParallel(func(pb *testing.PB) {452		var s struct{}453		for pb.Next() {454			if err := Unmarshal(j, &s); err != nil {455				b.Fatalf("Unmarshal error: %v", err)456			}457		}458	})459}460 461func BenchmarkTypeFieldsCache(b *testing.B) {462	b.ReportAllocs()463	var maxTypes int = 1e6464	if testenv.Builder() != "" {465		maxTypes = 1e3 // restrict cache sizes on builders466	}467 468	// Dynamically generate many new types.469	types := make([]reflect.Type, maxTypes)470	fs := []reflect.StructField{{471		Type:  reflect.TypeFor[string](),472		Index: []int{0},473	}}474	for i := range types {475		fs[0].Name = fmt.Sprintf("TypeFieldsCache%d", i)476		types[i] = reflect.StructOf(fs)477	}478 479	// clearClear clears the cache. Other JSON operations, must not be running.480	clearCache := func() {481		fieldCache = sync.Map{}482	}483 484	// MissTypes tests the performance of repeated cache misses.485	// This measures the time to rebuild a cache of size nt.486	for nt := 1; nt <= maxTypes; nt *= 10 {487		ts := types[:nt]488		b.Run(fmt.Sprintf("MissTypes%d", nt), func(b *testing.B) {489			nc := runtime.GOMAXPROCS(0)490			for i := 0; i < b.N; i++ {491				clearCache()492				var wg sync.WaitGroup493				for j := 0; j < nc; j++ {494					wg.Add(1)495					go func(j int) {496						for _, t := range ts[(j*len(ts))/nc : ((j+1)*len(ts))/nc] {497							cachedTypeFields(t)498						}499						wg.Done()500					}(j)501				}502				wg.Wait()503			}504		})505	}506 507	// HitTypes tests the performance of repeated cache hits.508	// This measures the average time of each cache lookup.509	for nt := 1; nt <= maxTypes; nt *= 10 {510		// Pre-warm a cache of size nt.511		clearCache()512		for _, t := range types[:nt] {513			cachedTypeFields(t)514		}515		b.Run(fmt.Sprintf("HitTypes%d", nt), func(b *testing.B) {516			b.RunParallel(func(pb *testing.PB) {517				for pb.Next() {518					cachedTypeFields(types[0])519				}520			})521		})522	}523}524 525func BenchmarkEncodeMarshaler(b *testing.B) {526	b.ReportAllocs()527 528	m := struct {529		A int530		B RawMessage531	}{}532 533	b.RunParallel(func(pb *testing.PB) {534		enc := NewEncoder(io.Discard)535 536		for pb.Next() {537			if err := enc.Encode(&m); err != nil {538				b.Fatalf("Encode error: %v", err)539			}540		}541	})542}543 544func BenchmarkEncoderEncode(b *testing.B) {545	b.ReportAllocs()546	type T struct {547		X, Y string548	}549	v := &T{"foo", "bar"}550	b.RunParallel(func(pb *testing.PB) {551		for pb.Next() {552			if err := NewEncoder(io.Discard).Encode(v); err != nil {553				b.Fatalf("Encode error: %v", err)554			}555		}556	})557}558 559func BenchmarkNumberIsValid(b *testing.B) {560	s := "-61657.61667E+61673"561	for i := 0; i < b.N; i++ {562		isValidNumber(s)563	}564}565 566func BenchmarkNumberIsValidRegexp(b *testing.B) {567	var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`)568	s := "-61657.61667E+61673"569	for i := 0; i < b.N; i++ {570		jsonNumberRegexp.MatchString(s)571	}572}573 574func BenchmarkUnmarshalNumber(b *testing.B) {575	b.ReportAllocs()576	data := []byte(`"-61657.61667E+61673"`)577	var number Number578	for i := 0; i < b.N; i++ {579		if err := Unmarshal(data, &number); err != nil {580			b.Fatal("Unmarshal:", err)581		}582	}583}584 
codekingpro/portable-devtools · Team Ai