protobuf-go/internal/impl/codec_map.go

389 lines
10 KiB
Go
Raw Normal View History

internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package impl
import (
"reflect"
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
"sort"
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/reflect/protoreflect"
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
)
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>
2019-06-27 10:54:42 -07:00
type mapInfo struct {
goType reflect.Type
keyWiretag uint64
valWiretag uint64
keyFuncs valueCoderFuncs
valFuncs valueCoderFuncs
keyZero protoreflect.Value
keyKind protoreflect.Kind
conv *mapConverter
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>
2019-06-27 10:54:42 -07:00
}
func encoderFuncsForMap(fd protoreflect.FieldDescriptor, ft reflect.Type) (valueMessage *MessageInfo, funcs pointerCoderFuncs) {
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
// TODO: Consider generating specialized map coders.
keyField := fd.MapKey()
valField := fd.MapValue()
keyWiretag := protowire.EncodeTag(1, wireTypes[keyField.Kind()])
valWiretag := protowire.EncodeTag(2, wireTypes[valField.Kind()])
keyFuncs := encoderFuncsForValue(keyField)
valFuncs := encoderFuncsForValue(valField)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
conv := newMapConverter(ft, fd)
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
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>
2019-06-27 10:54:42 -07:00
mapi := &mapInfo{
goType: ft,
keyWiretag: keyWiretag,
valWiretag: valWiretag,
keyFuncs: keyFuncs,
valFuncs: valFuncs,
keyZero: keyField.Default(),
keyKind: keyField.Kind(),
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
conv: conv,
}
if valField.Kind() == protoreflect.MessageKind {
valueMessage = getMessageInfo(ft.Elem())
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>
2019-06-27 10:54:42 -07:00
}
funcs = pointerCoderFuncs{
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
return sizeMap(p.AsValueOf(ft).Elem(), mapi, f, opts)
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
},
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
return appendMap(b, p.AsValueOf(ft).Elem(), mapi, f, opts)
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
},
unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
mp := p.AsValueOf(ft)
if mp.Elem().IsNil() {
mp.Elem().Set(reflect.MakeMap(mapi.goType))
}
if f.mi == nil {
return consumeMap(b, mp.Elem(), wtyp, mapi, f, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
} else {
return consumeMapOfMessage(b, mp.Elem(), wtyp, mapi, f, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
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>
2019-06-27 10:54:42 -07:00
},
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
}
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>
2020-02-11 11:25:16 -08:00
switch valField.Kind() {
case protoreflect.MessageKind:
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>
2020-02-11 11:25:16 -08:00
funcs.merge = mergeMapOfMessage
case protoreflect.BytesKind:
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>
2020-02-11 11:25:16 -08:00
funcs.merge = mergeMapOfBytes
default:
funcs.merge = mergeMap
}
if valFuncs.isInit != nil {
funcs.isInit = func(p pointer, f *coderFieldInfo) error {
return isInitMap(p.AsValueOf(ft).Elem(), mapi, f)
}
}
return valueMessage, funcs
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
}
const (
mapKeyTagSize = 1 // field 1, tag size 1.
mapValTagSize = 1 // field 2, tag size 2.
)
func sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) int {
if mapv.Len() == 0 {
return 0
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>
2019-06-27 10:54:42 -07:00
}
n := 0
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
iter := mapRange(mapv)
for iter.Next() {
key := mapi.conv.keyConv.PBValueOf(iter.Key()).MapKey()
keySize := mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
var valSize int
value := mapi.conv.valConv.PBValueOf(iter.Value())
if f.mi == nil {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
valSize = mapi.valFuncs.size(value, mapValTagSize, opts)
} else {
p := pointerOfValue(iter.Value())
valSize += mapValTagSize
valSize += protowire.SizeBytes(f.mi.sizePointer(p, opts))
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
n += f.tagsize + protowire.SizeBytes(keySize+valSize)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
return n
}
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>
2019-06-27 10:54:42 -07:00
func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != protowire.BytesType {
return out, errUnknown
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>
2019-06-27 10:54:42 -07:00
}
b, n := protowire.ConsumeBytes(b)
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>
2019-06-27 10:54:42 -07:00
if n < 0 {
return out, errDecode
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>
2019-06-27 10:54:42 -07:00
}
var (
key = mapi.keyZero
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
val = mapi.conv.valConv.New()
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>
2019-06-27 10:54:42 -07:00
)
for len(b) > 0 {
num, wtyp, n := protowire.ConsumeTag(b)
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>
2019-06-27 10:54:42 -07:00
if n < 0 {
return out, errDecode
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>
2019-06-27 10:54:42 -07:00
}
if num > protowire.MaxValidNumber {
return out, errDecode
}
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>
2019-06-27 10:54:42 -07:00
b = b[n:]
err := errUnknown
switch num {
case genid.MapEntry_Key_field_number:
var v protoreflect.Value
var o unmarshalOutput
v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
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>
2019-06-27 10:54:42 -07:00
if err != nil {
break
}
key = v
n = o.n
case genid.MapEntry_Value_field_number:
var v protoreflect.Value
var o unmarshalOutput
v, o, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts)
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>
2019-06-27 10:54:42 -07:00
if err != nil {
break
}
val = v
n = o.n
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>
2019-06-27 10:54:42 -07:00
}
if err == errUnknown {
n = protowire.ConsumeFieldValue(num, wtyp, b)
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>
2019-06-27 10:54:42 -07:00
if n < 0 {
return out, errDecode
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>
2019-06-27 10:54:42 -07:00
}
} else if err != nil {
return out, err
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>
2019-06-27 10:54:42 -07:00
}
b = b[n:]
}
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), mapi.conv.valConv.GoValueOf(val))
out.n = n
return out, nil
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>
2019-06-27 10:54:42 -07:00
}
func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != protowire.BytesType {
return out, errUnknown
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
}
b, n := protowire.ConsumeBytes(b)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
if n < 0 {
return out, errDecode
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
var (
key = mapi.keyZero
val = reflect.New(f.mi.GoReflectType.Elem())
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
)
for len(b) > 0 {
num, wtyp, n := protowire.ConsumeTag(b)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
if n < 0 {
return out, errDecode
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
if num > protowire.MaxValidNumber {
return out, errDecode
}
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
b = b[n:]
err := errUnknown
switch num {
case 1:
var v protoreflect.Value
var o unmarshalOutput
v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
if err != nil {
break
}
key = v
n = o.n
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
case 2:
if wtyp != protowire.BytesType {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
break
}
var v []byte
v, n = protowire.ConsumeBytes(b)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
if n < 0 {
return out, errDecode
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
var o unmarshalOutput
o, err = f.mi.unmarshalPointer(v, pointerOfValue(val), 0, opts)
if o.initialized {
// Consider this map item initialized so long as we see
// an initialized value.
out.initialized = true
}
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
if err == errUnknown {
n = protowire.ConsumeFieldValue(num, wtyp, b)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
if n < 0 {
return out, errDecode
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
} else if err != nil {
return out, err
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
b = b[n:]
}
mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), val)
out.n = n
return out, nil
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
if f.mi == nil {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
val := mapi.conv.valConv.PBValueOf(valrv)
size := 0
size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
size += mapi.valFuncs.size(val, mapValTagSize, opts)
b = protowire.AppendVarint(b, uint64(size))
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts)
if err != nil {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
return nil, err
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
}
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
return mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts)
} else {
key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
val := pointerOfValue(valrv)
valSize := f.mi.sizePointer(val, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
size := 0
size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
size += mapValTagSize + protowire.SizeBytes(valSize)
b = protowire.AppendVarint(b, uint64(size))
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts)
if err != nil {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
return nil, err
}
b = protowire.AppendVarint(b, mapi.valWiretag)
b = protowire.AppendVarint(b, uint64(valSize))
return f.mi.marshalAppendPointer(b, val, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
}
func appendMap(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
if mapv.Len() == 0 {
return b, nil
}
if opts.Deterministic() {
return appendMapDeterministic(b, mapv, mapi, f, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
}
iter := mapRange(mapv)
for iter.Next() {
var err error
b = protowire.AppendVarint(b, f.wiretag)
b, err = appendMapItem(b, iter.Key(), iter.Value(), mapi, f, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
if err != nil {
return b, err
}
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
}
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
return b, nil
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
}
func appendMapDeterministic(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
keys := mapv.MapKeys()
sort.Slice(keys, func(i, j int) bool {
switch keys[i].Kind() {
case reflect.Bool:
return !keys[i].Bool() && keys[j].Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return keys[i].Int() < keys[j].Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return keys[i].Uint() < keys[j].Uint()
case reflect.Float32, reflect.Float64:
return keys[i].Float() < keys[j].Float()
case reflect.String:
return keys[i].String() < keys[j].String()
default:
panic("invalid kind: " + keys[i].Kind().String())
}
})
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
for _, key := range keys {
var err error
b = protowire.AppendVarint(b, f.wiretag)
b, err = appendMapItem(b, key, mapv.MapIndex(key), mapi, f, opts)
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
if err != nil {
return b, err
}
}
return b, nil
}
func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error {
if mi := f.mi; mi != nil {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
mi.init()
if !mi.needsInitCheck {
return nil
}
iter := mapRange(mapv)
for iter.Next() {
val := pointerOfValue(iter.Value())
if err := mi.checkInitializedPointer(val); err != nil {
internal/impl: faster map fast path Avoid using protobuf reflection on map values in the fast path. Range operations in particular are expensive in protoreflect, because the closure passed to Map.Range escapes. Iterate maps using a reflect.MapIter when available. When operating on maps of messages where we have a *MessageInfo for the message type, directly jump to the fast-path *MessageInfo methods rather than passing through the proto package. Benchmarks deltas for a google.protobuf.Struct with JSON represention: {"parameters":{"a":{"b":{"c":{"d":{"e":{"f":{"g":{}}}}}}}}} Compared to previous revision: name old time/op new time/op delta NestedStruct/Size 7.22µs ± 2% 4.84µs ± 2% -32.96% (p=0.000 n=8+8) NestedStruct/Size-8 9.30µs ± 2% 5.89µs ± 2% -36.60% (p=0.000 n=8+8) NestedStruct/Marshal 77.6µs ±12% 9.8µs ± 4% -87.33% (p=0.000 n=8+8) NestedStruct/Marshal-8 91.6µs ± 2% 11.9µs ± 2% -86.99% (p=0.000 n=8+8) NestedStruct/Unmarshal 11.5µs ± 4% 8.7µs ± 2% -24.76% (p=0.000 n=8+8) NestedStruct/Unmarshal-8 15.4µs ± 4% 11.9µs ± 2% -22.41% (p=0.000 n=8+8) Compared to github.com/golang/protobuf: name old time/op new time/op delta NestedStruct/Size 5.42µs ± 1% 4.84µs ± 2% -10.61% (p=0.000 n=8+8) NestedStruct/Size-8 6.34µs ± 2% 5.89µs ± 2% -7.10% (p=0.000 n=8+8) NestedStruct/Marshal 12.5µs ± 2% 9.8µs ± 4% -21.41% (p=0.000 n=7+8) NestedStruct/Marshal-8 14.1µs ± 3% 11.9µs ± 2% -15.52% (p=0.000 n=8+8) NestedStruct/Unmarshal 9.66µs ± 1% 8.65µs ± 2% -10.40% (p=0.000 n=7+8) NestedStruct/Unmarshal-8 11.7µs ± 3% 11.9µs ± 2% +1.95% (p=0.038 n=8+8) Change-Id: I0effe6491f30d41f31904777f74eca3ac3694db3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/211737 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-12-17 11:39:17 -08:00
return err
}
}
} else {
iter := mapRange(mapv)
for iter.Next() {
val := mapi.conv.valConv.PBValueOf(iter.Value())
if err := mapi.valFuncs.isInit(val); err != nil {
return err
}
}
}
return nil
internal/impl: add fast-path marshal implementation This is a port of the v1 table marshaler, with some substantial cleanup and refactoring. Benchstat results from the protobuf reference benchmark data comparing the v1 package with v2, with AllowPartial:true set for the new package. This is not an apples-to-apples comparison, since v1 doesn't have a way to disable required field checks. Required field checks in v2 package currently go through reflection, which performs terribly; my initial experimentation indicates that fast-path required field checks will not add a large amount of cost; these results are incomplete but not wholly inaccurate. name old time/op new time/op delta /dataset.google_message3_1.pb/Marshal-12 219ms ± 1% 232ms ± 1% +5.85% (p=0.004 n=6+5) /dataset.google_message2.pb/Marshal-12 261µs ± 3% 248µs ± 1% -5.14% (p=0.002 n=6+6) /dataset.google_message1_proto2.pb/Marshal-12 681ns ± 2% 637ns ± 3% -6.53% (p=0.002 n=6+6) /dataset.google_message1_proto3.pb/Marshal-12 1.10µs ± 8% 0.99µs ± 3% -9.63% (p=0.002 n=6+6) /dataset.google_message3_3.pb/Marshal-12 44.2ms ± 3% 35.2ms ± 1% -20.28% (p=0.004 n=6+5) /dataset.google_message4.pb/Marshal-12 91.4ms ± 2% 94.9ms ± 2% +3.78% (p=0.002 n=6+6) /dataset.google_message3_2.pb/Marshal-12 78.7ms ± 6% 80.8ms ± 4% ~ (p=0.310 n=6+6) /dataset.google_message3_4.pb/Marshal-12 10.6ms ± 3% 10.6ms ± 8% ~ (p=0.662 n=5+6) /dataset.google_message3_5.pb/Marshal-12 675ms ± 4% 510ms ± 2% -24.40% (p=0.002 n=6+6) /dataset.google_message3_1.pb/Marshal 219ms ± 1% 236ms ± 7% +8.06% (p=0.004 n=5+6) /dataset.google_message2.pb/Marshal 257µs ± 1% 250µs ± 3% ~ (p=0.052 n=5+6) /dataset.google_message1_proto2.pb/Marshal 685ns ± 1% 628ns ± 1% -8.41% (p=0.008 n=5+5) /dataset.google_message1_proto3.pb/Marshal 1.08µs ± 1% 0.98µs ± 2% -9.31% (p=0.004 n=5+6) /dataset.google_message3_3.pb/Marshal 43.7ms ± 1% 35.1ms ± 1% -19.76% (p=0.002 n=6+6) /dataset.google_message4.pb/Marshal 93.4ms ± 4% 94.9ms ± 2% ~ (p=0.180 n=6+6) /dataset.google_message3_2.pb/Marshal 105ms ± 2% 98ms ± 7% -6.81% (p=0.009 n=5+6) /dataset.google_message3_4.pb/Marshal 16.3ms ± 6% 15.7ms ± 3% -3.44% (p=0.041 n=6+6) /dataset.google_message3_5.pb/Marshal 676ms ± 4% 504ms ± 2% -25.50% (p=0.004 n=6+5) Change-Id: I72cc4597117f4cf5d236ef505777d49dd4a5f75d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171020 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-04-01 13:49:56 -07:00
}
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>
2020-02-11 11:25:16 -08:00
func mergeMap(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
dstm := dst.AsValueOf(f.ft).Elem()
srcm := src.AsValueOf(f.ft).Elem()
if srcm.Len() == 0 {
return
}
if dstm.IsNil() {
dstm.Set(reflect.MakeMap(f.ft))
}
iter := mapRange(srcm)
for iter.Next() {
dstm.SetMapIndex(iter.Key(), iter.Value())
}
}
func mergeMapOfBytes(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
dstm := dst.AsValueOf(f.ft).Elem()
srcm := src.AsValueOf(f.ft).Elem()
if srcm.Len() == 0 {
return
}
if dstm.IsNil() {
dstm.Set(reflect.MakeMap(f.ft))
}
iter := mapRange(srcm)
for iter.Next() {
dstm.SetMapIndex(iter.Key(), reflect.ValueOf(append(emptyBuf[:], iter.Value().Bytes()...)))
}
}
func mergeMapOfMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
dstm := dst.AsValueOf(f.ft).Elem()
srcm := src.AsValueOf(f.ft).Elem()
if srcm.Len() == 0 {
return
}
if dstm.IsNil() {
dstm.Set(reflect.MakeMap(f.ft))
}
iter := mapRange(srcm)
for iter.Next() {
val := reflect.New(f.ft.Elem().Elem())
if f.mi != nil {
f.mi.mergePointer(pointerOfValue(val), pointerOfValue(iter.Value()), opts)
} else {
opts.Merge(asMessage(val), asMessage(iter.Value()))
}
dstm.SetMapIndex(iter.Key(), val)
}
}