Skip to content

Commit

Permalink
improve complex pack performance
Browse files Browse the repository at this point in the history
  • Loading branch information
lunixbochs committed Nov 22, 2015
1 parent bdb3710 commit 96dd83d
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 23 deletions.
26 changes: 13 additions & 13 deletions field.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (f *Field) Size(val reflect.Value) int {
}
}

func (f *Field) packVal(buf []byte, val reflect.Value, length int) error {
func (f *Field) packVal(buf []byte, val reflect.Value, length int) (size int, err error) {
order := f.Order
if f.Ptr {
val = val.Elem()
Expand All @@ -79,6 +79,7 @@ func (f *Field) packVal(buf []byte, val reflect.Value, length int) error {
case Struct:
return f.Fields.Pack(buf, val)
case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
size = f.Type.Size()
var n uint64
switch f.kind {
case reflect.Bool:
Expand Down Expand Up @@ -109,6 +110,7 @@ func (f *Field) packVal(buf []byte, val reflect.Value, length int) error {
order.PutUint64(buf, uint64(n))
}
case Float32, Float64:
size = f.Type.Size()
n := val.Float()
switch f.Type {
case Float32:
Expand All @@ -119,42 +121,40 @@ func (f *Field) packVal(buf []byte, val reflect.Value, length int) error {
case String:
switch f.kind {
case reflect.String:
size = val.Len()
copy(buf, []byte(val.String()))
default:
// TODO: handle kind != bytes here
size = val.Len()
copy(buf, val.Bytes())
}
}
return nil
return
}

func (f *Field) Pack(buf []byte, val reflect.Value, length int) error {
func (f *Field) Pack(buf []byte, val reflect.Value, length int) (int, error) {
if f.Type == Pad {
for i := 0; i < length; i++ {
buf[i] = 0
}
return nil
return length, nil
}
if f.Slice {
// special case byte slices for performance
if !f.Array && f.Type == Uint8 && f.defType == Uint8 {
copy(buf, val.Bytes())
return nil
return val.Len(), nil
}
pos := 0
for i := 0; i < length; i++ {
cur := val.Index(i)
if err := f.packVal(buf[pos:], cur, 1); err != nil {
return err
}
// TODO: make packVal() return the length?
if f.Type == Struct {
pos += f.Fields.Sizeof(cur)
if n, err := f.packVal(buf[pos:], cur, 1); err != nil {
return pos, err
} else {
pos += f.Type.Size()
pos += n
}
}
return nil
return pos, nil
} else {
return f.packVal(buf, val, length)
}
Expand Down
12 changes: 6 additions & 6 deletions fields.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (f Fields) Sizeof(val reflect.Value) int {
return size
}

func (f Fields) Pack(buf []byte, val reflect.Value) error {
func (f Fields) Pack(buf []byte, val reflect.Value) (int, error) {
for val.Kind() == reflect.Ptr {
val = val.Elem()
}
Expand All @@ -58,13 +58,13 @@ func (f Fields) Pack(buf []byte, val reflect.Value) error {
length := val.FieldByIndex(field.Sizeof).Len()
v = reflect.ValueOf(length)
}
err := field.Pack(buf[pos:], v, length)
if err != nil {
return err
if n, err := field.Pack(buf[pos:], v, length); err != nil {
return n, err
} else {
pos += n
}
pos += field.Size(v)
}
return nil
return pos, nil
}

func (f Fields) Unpack(r io.Reader, val reflect.Value) error {
Expand Down
7 changes: 4 additions & 3 deletions packable.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type Packable interface {
SetByteOrder(order binary.ByteOrder)
String() string
Sizeof(val reflect.Value) int
Pack(buf []byte, val reflect.Value) error
Pack(buf []byte, val reflect.Value) (int, error)
Unpack(r io.Reader, val reflect.Value) error
}

Expand All @@ -48,9 +48,10 @@ func (b *binaryFallback) Sizeof(val reflect.Value) int {
return binary.Size(val.Interface())
}

func (b *binaryFallback) Pack(buf []byte, val reflect.Value) error {
func (b *binaryFallback) Pack(buf []byte, val reflect.Value) (int, error) {
tmp := byteWriter{buf: buf}
return binary.Write(tmp, b.order, val.Interface())
err := binary.Write(tmp, b.order, val.Interface())
return tmp.pos, err
}

func (b *binaryFallback) Unpack(r io.Reader, val reflect.Value) error {
Expand Down
2 changes: 1 addition & 1 deletion struc.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func PackWithOrder(w io.Writer, data interface{}, order binary.ByteOrder) error
}
size := fields.Sizeof(val)
buf := make([]byte, size)
if err := fields.Pack(buf, val); err != nil {
if _, err := fields.Pack(buf, val); err != nil {
return err
}
_, err = w.Write(buf)
Expand Down

0 comments on commit 96dd83d

Please sign in to comment.