Răsfoiți Sursa

Improve XDR performance

Jakob Borg 11 ani în urmă
părinte
comite
b57f4ed97e
7 a modificat fișierele cu 185 adăugiri și 96 ștergeri
  1. 20 20
      discover/packets_xdr.go
  2. 40 40
      protocol/message_xdr.go
  3. 46 16
      xdr/bench_test.go
  4. 52 13
      xdr/bench_xdr_test.go
  5. 5 5
      xdr/cmd/coder/main.go
  6. 15 2
      xdr/reader.go
  7. 7 0
      xdr/writer.go

+ 20 - 20
discover/packets_xdr.go

@@ -13,10 +13,10 @@ func (o QueryV2) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o QueryV2) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -51,10 +51,10 @@ func (o AnnounceV2) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o AnnounceV2) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -101,10 +101,10 @@ func (o Node) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o Node) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -152,10 +152,10 @@ func (o Address) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o Address) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 

+ 40 - 40
protocol/message_xdr.go

@@ -13,10 +13,10 @@ func (o IndexMessage) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o IndexMessage) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -64,10 +64,10 @@ func (o FileInfo) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o FileInfo) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -121,10 +121,10 @@ func (o BlockInfo) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o BlockInfo) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -159,10 +159,10 @@ func (o RequestMessage) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o RequestMessage) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -204,10 +204,10 @@ func (o ClusterConfigMessage) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o ClusterConfigMessage) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -275,10 +275,10 @@ func (o Repository) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o Repository) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -326,10 +326,10 @@ func (o Node) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o Node) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -366,10 +366,10 @@ func (o Option) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o Option) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 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 {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 

+ 46 - 16
xdr/bench_test.go

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

+ 52 - 13
xdr/bench_xdr_test.go

@@ -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
 
 import (
@@ -17,18 +13,26 @@ func (o XDRBenchStruct) EncodeXDR(w io.Writer) (int, error) {
 }
 
 func (o XDRBenchStruct) MarshalXDR() []byte {
-	var buf bytes.Buffer
-	var xw = xdr.NewWriter(&buf)
+	var aw = make(xdr.AppendWriter, 0, 128)
+	var xw = xdr.NewWriter(&aw)
 	o.encodeXDR(xw)
-	return buf.Bytes()
+	return []byte(aw)
 }
 
 func (o XDRBenchStruct) encodeXDR(xw *xdr.Writer) (int, error) {
 	xw.WriteUint64(o.I1)
 	xw.WriteUint32(o.I2)
 	xw.WriteUint16(o.I3)
-	xw.WriteBytes(o.Bs)
-	xw.WriteString(o.S)
+	if len(o.Bs0) > 128 {
+		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()
 }
 
@@ -38,8 +42,8 @@ func (o *XDRBenchStruct) DecodeXDR(r io.Reader) error {
 }
 
 func (o *XDRBenchStruct) UnmarshalXDR(bs []byte) error {
-	var buf = bytes.NewBuffer(bs)
-	var xr = xdr.NewReader(buf)
+	var br = bytes.NewReader(bs)
+	var xr = xdr.NewReader(br)
 	return o.decodeXDR(xr)
 }
 
@@ -47,7 +51,42 @@ func (o *XDRBenchStruct) decodeXDR(xr *xdr.Reader) error {
 	o.I1 = xr.ReadUint64()
 	o.I2 = xr.ReadUint32()
 	o.I3 = xr.ReadUint16()
-	o.Bs = xr.ReadBytes()
-	o.S = xr.ReadString()
+	o.Bs0 = xr.ReadBytesMax(128)
+	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()
 }

+ 5 - 5
xdr/cmd/coder/main.go

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

+ 15 - 2
xdr/reader.go

@@ -17,6 +17,7 @@ type Reader struct {
 	tot  int
 	err  error
 	b    [8]byte
+	sb   []byte
 	last time.Time
 }
 
@@ -27,11 +28,23 @@ func NewReader(r io.Reader) *Reader {
 }
 
 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 {
-	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 {

+ 7 - 0
xdr/writer.go

@@ -27,6 +27,13 @@ type Writer struct {
 	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 {
 	return &Writer{
 		w: w,