internal/impl: pass ExtensionTypeDescriptor to extensionMap

The layers freely convert between ExtensionTypeDescriptor (via
ExtensionTypeDescriptor.Type) and ExtensionType (via
ExtensionType.TypeDescriptor()). For certain hot functions , like
(*extensionMap).Has() and (*extensionMap).Get(), this saves a Type() and
TypeDescriptor() pair.

Oddly, the gains are bigger than I expected. This commit is
02-typedesciptor-not-type, it is layered on top of CL 576315
(named 01-cse-hasextension):

    benchstat 00-cse-messageinfo 01-cse-hasextension 02-typedesciptor-not-type
    goarch: amd64
    cpu: AMD Ryzen Threadripper PRO 3995WX 64-Cores
                          │ 00-cse-messageinfo │         01-cse-hasextension         │      02-typedesciptor-not-type      │
                          │       sec/op       │    sec/op     vs base               │   sec/op     vs base                │
    Extension/Has/None-12         103.30n ± 3%    96.73n ± 1%  -6.36% (p=0.000 n=10)   85.54n ± 2%  -17.19% (p=0.000 n=10)
    Extension/Has/Set-12          113.05n ± 3%   107.15n ± 1%  -5.22% (p=0.000 n=10)   97.36n ± 2%  -13.88% (p=0.000 n=10)
    Extension/Get/None-12          182.7n ± 2%    176.3n ± 2%  -3.48% (p=0.000 n=10)   173.3n ± 2%   -5.09% (p=0.000 n=10)
    Extension/Get/Set-12           140.1n ± 2%    138.0n ± 1%  -1.46% (p=0.024 n=10)   135.0n ± 1%   -3.64% (p=0.000 n=10)
    Extension/Set-12               218.6n ± 2%    219.5n ± 1%       ~ (p=0.172 n=10)   210.2n ± 2%   -3.82% (p=0.001 n=10)
    geomean                        145.6n         140.8n       -3.25%                  132.6n        -8.91%

Change-Id: If9c67c680ca57b5d93f863bb1c72f3e5031ed18c
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/576316
Reviewed-by: Michael Stapelberg <stapelberg@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Nicolas Hillegeer <aktau@google.com>
This commit is contained in:
Nicolas Hillegeer 2024-04-03 13:25:41 -07:00 committed by Gopher Robot
parent 39bbf13930
commit 98873a2050
3 changed files with 49 additions and 52 deletions

View File

