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>
diff --git a/internal/impl/validate.go b/internal/impl/validate.go
index 093f078..40c6a7a 100644
--- a/internal/impl/validate.go
+++ b/internal/impl/validate.go
@@ -251,14 +251,30 @@
}
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 @@
b = b[n:]
continue Field
}
- n = wire.ConsumeFieldValue(num, wtyp, b)
+ n := wire.ConsumeFieldValue(num, wtyp, b)
if n < 0 {
return ValidationInvalid
}