Commit 5df1cf04 authored by Rob Pike's avatar Rob Pike

gob: use bufio on the decode to avoid a system call on each read.

Add a benchmark.
BenchmarkEndToEndPipe gives 14.3microseconds/op before,
13.1microseconds/op after, or about 76e3 round trips per second
through the kernel.
With a bytes buffer, and therefore no system calls for I/O, the
numbers go to 7.3microseconds/op, or about 137e3 round trips
per second.

R=rsc
CC=golang-dev
https://golang.org/cl/4279045
parent c734b50b
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package gob package gob
import ( import (
"bufio"
"bytes" "bytes"
"io" "io"
"os" "os"
...@@ -30,7 +31,7 @@ type Decoder struct { ...@@ -30,7 +31,7 @@ type Decoder struct {
// NewDecoder returns a new decoder that reads from the io.Reader. // NewDecoder returns a new decoder that reads from the io.Reader.
func NewDecoder(r io.Reader) *Decoder { func NewDecoder(r io.Reader) *Decoder {
dec := new(Decoder) dec := new(Decoder)
dec.r = r dec.r = bufio.NewReader(r)
dec.wireType = make(map[typeId]*wireType) dec.wireType = make(map[typeId]*wireType)
dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine) dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
dec.ignorerCache = make(map[typeId]**decEngine) dec.ignorerCache = make(map[typeId]**decEngine)
......
...@@ -514,3 +514,39 @@ func TestNestedInterfaces(t *testing.T) { ...@@ -514,3 +514,39 @@ func TestNestedInterfaces(t *testing.T) {
t.Fatalf("final value %d; expected %d", inner.A, 7) t.Fatalf("final value %d; expected %d", inner.A, 7)
} }
} }
type Bench struct {
A int
B float64
C string
D []byte
}
func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) {
b.StopTimer()
enc := NewEncoder(w)
dec := NewDecoder(r)
bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
b.StartTimer()
for i := 0; i < b.N; i++ {
if enc.Encode(bench) != nil {
panic("encode error")
}
if dec.Decode(bench) != nil {
panic("decode error")
}
}
}
func BenchmarkEndToEndPipe(b *testing.B) {
r, w, err := os.Pipe()
if err != nil {
panic("can't get pipe:" + err.String())
}
benchmarkEndToEnd(r, w, b)
}
func BenchmarkEndToEndByteBuffer(b *testing.B) {
var buf bytes.Buffer
benchmarkEndToEnd(&buf, &buf, b)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment