internal/impl: add fast-path unmarshal
Benchmarks run with:
go test ./benchmarks/ -bench=Wire -benchtime=500ms -benchmem -count=8
Fast-path vs. parent commit:
name old time/op new time/op delta
Wire/Unmarshal/google_message1_proto2-12 1.35µs ± 2% 0.45µs ± 4% -67.01% (p=0.000 n=8+8)
Wire/Unmarshal/google_message1_proto3-12 1.07µs ± 1% 0.31µs ± 1% -71.04% (p=0.000 n=8+8)
Wire/Unmarshal/google_message2-12 691µs ± 2% 188µs ± 2% -72.78% (p=0.000 n=7+8)
name old allocs/op new allocs/op delta
Wire/Unmarshal/google_message1_proto2-12 60.0 ± 0% 25.0 ± 0% -58.33% (p=0.000 n=8+8)
Wire/Unmarshal/google_message1_proto3-12 42.0 ± 0% 7.0 ± 0% -83.33% (p=0.000 n=8+8)
Wire/Unmarshal/google_message2-12 28.6k ± 0% 8.5k ± 0% -70.34% (p=0.000 n=8+8)
Fast-path vs. -v1:
name old time/op new time/op delta
Wire/Unmarshal/google_message1_proto2-12 702ns ± 1% 445ns ± 4% -36.58% (p=0.000 n=8+8)
Wire/Unmarshal/google_message1_proto3-12 604ns ± 1% 311ns ± 1% -48.54% (p=0.000 n=8+8)
Wire/Unmarshal/google_message2-12 179µs ± 3% 188µs ± 2% +5.30% (p=0.000 n=7+8)
name old allocs/op new allocs/op delta
Wire/Unmarshal/google_message1_proto2-12 26.0 ± 0% 25.0 ± 0% -3.85% (p=0.000 n=8+8)
Wire/Unmarshal/google_message1_proto3-12 8.00 ± 0% 7.00 ± 0% -12.50% (p=0.000 n=8+8)
Wire/Unmarshal/google_message2-12 8.49k ± 0% 8.49k ± 0% -0.01% (p=0.000 n=8+8)
Change-Id: I6247ac3fd66a63d9acb902cbd192094ee3d151c3
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/185147
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/impl/codec_tables.go b/internal/impl/codec_tables.go
index 8acb10d..3d492af 100644
--- a/internal/impl/codec_tables.go
+++ b/internal/impl/codec_tables.go
@@ -8,21 +8,24 @@
"fmt"
"reflect"
+ "google.golang.org/protobuf/internal/encoding/wire"
pref "google.golang.org/protobuf/reflect/protoreflect"
)
// pointerCoderFuncs is a set of pointer encoding functions.
type pointerCoderFuncs struct {
- size func(p pointer, tagsize int, opts marshalOptions) int
- marshal func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error)
- isInit func(p pointer) error
+ size func(p pointer, tagsize int, opts marshalOptions) int
+ marshal func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error)
+ unmarshal func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error)
+ isInit func(p pointer) error
}
// ifaceCoderFuncs is a set of interface{} encoding functions.
type ifaceCoderFuncs struct {
- size func(ival interface{}, tagsize int, opts marshalOptions) int
- marshal func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error)
- isInit func(ival interface{}) error
+ size func(ival interface{}, tagsize int, opts marshalOptions) int
+ marshal func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error)
+ unmarshal func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error)
+ isInit func(ival interface{}) error
}
// fieldCoder returns pointer functions for a field, used for operating on
@@ -574,7 +577,7 @@
case pref.MessageKind:
return coderMessageIface
case pref.GroupKind:
- return coderGroupIface
+ return makeGroupValueCoder(fd, ft)
}
}
panic(fmt.Errorf("invalid type: no encoder for %v %v %v/%v", fd.FullName(), fd.Cardinality(), fd.Kind(), ft))