goprotobuf: Several optimisations:
- avoid allocation in dec_slice_struct.
- store backpointer to StructProperties in Properties to avoid calls to GetProperties.
- speed up XXX_unrecognized operations.
R=adg
CC=golang-dev
http://codereview.appspot.com/6450135
diff --git a/proto/decode.go b/proto/decode.go
index c5b1ad7..1929747 100644
--- a/proto/decode.go
+++ b/proto/decode.go
@@ -213,7 +213,7 @@
// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
// If the protocol buffer has extensions, and the field matches, add it as an extension.
// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
-func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base uintptr) error {
+func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base, unrecOffset uintptr) error {
oi := o.index
@@ -222,13 +222,11 @@
return err
}
- x := fieldIndex(t, "XXX_unrecognized")
- if x == nil {
+ if unrecOffset == 0 {
return nil
}
- p := propByIndex(t, x)
- ptr := (*[]byte)(unsafe.Pointer(base + p.offset))
+ ptr := (*[]byte)(unsafe.Pointer(base + unrecOffset))
if *ptr == nil {
// This is the first skipped element,
@@ -286,6 +284,8 @@
}
// Unmarshaler is the interface representing objects that can unmarshal themselves.
+// The argument points to data that may be overwritten, so implementations should
+// not keep references to the buffer.
type Unmarshaler interface {
Unmarshal([]byte) error
}
@@ -333,7 +333,7 @@
return err
}
- err = p.unmarshalType(typ, false, base)
+ err = p.unmarshalType(typ, GetProperties(typ.Elem()), false, base)
if collectStats {
stats.Decode++
@@ -343,9 +343,8 @@
}
// unmarshalType does the work of unmarshaling a structure.
-func (o *Buffer) unmarshalType(t reflect.Type, is_group bool, base uintptr) error {
+func (o *Buffer) unmarshalType(t reflect.Type, prop *StructProperties, is_group bool, base uintptr) error {
st := t.Elem()
- prop := GetProperties(st)
required, reqFields := prop.reqCount, uint64(0)
var err error
@@ -379,7 +378,7 @@
}
continue
}
- err = o.skipAndSave(st, tag, wire, base)
+ err = o.skipAndSave(st, tag, wire, base, prop.unrecOffset)
continue
}
p := prop.Prop[fieldnum]
@@ -656,7 +655,7 @@
structv := unsafe.Pointer(bas)
*ptr = (*struct{})(structv)
- err := o.unmarshalType(p.stype, true, bas)
+ err := o.unmarshalType(p.stype, p.sprop, true, bas)
return err
}
@@ -685,7 +684,7 @@
o.buf = raw
o.index = 0
- err = o.unmarshalType(p.stype, false, bas)
+ err = o.unmarshalType(p.stype, p.sprop, false, bas)
o.buf = obuf
o.index = oi
@@ -715,11 +714,11 @@
*v = y
if is_group {
- err := o.unmarshalType(p.stype, is_group, bas)
+ err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
return err
}
- raw, err := o.DecodeRawBytes(true)
+ raw, err := o.DecodeRawBytes(false)
if err != nil {
return err
}
@@ -735,7 +734,7 @@
o.buf = raw
o.index = 0
- err = o.unmarshalType(p.stype, is_group, bas)
+ err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
o.buf = obuf
o.index = oi