internal/impl: inline small tag decoding in the validator

name                            old time/op    new time/op    delta
EmptyMessage/Wire/Validate-12     4.59ns ± 0%    4.51ns ± 1%   -1.74%  (p=0.001 n=8+8)
RepeatedInt32/Wire/Validate-12    1.28µs ± 0%    0.91µs ± 0%  -28.71%  (p=0.000 n=7+8)
Required/Wire/Validate-12         48.3ns ± 2%    34.5ns ± 0%  -28.69%  (p=0.001 n=7+7)

Change-Id: If7c431ee23d930d44af0fc26b7bd2149d3aded64
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/216624
Reviewed-by: Joe Tsai <joetsai@google.com>
This commit is contained in:
Damien Neil 2020-01-28 08:06:12 -08:00
parent f25a6ca994
commit 5d82883c5a

View File

@ -251,14 +251,30 @@ State:
}
Field:
for len(b) > 0 {
num, wtyp, n := wire.ConsumeTag(b)
if n < 0 {
return ValidationInvalid
// Parse the tag (field number and wire type).
var tag uint64
if b[0] < 0x80 {
tag = uint64(b[0])
b = b[1:]
} else if len(b) >= 2 && b[1] < 128 {
tag = uint64(b[0]&0x7f) + uint64(b[1])<<7
b = b[2:]
} else {
var n int
tag, n = wire.ConsumeVarint(b)
if n < 0 {
return ValidationInvalid
}
b = b[n:]
}
b = b[n:]
if num > wire.MaxValidNumber {
var num wire.Number
if n := tag >> 3; n < uint64(wire.MinValidNumber) || n > uint64(wire.MaxValidNumber) {
return ValidationInvalid
} else {
num = wire.Number(n)
}
wtyp := wire.Type(tag & 7)
if wtyp == wire.EndGroupType {
if st.endGroup == num {
goto PopState
@ -431,7 +447,7 @@ State:
b = b[n:]
continue Field
}
n = wire.ConsumeFieldValue(num, wtyp, b)
n := wire.ConsumeFieldValue(num, wtyp, b)
if n < 0 {
return ValidationInvalid
}