From 381ba9f64cce0e40889d0eec3efef4ca9bb0cf26 Mon Sep 17 00:00:00 2001 From: kwakubiney Date: Mon, 11 Mar 2024 22:53:08 +0000 Subject: encoding/binary: cache struct sizes to speed up Read and Write for slice of structs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A lot of allocations happen in dataSize due to reflection. Cache the result of the function when encoding a slice of structs similar to what is done for struct types so that subsequent calls to dataSize can avoid allocations. │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ WriteSlice1000Structs-2 846.7µ ± 4% 856.4µ ± 3% ~ (p=0.602 n=20) │ old.txt │ new.txt │ │ B/s │ B/s vs base │ WriteSlice1000Structs-2 84.48Mi ± 4% 83.52Mi ± 3% ~ (p=0.602 n=20) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ WriteSlice1000Structs-2 80.18Ki ± 0% 80.06Ki ± 0% -0.15% (p=0.000 n=20) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ WriteSlice1000Structs-2 16.000 ± 0% 1.000 ± 0% -93.75% (p=0.000 n=2 │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ ReadSlice1000Structs-2 847.4µ ± 4% 821.1µ ± 3% -3.10% (p=0.012 n=20) │ old.txt │ new.txt │ │ B/s │ B/s vs base │ ReadSlice1000Structs-2 84.40Mi ± 4% 87.11Mi ± 3% +3.20% (p=0.012 n=20) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ ReadSlice1000Structs-2 80.12Ki ± 0% 80.00Ki ± 0% -0.15% (p=0.000 n=20) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ ReadSlice1000Structs-2 16.000 ± 0% 1.000 ± 0% -93.75% (p=0.000 n=20) Fixes #66253 Change-Id: I8227e61306db1fe103489ea4fee2429247c3debc Reviewed-on: https://go-review.googlesource.com/c/go/+/570855 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Cherry Mui Auto-Submit: Ian Lance Taylor --- src/encoding/binary/binary.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/encoding/binary/binary.go') diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go index 59a6c654d2..634995a5bd 100644 --- a/src/encoding/binary/binary.go +++ b/src/encoding/binary/binary.go @@ -480,8 +480,17 @@ var structSize sync.Map // map[reflect.Type]int func dataSize(v reflect.Value) int { switch v.Kind() { case reflect.Slice: - if s := sizeof(v.Type().Elem()); s >= 0 { - return s * v.Len() + t := v.Type().Elem() + if size, ok := structSize.Load(t); ok { + return size.(int) * v.Len() + } + + size := sizeof(t) + if size >= 0 { + if t.Kind() == reflect.Struct { + structSize.Store(t, size) + } + return size * v.Len() } case reflect.Struct: -- cgit v1.3