mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-29 09:32:38 +00:00
internal/impl: precompute required bit in validator
Required field validation populates a bitmask of observed required fields. Store a uint64 containing the bit to set in the validationInfo rather than the index of the bit. Provides a noticeable speed increase in validation. name old time/op new time/op delta EmptyMessage/Wire/Unmarshal 40.2ns ± 1% 40.2ns ± 2% ~ (p=0.860 n=35+37) EmptyMessage/Wire/Unmarshal-12 7.13ns ± 5% 7.12ns ± 1% ~ (p=0.112 n=37+37) RepeatedInt32/Wire/Unmarshal 6.57µs ± 1% 6.46µs ± 1% -1.56% (p=0.000 n=39+35) RepeatedInt32/Wire/Unmarshal-12 1.05µs ± 2% 1.05µs ± 2% ~ (p=0.659 n=37+33) Required/Wire/Unmarshal 258ns ± 1% 251ns ± 1% -2.87% (p=0.000 n=32+38) Required/Wire/Unmarshal-12 44.3ns ± 2% 42.4ns ± 1% -4.36% (p=0.000 n=36+37) Change-Id: Ib1cb74d3e348355a6a2f66aecf8fdc4b58cd84d4 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/216420 Reviewed-by: Joe Tsai <joetsai@google.com>
This commit is contained in:
parent
ce8f7f6353
commit
170b2bfca6
@ -143,9 +143,10 @@ func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Numbe
|
|||||||
var o unmarshalOutput
|
var o unmarshalOutput
|
||||||
o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
|
o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
|
||||||
n = o.n
|
n = o.n
|
||||||
if reqi := f.validation.requiredIndex; reqi > 0 && err == nil {
|
if err != nil {
|
||||||
requiredMask |= 1 << (reqi - 1)
|
break
|
||||||
}
|
}
|
||||||
|
requiredMask |= f.validation.requiredBit
|
||||||
if f.funcs.isInit != nil && !o.initialized {
|
if f.funcs.isInit != nil && !o.initialized {
|
||||||
initialized = false
|
initialized = false
|
||||||
}
|
}
|
||||||
|
@ -77,11 +77,13 @@ type validationInfo struct {
|
|||||||
typ validationType
|
typ validationType
|
||||||
keyType, valType validationType
|
keyType, valType validationType
|
||||||
|
|
||||||
// For non-required fields, requiredIndex is 0.
|
// For non-required fields, requiredBit is 0.
|
||||||
//
|
//
|
||||||
// For required fields, requiredIndex is unique index in the range
|
// For required fields, requiredBit's nth bit is set, where n is a
|
||||||
// (0, MessageInfo.numRequiredFields].
|
// unique index in the range [0, MessageInfo.numRequiredFields).
|
||||||
requiredIndex uint8
|
//
|
||||||
|
// If there are more than 64 required fields, requiredBit is 0.
|
||||||
|
requiredBit uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type validationType uint8
|
type validationType uint8
|
||||||
@ -131,7 +133,7 @@ func newFieldValidationInfo(mi *MessageInfo, si structInfo, fd pref.FieldDescrip
|
|||||||
// of the required fields past 64.
|
// of the required fields past 64.
|
||||||
if mi.numRequiredFields < math.MaxUint8 {
|
if mi.numRequiredFields < math.MaxUint8 {
|
||||||
mi.numRequiredFields++
|
mi.numRequiredFields++
|
||||||
vi.requiredIndex = mi.numRequiredFields
|
vi.requiredBit = 1 << (mi.numRequiredFields - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vi
|
return vi
|
||||||
@ -272,7 +274,7 @@ State:
|
|||||||
case 2:
|
case 2:
|
||||||
vi.typ = st.valType
|
vi.typ = st.valType
|
||||||
vi.mi = st.mi
|
vi.mi = st.mi
|
||||||
vi.requiredIndex = 1
|
vi.requiredBit = 1
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
var f *coderFieldInfo
|
var f *coderFieldInfo
|
||||||
@ -321,7 +323,7 @@ State:
|
|||||||
vi = getExtensionFieldInfo(xt).validation
|
vi = getExtensionFieldInfo(xt).validation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if vi.requiredIndex > 0 {
|
if vi.requiredBit != 0 {
|
||||||
// Check that the field has a compatible wire type.
|
// Check that the field has a compatible wire type.
|
||||||
// We only need to consider non-repeated field types,
|
// We only need to consider non-repeated field types,
|
||||||
// since repeated fields (and maps) can never be required.
|
// since repeated fields (and maps) can never be required.
|
||||||
@ -337,7 +339,7 @@ State:
|
|||||||
ok = wtyp == wire.BytesType
|
ok = wtyp == wire.BytesType
|
||||||
}
|
}
|
||||||
if ok {
|
if ok {
|
||||||
st.requiredMask |= 1 << (vi.requiredIndex - 1)
|
st.requiredMask |= vi.requiredBit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch vi.typ {
|
switch vi.typ {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user