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>
diff --git a/internal/cmd/generate-types/impl.go b/internal/cmd/generate-types/impl.go
index 2d33777..13d510d 100644
--- a/internal/cmd/generate-types/impl.go
+++ b/internal/cmd/generate-types/impl.go
@@ -783,55 +783,55 @@
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 {
diff --git a/internal/impl/message_reflect.go b/internal/impl/message_reflect.go
index c138f4a..a6f0dbd 100644
--- a/internal/impl/message_reflect.go
+++ b/internal/impl/message_reflect.go
@@ -247,11 +247,10 @@
}
}
}
-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 @@
}
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 @@
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 @@
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 @@
// 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 @@
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()))
}
diff --git a/internal/impl/message_reflect_gen.go b/internal/impl/message_reflect_gen.go
index b10033e..29ba6bd 100644
--- a/internal/impl/message_reflect_gen.go
+++ b/internal/impl/message_reflect_gen.go
@@ -66,55 +66,55 @@
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) 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 {