Skip to content

Commit de9682a

Browse files
committed
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 <[email protected]> Reviewed-by: Lasse Folger <[email protected]>
1 parent b0a9446 commit de9682a

File tree

2 files changed

+13
-1
lines changed

2 files changed

+13
-1
lines changed

internal/benchmarks/micro/micro_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ func BenchmarkEmptyMessage(b *testing.B) {
6767
}
6868
})
6969
})
70+
b.Run("New", func(b *testing.B) {
71+
mt := (&emptypb.Empty{}).ProtoReflect().Type()
72+
b.RunParallel(func(pb *testing.PB) {
73+
for pb.Next() {
74+
mt.New()
75+
}
76+
})
77+
})
7078
}
7179

7280
// BenchmarkRepeatedInt32 tests a message containing 500 non-packed repeated int32s.

internal/impl/message.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,11 @@ fieldLoop:
218218
}
219219

220220
func (mi *MessageInfo) New() protoreflect.Message {
221-
return mi.MessageOf(reflect.New(mi.GoReflectType.Elem()).Interface())
221+
m := reflect.New(mi.GoReflectType.Elem()).Interface()
222+
if r, ok := m.(protoreflect.ProtoMessage); ok {
223+
return r.ProtoReflect()
224+
}
225+
return mi.MessageOf(m)
222226
}
223227
func (mi *MessageInfo) Zero() protoreflect.Message {
224228
return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface())

0 commit comments

Comments
 (0)