Skip to content

Commit

Permalink
encoding/gob: avoid a pointer to wireType in typeInfo
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Matthew Dempsky <[email protected]>
Run-TryBot: Daniel Martí <[email protected]>
Reviewed-by: Rob Pike <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
  • Loading branch information
mvdan committed Mar 29, 2023
1 parent 6a51c00 commit 4d296bc
Showing 1 changed file with 10 additions and 10 deletions.
20 changes: 10 additions & 10 deletions src/encoding/gob/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
}
}

Expand Down

0 comments on commit 4d296bc

Please sign in to comment.