From 5d82883c5a9dc1e3f8e72cba2233aa5e68dcfc1d Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Tue, 28 Jan 2020 08:06:12 -0800 Subject: [PATCH] internal/impl: inline small tag decoding in the validator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- internal/impl/validate.go | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/internal/impl/validate.go b/internal/impl/validate.go index 093f0784..40c6a7a1 100644 --- a/internal/impl/validate.go +++ b/internal/impl/validate.go @@ -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 }