From 8487974523a5cc49f487296c29c675005fb2d367 Mon Sep 17 00:00:00 2001 From: Dominic Barnes Date: Thu, 17 Jul 2025 13:09:52 -0700 Subject: [PATCH 1/2] perf(json): revert decodeInto helper changes for object/array/string --- json/decode.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/json/decode.go b/json/decode.go index 46922d5..b44dde6 100644 --- a/json/decode.go +++ b/json/decode.go @@ -1292,15 +1292,19 @@ func (d decoder) decodeInterface(b []byte, p unsafe.Pointer) ([]byte, error) { switch k.Class() { case Object: - v, err = decodeInto[map[string]any](&val, v, d, decoder.decodeMapStringInterface) + m := make(map[string]interface{}) + v, err = d.decodeMapStringInterface(v, unsafe.Pointer(&m)) + val = m case Array: - size := alignedSize(interfaceType) - fn := constructSliceDecodeFunc(size, sliceInterfaceType, decoder.decodeInterface) - v, err = decodeInto[[]any](&val, v, d, fn) + a := make([]interface{}, 0, 10) + v, err = d.decodeSlice(v, unsafe.Pointer(&a), unsafe.Sizeof(a[0]), sliceInterfaceType, decoder.decodeInterface) + val = a case String: - v, err = decodeInto[string](&val, v, d, decoder.decodeString) + s := "" + v, err = d.decodeString(v, unsafe.Pointer(&s)) + val = s case Null: v, val = nil, nil From 4e4d357392d60a3a35c56fade65f0233c4113313 Mon Sep 17 00:00:00 2001 From: Dominic Barnes Date: Thu, 17 Jul 2025 13:10:29 -0700 Subject: [PATCH 2/2] per(json): add benchmarks for decoding object and array with mixed members --- json/golang_bench_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/json/golang_bench_test.go b/json/golang_bench_test.go index 201352f..3cf7e5a 100644 --- a/json/golang_bench_test.go +++ b/json/golang_bench_test.go @@ -261,6 +261,32 @@ func BenchmarkUnmarshalString(b *testing.B) { }) } +func BenchmarkUnmarshalObjectMixed(b *testing.B) { + b.ReportAllocs() + data := []byte(`{"string":"hello world","time":"2025-07-17T18:40:04.338Z","bool":true,"integer":42,"decimal":3.14,"null":null,"object":{"hello":"world"},"array":[1,2,3]}`) + b.RunParallel(func(pb *testing.PB) { + var m map[string]any + for pb.Next() { + if err := Unmarshal(data, &m); err != nil { + b.Fatal("Unmarshal:", err) + } + } + }) +} + +func BenchmarkUnmarshalArrayMixed(b *testing.B) { + b.ReportAllocs() + data := []byte(`["hello world","2025-07-17T18:40:04.338Z",true,42,3.14,null,{"hello":"world"},[1,2,3]]`) + b.RunParallel(func(pb *testing.PB) { + var a []any + for pb.Next() { + if err := Unmarshal(data, &a); err != nil { + b.Fatal("Unmarshal:", err) + } + } + }) +} + func BenchmarkUnmarshalFloat64(b *testing.B) { b.ReportAllocs() data := []byte(`3.14`)