diff options
author | Damien Neil <dneil@google.com> | 2022-07-20 10:12:14 -0700 |
---|---|---|
committer | Damien Neil <dneil@google.com> | 2022-07-21 16:01:25 +0000 |
commit | de9682ad1656cd1ee6808865f7a42f5a5d79eb73 (patch) | |
tree | 860c30875efcf8637876eb38c37a1051a49e98fa | |
parent | b0a944684d78a6b7c1f2bb6864fa910385d5b97a (diff) | |
download | golang-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.go | 8 | ||||
-rw-r--r-- | internal/impl/message.go | 6 |
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()) |