aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Neil <dneil@google.com>2022-07-20 10:12:14 -0700
committerDamien Neil <dneil@google.com>2022-07-21 16:01:25 +0000
commitde9682ad1656cd1ee6808865f7a42f5a5d79eb73 (patch)
tree860c30875efcf8637876eb38c37a1051a49e98fa
parentb0a944684d78a6b7c1f2bb6864fa910385d5b97a (diff)
downloadgolang-protobuf-de9682ad1656cd1ee6808865f7a42f5a5d79eb73.tar.gz
internal/impl: improve MessageInfo.New performance
Calling the ProtoReflect method of the newly-constructed message avoids an allocation in MessageInfo.MessageOf in the common case of a generated message with an optimized ProtoReflect method. Benchmark for creating an empty message, darwin/arm64 M1 laptop: name old time/op new time/op delta EmptyMessage/New-10 32.1ns ± 2% 23.7ns ± 2% -26.06% (p=0.000 n=10+9) name old alloc/op new alloc/op delta EmptyMessage/New-10 64.0B ± 0% 48.0B ± 0% -25.00% (p=0.000 n=10+10) name old allocs/op new allocs/op delta EmptyMessage/New-10 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) Change-Id: Ifa3c3ffa8edc76f78399306d0f4964eae4aacd28 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/418677 Reviewed-by: Michael Stapelberg <stapelberg@google.com> Reviewed-by: Lasse Folger <lassefolger@google.com>
-rw-r--r--internal/benchmarks/micro/micro_test.go8
-rw-r--r--internal/impl/message.go6
2 files changed, 13 insertions, 1 deletions
diff --git a/internal/benchmarks/micro/micro_test.go b/internal/benchmarks/micro/micro_test.go
index dd967448..cbfb2449 100644
--- a/internal/benchmarks/micro/micro_test.go
+++ b/internal/benchmarks/micro/micro_test.go
@@ -67,6 +67,14 @@ func BenchmarkEmptyMessage(b *testing.B) {
}
})
})
+ b.Run("New", func(b *testing.B) {
+ mt := (&emptypb.Empty{}).ProtoReflect().Type()
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ mt.New()
+ }
+ })
+ })
}
// BenchmarkRepeatedInt32 tests a message containing 500 non-packed repeated int32s.
diff --git a/internal/impl/message.go b/internal/impl/message.go
index 3945ab2e..4f5fb67a 100644
--- a/internal/impl/message.go
+++ b/internal/impl/message.go
@@ -218,7 +218,11 @@ fieldLoop:
}
func (mi *MessageInfo) New() protoreflect.Message {
- return mi.MessageOf(reflect.New(mi.GoReflectType.Elem()).Interface())
+ m := reflect.New(mi.GoReflectType.Elem()).Interface()
+ if r, ok := m.(protoreflect.ProtoMessage); ok {
+ return r.ProtoReflect()
+ }
+ return mi.MessageOf(m)
}
func (mi *MessageInfo) Zero() protoreflect.Message {
return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface())