Improve XDR performance

This commit is contained in:
Jakob Borg 2014-06-30 13:33:52 +02:00
parent 7633b9672f
commit b57f4ed97e
7 changed files with 186 additions and 97 deletions

View File

@ -13,10 +13,10 @@ func (o QueryV2) EncodeXDR(w io.Writer) (int, error) {
} }
func (o QueryV2) MarshalXDR() []byte { func (o QueryV2) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o QueryV2) encodeXDR(xw *xdr.Writer) (int, error) { func (o QueryV2) encodeXDR(xw *xdr.Writer) (int, error) {
@ -34,8 +34,8 @@ func (o *QueryV2) DecodeXDR(r io.Reader) error {
} }
func (o *QueryV2) UnmarshalXDR(bs []byte) error { func (o *QueryV2) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -51,10 +51,10 @@ func (o AnnounceV2) EncodeXDR(w io.Writer) (int, error) {
} }
func (o AnnounceV2) MarshalXDR() []byte { func (o AnnounceV2) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o AnnounceV2) encodeXDR(xw *xdr.Writer) (int, error) { func (o AnnounceV2) encodeXDR(xw *xdr.Writer) (int, error) {
@ -76,8 +76,8 @@ func (o *AnnounceV2) DecodeXDR(r io.Reader) error {
} }
func (o *AnnounceV2) UnmarshalXDR(bs []byte) error { func (o *AnnounceV2) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -101,10 +101,10 @@ func (o Node) EncodeXDR(w io.Writer) (int, error) {
} }
func (o Node) MarshalXDR() []byte { func (o Node) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o Node) encodeXDR(xw *xdr.Writer) (int, error) { func (o Node) encodeXDR(xw *xdr.Writer) (int, error) {
@ -128,8 +128,8 @@ func (o *Node) DecodeXDR(r io.Reader) error {
} }
func (o *Node) UnmarshalXDR(bs []byte) error { func (o *Node) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -152,10 +152,10 @@ func (o Address) EncodeXDR(w io.Writer) (int, error) {
} }
func (o Address) MarshalXDR() []byte { func (o Address) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o Address) encodeXDR(xw *xdr.Writer) (int, error) { func (o Address) encodeXDR(xw *xdr.Writer) (int, error) {
@ -173,8 +173,8 @@ func (o *Address) DecodeXDR(r io.Reader) error {
} }
func (o *Address) UnmarshalXDR(bs []byte) error { func (o *Address) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }

View File

@ -13,10 +13,10 @@ func (o IndexMessage) EncodeXDR(w io.Writer) (int, error) {
} }
func (o IndexMessage) MarshalXDR() []byte { func (o IndexMessage) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o IndexMessage) encodeXDR(xw *xdr.Writer) (int, error) { func (o IndexMessage) encodeXDR(xw *xdr.Writer) (int, error) {
@ -40,8 +40,8 @@ func (o *IndexMessage) DecodeXDR(r io.Reader) error {
} }
func (o *IndexMessage) UnmarshalXDR(bs []byte) error { func (o *IndexMessage) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -64,10 +64,10 @@ func (o FileInfo) EncodeXDR(w io.Writer) (int, error) {
} }
func (o FileInfo) MarshalXDR() []byte { func (o FileInfo) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o FileInfo) encodeXDR(xw *xdr.Writer) (int, error) { func (o FileInfo) encodeXDR(xw *xdr.Writer) (int, error) {
@ -94,8 +94,8 @@ func (o *FileInfo) DecodeXDR(r io.Reader) error {
} }
func (o *FileInfo) UnmarshalXDR(bs []byte) error { func (o *FileInfo) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -121,10 +121,10 @@ func (o BlockInfo) EncodeXDR(w io.Writer) (int, error) {
} }
func (o BlockInfo) MarshalXDR() []byte { func (o BlockInfo) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o BlockInfo) encodeXDR(xw *xdr.Writer) (int, error) { func (o BlockInfo) encodeXDR(xw *xdr.Writer) (int, error) {
@ -142,8 +142,8 @@ func (o *BlockInfo) DecodeXDR(r io.Reader) error {
} }
func (o *BlockInfo) UnmarshalXDR(bs []byte) error { func (o *BlockInfo) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -159,10 +159,10 @@ func (o RequestMessage) EncodeXDR(w io.Writer) (int, error) {
} }
func (o RequestMessage) MarshalXDR() []byte { func (o RequestMessage) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o RequestMessage) encodeXDR(xw *xdr.Writer) (int, error) { func (o RequestMessage) encodeXDR(xw *xdr.Writer) (int, error) {
@ -185,8 +185,8 @@ func (o *RequestMessage) DecodeXDR(r io.Reader) error {
} }
func (o *RequestMessage) UnmarshalXDR(bs []byte) error { func (o *RequestMessage) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -204,10 +204,10 @@ func (o ClusterConfigMessage) EncodeXDR(w io.Writer) (int, error) {
} }
func (o ClusterConfigMessage) MarshalXDR() []byte { func (o ClusterConfigMessage) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o ClusterConfigMessage) encodeXDR(xw *xdr.Writer) (int, error) { func (o ClusterConfigMessage) encodeXDR(xw *xdr.Writer) (int, error) {
@ -242,8 +242,8 @@ func (o *ClusterConfigMessage) DecodeXDR(r io.Reader) error {
} }
func (o *ClusterConfigMessage) UnmarshalXDR(bs []byte) error { func (o *ClusterConfigMessage) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -275,10 +275,10 @@ func (o Repository) EncodeXDR(w io.Writer) (int, error) {
} }
func (o Repository) MarshalXDR() []byte { func (o Repository) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o Repository) encodeXDR(xw *xdr.Writer) (int, error) { func (o Repository) encodeXDR(xw *xdr.Writer) (int, error) {
@ -302,8 +302,8 @@ func (o *Repository) DecodeXDR(r io.Reader) error {
} }
func (o *Repository) UnmarshalXDR(bs []byte) error { func (o *Repository) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -326,10 +326,10 @@ func (o Node) EncodeXDR(w io.Writer) (int, error) {
} }
func (o Node) MarshalXDR() []byte { func (o Node) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o Node) encodeXDR(xw *xdr.Writer) (int, error) { func (o Node) encodeXDR(xw *xdr.Writer) (int, error) {
@ -348,8 +348,8 @@ func (o *Node) DecodeXDR(r io.Reader) error {
} }
func (o *Node) UnmarshalXDR(bs []byte) error { func (o *Node) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -366,10 +366,10 @@ func (o Option) EncodeXDR(w io.Writer) (int, error) {
} }
func (o Option) MarshalXDR() []byte { func (o Option) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o Option) encodeXDR(xw *xdr.Writer) (int, error) { func (o Option) encodeXDR(xw *xdr.Writer) (int, error) {
@ -390,8 +390,8 @@ func (o *Option) DecodeXDR(r io.Reader) error {
} }
func (o *Option) UnmarshalXDR(bs []byte) error { func (o *Option) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }

View File

@ -5,25 +5,30 @@
package xdr_test package xdr_test
import ( import (
"bytes" "io"
"io/ioutil"
"testing" "testing"
) )
type XDRBenchStruct struct { type XDRBenchStruct struct {
I1 uint64 I1 uint64
I2 uint32 I2 uint32
I3 uint16 I3 uint16
Bs []byte Bs0 []byte // max:128
S string Bs1 []byte
S0 string // max:128
S1 string
} }
var res []byte // no to be optimized away var res []byte // no to be optimized away
var s = XDRBenchStruct{ var s = XDRBenchStruct{
I1: 42, I1: 42,
I2: 43, I2: 43,
I3: 44, I3: 44,
Bs: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, Bs0: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18},
S: "Hello World!", Bs1: []byte{11, 12, 13, 14, 15, 16, 17, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
S0: "Hello World! String one.",
S1: "Hello World! String two.",
} }
var e = s.MarshalXDR() var e = s.MarshalXDR()
@ -43,15 +48,40 @@ func BenchmarkThisUnmarshal(b *testing.B) {
} }
} }
func BenchmarkEncode(b *testing.B) { func BenchmarkThisEncode(b *testing.B) {
bs := make([]byte, 0, 65536)
buf := bytes.NewBuffer(bs)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, err := s.EncodeXDR(buf) _, err := s.EncodeXDR(ioutil.Discard)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
buf.Reset() }
}
type repeatReader struct {
data []byte
}
func (r *repeatReader) Read(bs []byte) (n int, err error) {
if len(bs) > len(r.data) {
err = io.EOF
}
n = copy(bs, r.data)
r.data = r.data[n:]
return n, err
}
func (r *repeatReader) Reset(bs []byte) {
r.data = bs
}
func BenchmarkThisDecode(b *testing.B) {
rr := &repeatReader{e}
var t XDRBenchStruct
for i := 0; i < b.N; i++ {
err := t.DecodeXDR(rr)
if err != nil {
b.Fatal(err)
}
rr.Reset(e)
} }
} }

View File

@ -1,7 +1,3 @@
// Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
// Use of this source code is governed by an MIT-style license that can be
// found in the LICENSE file.
package xdr_test package xdr_test
import ( import (
@ -17,18 +13,26 @@ func (o XDRBenchStruct) EncodeXDR(w io.Writer) (int, error) {
} }
func (o XDRBenchStruct) MarshalXDR() []byte { func (o XDRBenchStruct) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
} }
func (o XDRBenchStruct) encodeXDR(xw *xdr.Writer) (int, error) { func (o XDRBenchStruct) encodeXDR(xw *xdr.Writer) (int, error) {
xw.WriteUint64(o.I1) xw.WriteUint64(o.I1)
xw.WriteUint32(o.I2) xw.WriteUint32(o.I2)
xw.WriteUint16(o.I3) xw.WriteUint16(o.I3)
xw.WriteBytes(o.Bs) if len(o.Bs0) > 128 {
xw.WriteString(o.S) return xw.Tot(), xdr.ErrElementSizeExceeded
}
xw.WriteBytes(o.Bs0)
xw.WriteBytes(o.Bs1)
if len(o.S0) > 128 {
return xw.Tot(), xdr.ErrElementSizeExceeded
}
xw.WriteString(o.S0)
xw.WriteString(o.S1)
return xw.Tot(), xw.Error() return xw.Tot(), xw.Error()
} }
@ -38,8 +42,8 @@ func (o *XDRBenchStruct) DecodeXDR(r io.Reader) error {
} }
func (o *XDRBenchStruct) UnmarshalXDR(bs []byte) error { func (o *XDRBenchStruct) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
} }
@ -47,7 +51,42 @@ func (o *XDRBenchStruct) decodeXDR(xr *xdr.Reader) error {
o.I1 = xr.ReadUint64() o.I1 = xr.ReadUint64()
o.I2 = xr.ReadUint32() o.I2 = xr.ReadUint32()
o.I3 = xr.ReadUint16() o.I3 = xr.ReadUint16()
o.Bs = xr.ReadBytes() o.Bs0 = xr.ReadBytesMax(128)
o.S = xr.ReadString() o.Bs1 = xr.ReadBytes()
o.S0 = xr.ReadStringMax(128)
o.S1 = xr.ReadString()
return xr.Error()
}
func (o repeatReader) EncodeXDR(w io.Writer) (int, error) {
var xw = xdr.NewWriter(w)
return o.encodeXDR(xw)
}
func (o repeatReader) MarshalXDR() []byte {
var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw)
return []byte(aw)
}
func (o repeatReader) encodeXDR(xw *xdr.Writer) (int, error) {
xw.WriteBytes(o.data)
return xw.Tot(), xw.Error()
}
func (o *repeatReader) DecodeXDR(r io.Reader) error {
xr := xdr.NewReader(r)
return o.decodeXDR(xr)
}
func (o *repeatReader) UnmarshalXDR(bs []byte) error {
var br = bytes.NewReader(bs)
var xr = xdr.NewReader(br)
return o.decodeXDR(xr)
}
func (o *repeatReader) decodeXDR(xr *xdr.Reader) error {
o.data = xr.ReadBytes()
return xr.Error() return xr.Error()
} }

View File

@ -50,10 +50,10 @@ func (o {{.TypeName}}) EncodeXDR(w io.Writer) (int, error) {
}//+n }//+n
func (o {{.TypeName}}) MarshalXDR() []byte { func (o {{.TypeName}}) MarshalXDR() []byte {
var buf bytes.Buffer var aw = make(xdr.AppendWriter, 0, 128)
var xw = xdr.NewWriter(&buf) var xw = xdr.NewWriter(&aw)
o.encodeXDR(xw) o.encodeXDR(xw)
return buf.Bytes() return []byte(aw)
}//+n }//+n
func (o {{.TypeName}}) encodeXDR(xw *xdr.Writer) (int, error) { func (o {{.TypeName}}) encodeXDR(xw *xdr.Writer) (int, error) {
@ -98,8 +98,8 @@ func (o *{{.TypeName}}) DecodeXDR(r io.Reader) error {
}//+n }//+n
func (o *{{.TypeName}}) UnmarshalXDR(bs []byte) error { func (o *{{.TypeName}}) UnmarshalXDR(bs []byte) error {
var buf = bytes.NewBuffer(bs) var br = bytes.NewReader(bs)
var xr = xdr.NewReader(buf) var xr = xdr.NewReader(br)
return o.decodeXDR(xr) return o.decodeXDR(xr)
}//+n }//+n

View File

@ -17,6 +17,7 @@ type Reader struct {
tot int tot int
err error err error
b [8]byte b [8]byte
sb []byte
last time.Time last time.Time
} }
@ -27,11 +28,23 @@ func NewReader(r io.Reader) *Reader {
} }
func (r *Reader) ReadString() string { func (r *Reader) ReadString() string {
return string(r.ReadBytes()) if r.sb == nil {
r.sb = make([]byte, 64)
} else {
r.sb = r.sb[:cap(r.sb)]
}
r.sb = r.ReadBytesInto(r.sb)
return string(r.sb)
} }
func (r *Reader) ReadStringMax(max int) string { func (r *Reader) ReadStringMax(max int) string {
return string(r.ReadBytesMax(max)) if r.sb == nil {
r.sb = make([]byte, 64)
} else {
r.sb = r.sb[:cap(r.sb)]
}
r.sb = r.ReadBytesMaxInto(max, r.sb)
return string(r.sb)
} }
func (r *Reader) ReadBytes() []byte { func (r *Reader) ReadBytes() []byte {

View File

@ -27,6 +27,13 @@ type Writer struct {
last time.Time last time.Time
} }
type AppendWriter []byte
func (w *AppendWriter) Write(bs []byte) (int, error) {
*w = append(*w, bs...)
return len(bs), nil
}
func NewWriter(w io.Writer) *Writer { func NewWriter(w io.Writer) *Writer {
return &Writer{ return &Writer{
w: w, w: w,