1
0
mirror of https://github.com/golang/go synced 2024-11-23 11:00:08 -07:00

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 <iant@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
Reviewed-by: Rob Pike <r@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Daniel Martí 2023-03-25 11:48:41 +00:00
parent 6a51c000de
commit 4d296bcbc2

View File

@ -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)
}
}