@ -783,55 +783,55 @@ func (m *{{.}}) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) b
func (m *{{.}}) Has(fd protoreflect.FieldDescriptor) bool {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.has(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Has(xt)
return mi.extensionMap(m.pointer()).Has(xd)
}
}
func (m *{{.}}) Clear(fd protoreflect.FieldDescriptor) {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
fi.clear(m.pointer())
} else {
mi.extensionMap(m.pointer()).Clear(xt)
mi.extensionMap(m.pointer()).Clear(xd)
}
}
func (m *{{.}}) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.get(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Get(xt)
return mi.extensionMap(m.pointer()).Get(xd)
}
}
func (m *{{.}}) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
fi.set(m.pointer(), v)
} else {
mi.extensionMap(m.pointer()).Set(xt, v)
mi.extensionMap(m.pointer()).Set(xd, v)
}
}
func (m *{{.}}) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.mutable(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Mutable(xt)
return mi.extensionMap(m.pointer()).Mutable(xd)
}
}
func (m *{{.}}) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.newField()
} else {
return xt.New()
return xd.Type().New()
}
}
func (m *{{.}}) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {

View File

@ -247,11 +247,10 @@ func (m *extensionMap) Range(f func(protoreflect.FieldDescriptor, protoreflect.V
}
}
}
func (m *extensionMap) Has(xt protoreflect.ExtensionType) (ok bool) {
func (m *extensionMap) Has(xd protoreflect.ExtensionTypeDescriptor) (ok bool) {
if m == nil {
return false
}
xd := xt.TypeDescriptor()
x, ok := (*m)[int32(xd.Number())]
if !ok {
return false
@ -264,20 +263,19 @@ func (m *extensionMap) Has(xt protoreflect.ExtensionType) (ok bool) {
}
return true
}
func (m *extensionMap) Clear(xt protoreflect.ExtensionType) {
delete(*m, int32(xt.TypeDescriptor().Number()))
func (m *extensionMap) Clear(xd protoreflect.ExtensionTypeDescriptor) {
delete(*m, int32(xd.Number()))
}
func (m *extensionMap) Get(xt protoreflect.ExtensionType) protoreflect.Value {
xd := xt.TypeDescriptor()
func (m *extensionMap) Get(xd protoreflect.ExtensionTypeDescriptor) protoreflect.Value {
if m != nil {
if x, ok := (*m)[int32(xd.Number())]; ok {
return x.Value()
}
}
return xt.Zero()
return xd.Type().Zero()
}
func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value) {
xd := xt.TypeDescriptor()
func (m *extensionMap) Set(xd protoreflect.ExtensionTypeDescriptor, v protoreflect.Value) {
xt := xd.Type()
isValid := true
switch {
case !xt.IsValidValue(v):
@ -290,7 +288,7 @@ func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value)
isValid = v.Message().IsValid()
}
if !isValid {
panic(fmt.Sprintf("%v: assigning invalid value", xt.TypeDescriptor().FullName()))
panic(fmt.Sprintf("%v: assigning invalid value", xd.FullName()))
}
if *m == nil {
@ -300,16 +298,15 @@ func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value)
x.Set(xt, v)
(*m)[int32(xd.Number())] = x
}
func (m *extensionMap) Mutable(xt protoreflect.ExtensionType) protoreflect.Value {
xd := xt.TypeDescriptor()
func (m *extensionMap) Mutable(xd protoreflect.ExtensionTypeDescriptor) protoreflect.Value {
if xd.Kind() != protoreflect.MessageKind && xd.Kind() != protoreflect.GroupKind && !xd.IsList() && !xd.IsMap() {
panic("invalid Mutable on field with non-composite type")
}
if x, ok := (*m)[int32(xd.Number())]; ok {
return x.Value()
}
v := xt.New()
m.Set(xt, v)
v := xd.Type().New()
m.Set(xd, v)
return v
}
@ -426,7 +423,7 @@ func (m *messageIfaceWrapper) protoUnwrap() interface{} {
// checkField verifies that the provided field descriptor is valid.
// Exactly one of the returned values is populated.
func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo, protoreflect.ExtensionType) {
func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo, protoreflect.ExtensionTypeDescriptor) {
var fi *fieldInfo
if n := fd.Number(); 0 < n && int(n) < len(mi.denseFields) {
fi = mi.denseFields[n]
@ -455,7 +452,7 @@ func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo,
if !ok {
panic(fmt.Sprintf("extension %v does not implement protoreflect.ExtensionTypeDescriptor", fd.FullName()))
}
return nil, xtd.Type()
return nil, xtd
}
panic(fmt.Sprintf("field %v is invalid", fd.FullName()))
}

View File

@ -66,55 +66,55 @@ func (m *messageState) Range(f func(protoreflect.FieldDescriptor, protoreflect.V
func (m *messageState) Has(fd protoreflect.FieldDescriptor) bool {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.has(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Has(xt)
return mi.extensionMap(m.pointer()).Has(xd)
}
}
func (m *messageState) Clear(fd protoreflect.FieldDescriptor) {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
fi.clear(m.pointer())
} else {
mi.extensionMap(m.pointer()).Clear(xt)
mi.extensionMap(m.pointer()).Clear(xd)
}
}
func (m *messageState) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.get(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Get(xt)
return mi.extensionMap(m.pointer()).Get(xd)
}
}
func (m *messageState) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
fi.set(m.pointer(), v)
} else {
mi.extensionMap(m.pointer()).Set(xt, v)
mi.extensionMap(m.pointer()).Set(xd, v)
}
}
func (m *messageState) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.mutable(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Mutable(xt)
return mi.extensionMap(m.pointer()).Mutable(xd)
}
}
func (m *messageState) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.newField()
} else {
return xt.New()
return xd.Type().New()
}
}
func (m *messageState) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
@ -197,55 +197,55 @@ func (m *messageReflectWrapper) Range(f func(protoreflect.FieldDescriptor, proto
func (m *messageReflectWrapper) Has(fd protoreflect.FieldDescriptor) bool {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.has(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Has(xt)
return mi.extensionMap(m.pointer()).Has(xd)
}
}
func (m *messageReflectWrapper) Clear(fd protoreflect.FieldDescriptor) {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
fi.clear(m.pointer())
} else {
mi.extensionMap(m.pointer()).Clear(xt)
mi.extensionMap(m.pointer()).Clear(xd)
}
}
func (m *messageReflectWrapper) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.get(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Get(xt)
return mi.extensionMap(m.pointer()).Get(xd)
}
}
func (m *messageReflectWrapper) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
fi.set(m.pointer(), v)
} else {
mi.extensionMap(m.pointer()).Set(xt, v)
mi.extensionMap(m.pointer()).Set(xd, v)
}
}
func (m *messageReflectWrapper) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.mutable(m.pointer())
} else {
return mi.extensionMap(m.pointer()).Mutable(xt)
return mi.extensionMap(m.pointer()).Mutable(xd)
}
}
func (m *messageReflectWrapper) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
mi := m.messageInfo()
mi.init()
if fi, xt := mi.checkField(fd); fi != nil {
if fi, xd := mi.checkField(fd); fi != nil {
return fi.newField()
} else {
return xt.New()
return xd.Type().New()
}
}
func (m *messageReflectWrapper) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {