From: Daniel Martí Date: Sat, 25 Mar 2023 11:48:41 +0000 (+0000) Subject: encoding/gob: avoid a pointer to wireType in typeInfo X-Git-Tag: go1.21rc1~1099 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4d296bcbc25acb14ef603c6824113758d74b4a31;p=gostls13.git encoding/gob: avoid a pointer to wireType in typeInfo wireType itself is just a struct with seven pointer fields, so an indirection doesn't feel necessary to noticeably reduce the amount of memory that typeInfo takes for each Go type registered in gob. The indirection does add a small amount of overhead though, particularly one extra allocation when registering a type, which is done a number of times as part of init. For consistency, also update wireTypeUserInfo to not use a pointer. Measuring via one of the end-to-end benchmarks and benchinit: goos: linux goarch: amd64 pkg: encoding/gob cpu: AMD Ryzen 7 PRO 5850U with Radeon Graphics │ old │ new │ │ sec/op │ sec/op vs base │ EndToEndPipe-16 736.8n ± 5% 733.9n ± 5% ~ (p=0.971 n=10) EncodingGob 177.6µ ± 0% 173.6µ ± 0% -2.27% (p=0.000 n=10) geomean 11.44µ 11.29µ -1.34% │ old │ new │ │ B/op │ B/op vs base │ EndToEndPipe-16 1.766Ki ± 0% 1.766Ki ± 0% ~ (p=1.000 n=10) ¹ EncodingGob 38.47Ki ± 0% 38.27Ki ± 0% -0.50% (p=0.000 n=10) geomean 8.241Ki 8.220Ki -0.25% ¹ all samples are equal │ old │ new │ │ allocs/op │ allocs/op vs base │ EndToEndPipe-16 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹ EncodingGob 652.0 ± 0% 642.0 ± 0% -1.53% (p=0.000 n=10) geomean 36.11 35.83 -0.77% ¹ all samples are equal Change-Id: I528080b7d990ed595683f155a1ae25dcd26394b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/479398 Reviewed-by: Ian Lance Taylor Reviewed-by: Matthew Dempsky Run-TryBot: Daniel Martí Reviewed-by: Rob Pike TryBot-Result: Gopher Robot --- diff --git a/src/encoding/gob/type.go b/src/encoding/gob/type.go index 41204bfb7f..f8b7b24db7 100644 --- a/src/encoding/gob/type.go +++ b/src/encoding/gob/type.go @@ -263,7 +263,7 @@ var ( // Predefined because it's needed by the Decoder var tWireType = mustGetTypeInfo(reflect.TypeOf((*wireType)(nil)).Elem()).id -var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType) +var wireTypeUserInfo *userTypeInfo // userTypeInfo of wireType func init() { // Some magic numbers to make sure there are no surprises. @@ -284,7 +284,7 @@ func init() { } idToType = idToType[:firstUserId] registerBasics() - wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil))) + wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)).Elem()) } // Array type @@ -675,7 +675,7 @@ type typeInfo struct { id typeId encInit sync.Mutex // protects creation of encoder encoder atomic.Pointer[encEngine] - wire *wireType + wire wireType } // typeInfoMap is an atomic pointer to map[reflect.Type]*typeInfo. @@ -736,27 +736,27 @@ func buildTypeInfo(ut *userTypeInfo, rt reflect.Type) (*typeInfo, error) { gt := userType.id().gobType().(*gobEncoderType) switch ut.externalEnc { case xGob: - info.wire = &wireType{GobEncoderT: gt} + info.wire.GobEncoderT = gt case xBinary: - info.wire = &wireType{BinaryMarshalerT: gt} + info.wire.BinaryMarshalerT = gt case xText: - info.wire = &wireType{TextMarshalerT: gt} + info.wire.TextMarshalerT = gt } rt = ut.user } else { t := info.id.gobType() switch typ := rt; typ.Kind() { case reflect.Array: - info.wire = &wireType{ArrayT: t.(*arrayType)} + info.wire.ArrayT = t.(*arrayType) case reflect.Map: - info.wire = &wireType{MapT: t.(*mapType)} + info.wire.MapT = t.(*mapType) case reflect.Slice: // []byte == []uint8 is a special case handled separately if typ.Elem().Kind() != reflect.Uint8 { - info.wire = &wireType{SliceT: t.(*sliceType)} + info.wire.SliceT = t.(*sliceType) } case reflect.Struct: - info.wire = &wireType{StructT: t.(*structType)} + info.wire.StructT = t.(*structType) } }