proto: CSE ProtoReflect() and TypeDescriptor() in proto.HasExtension
No need to call them multiple times, no matter how cheap they are. Mild
improvements, this CL is 01-cse-hasextension:
$ perflock -socket=@perflock -shared -cores 12 go test -tags=protolegacy -test.bench=BenchmarkExtension -test.benchmem -test.run=^# -test.count 10 internal/benchmarks/micro/micro_test.go
goarch: amd64
cpu: AMD Ryzen Threadripper PRO 3995WX 64-Cores
│ 00-cse-messageinfo │ 01-cse-hasextension │
│ sec/op │ sec/op vs base │
Extension/Has/None-12 103.30n ± 3% 96.73n ± 1% -6.36% (p=0.000 n=10)
Extension/Has/Set-12 113.0n ± 3% 107.1n ± 1% -5.22% (p=0.000 n=10)
Extension/Get/None-12 182.7n ± 2% 176.3n ± 2% -3.48% (p=0.000 n=10)
Extension/Get/Set-12 140.1n ± 2% 138.0n ± 1% -1.46% (p=0.024 n=10)
Extension/Set-12 218.6n ± 2% 219.5n ± 1% ~ (p=0.172 n=10)
geomean 145.6n 140.8n -3.25%
Change-Id: Ide1a0c0fe4e562ed24f88dc829249fca0f052d48
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/576315
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Nicolas Hillegeer <aktau@google.com>
Reviewed-by: Michael Stapelberg <stapelberg@google.com>
diff --git a/proto/extension.go b/proto/extension.go
index 17899a3..c9c8721 100644
--- a/proto/extension.go
+++ b/proto/extension.go
@@ -11,18 +11,21 @@
// HasExtension reports whether an extension field is populated.
// It returns false if m is invalid or if xt does not extend m.
func HasExtension(m Message, xt protoreflect.ExtensionType) bool {
- // Treat nil message interface as an empty message; no populated fields.
- if m == nil {
+ // Treat nil message interface or descriptor as an empty message; no populated
+ // fields.
+ if m == nil || xt == nil {
return false
}
// As a special-case, we reports invalid or mismatching descriptors
// as always not being populated (since they aren't).
- if xt == nil || m.ProtoReflect().Descriptor() != xt.TypeDescriptor().ContainingMessage() {
+ mr := m.ProtoReflect()
+ xd := xt.TypeDescriptor()
+ if mr.Descriptor() != xd.ContainingMessage() {
return false
}
- return m.ProtoReflect().Has(xt.TypeDescriptor())
+ return mr.Has(xd)
}
// ClearExtension clears an extension field such that subsequent