proto, runtime/protoiface, internal/impl: add fast-path Merge
Comparing -tags=protoreflect to fast-path:
name old time/op new time/op delta
pkg:google.golang.org/protobuf/internal/benchmarks goos:linux goarch:amd64
/Clone/google_message1_proto2-12 1.70µs ± 1% 0.30µs ± 1% -82.64% (p=0.001 n=7+7)
/Clone/google_message1_proto3-12 1.01µs ± 1% 0.19µs ± 1% -80.77% (p=0.000 n=7+8)
/Clone/google_message2-12 818µs ± 8% 141µs ± 6% -82.78% (p=0.000 n=8+8)
pkg:google.golang.org/protobuf/internal/benchmarks/micro goos:linux goarch:amd64
EmptyMessage/Clone-12 51.1ns ± 1% 39.3ns ± 3% -23.03% (p=0.000 n=7+8)
RepeatedInt32/Clone-12 24.5µs ± 1% 1.1µs ± 3% -95.64% (p=0.000 n=8+8)
Required/Clone-12 978ns ± 1% 132ns ± 2% -86.46% (p=0.000 n=8+8)
name old alloc/op new alloc/op delta
pkg:google.golang.org/protobuf/internal/benchmarks goos:linux goarch:amd64
/Clone/google_message1_proto2-12 1.08kB ± 0% 0.74kB ± 0% -31.85% (p=0.000 n=8+8)
/Clone/google_message1_proto3-12 872B ± 0% 544B ± 0% -37.61% (p=0.000 n=8+8)
/Clone/google_message2-12 602kB ± 0% 411kB ± 0% -31.65% (p=0.000 n=8+8)
pkg:google.golang.org/protobuf/internal/benchmarks/micro goos:linux goarch:amd64
EmptyMessage/Clone-12 96.0B ± 0% 64.0B ± 0% -33.33% (p=0.000 n=8+8)
RepeatedInt32/Clone-12 25.4kB ± 0% 3.2kB ± 0% -87.33% (p=0.000 n=8+8)
Required/Clone-12 416B ± 0% 256B ± 0% -38.46% (p=0.000 n=8+8)
name old allocs/op new allocs/op delta
pkg:google.golang.org/protobuf/internal/benchmarks goos:linux goarch:amd64
/Clone/google_message1_proto2-12 52.0 ± 0% 21.0 ± 0% -59.62% (p=0.000 n=8+8)
/Clone/google_message1_proto3-12 33.0 ± 0% 3.0 ± 0% -90.91% (p=0.000 n=8+8)
/Clone/google_message2-12 22.3k ± 0% 7.5k ± 0% -66.41% (p=0.000 n=8+8)
pkg:google.golang.org/protobuf/internal/benchmarks/micro goos:linux goarch:amd64
EmptyMessage/Clone-12 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=8+8)
RepeatedInt32/Clone-12 1.51k ± 0% 0.00k ± 0% -99.80% (p=0.000 n=8+8)
Required/Clone-12 51.0 ± 0% 18.0 ± 0% -64.71% (p=0.000 n=8+8)
Change-Id: Ife9018097c34cb025dc9c4fdd9a61b2f947853c6
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/219147
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/impl/codec_reflect.go b/internal/impl/codec_reflect.go
index ae872aa..85811b0 100644
--- a/internal/impl/codec_reflect.go
+++ b/internal/impl/codec_reflect.go
@@ -37,10 +37,15 @@
return out, nil
}
+func mergeEnum(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
+ dst.v.Elem().Set(src.v.Elem())
+}
+
var coderEnum = pointerCoderFuncs{
size: sizeEnum,
marshal: appendEnum,
unmarshal: consumeEnum,
+ merge: mergeEnum,
}
func sizeEnumNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
@@ -57,10 +62,17 @@
return appendEnum(b, p, f, opts)
}
+func mergeEnumNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
+ if src.v.Elem().Int() != 0 {
+ dst.v.Elem().Set(src.v.Elem())
+ }
+}
+
var coderEnumNoZero = pointerCoderFuncs{
size: sizeEnumNoZero,
marshal: appendEnumNoZero,
unmarshal: consumeEnum,
+ merge: mergeEnumNoZero,
}
func sizeEnumPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
@@ -81,10 +93,19 @@
return consumeEnum(b, pointer{p.v.Elem()}, wtyp, f, opts)
}
+func mergeEnumPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
+ if !src.v.Elem().IsNil() {
+ v := reflect.New(dst.v.Type().Elem().Elem())
+ v.Elem().Set(src.v.Elem().Elem())
+ dst.v.Elem().Set(v)
+ }
+}
+
var coderEnumPtr = pointerCoderFuncs{
size: sizeEnumPtr,
marshal: appendEnumPtr,
unmarshal: consumeEnumPtr,
+ merge: mergeEnumPtr,
}
func sizeEnumSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
@@ -138,10 +159,15 @@
return out, nil
}
+func mergeEnumSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
+ dst.v.Elem().Set(reflect.AppendSlice(dst.v.Elem(), src.v.Elem()))
+}
+
var coderEnumSlice = pointerCoderFuncs{
size: sizeEnumSlice,
marshal: appendEnumSlice,
unmarshal: consumeEnumSlice,
+ merge: mergeEnumSlice,
}
func sizeEnumPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
@@ -179,4 +205,5 @@
size: sizeEnumPackedSlice,
marshal: appendEnumPackedSlice,
unmarshal: consumeEnumSlice,
+ merge: mergeEnumSlice,
}