2012-03-27 23:13:14 +00:00
|
|
|
// Copyright 2011 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package gob
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"runtime"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Bench struct {
|
|
|
|
A int
|
|
|
|
B float64
|
|
|
|
C string
|
|
|
|
D []byte
|
|
|
|
}
|
|
|
|
|
2015-08-28 15:33:40 +00:00
|
|
|
func benchmarkEndToEnd(b *testing.B, ctor func() interface{}, pipe func() (r io.Reader, w io.Writer, err error)) {
|
|
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
|
|
r, w, err := pipe()
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal("can't get pipe:", err)
|
2012-03-27 23:13:14 +00:00
|
|
|
}
|
2015-08-28 15:33:40 +00:00
|
|
|
v := ctor()
|
|
|
|
enc := NewEncoder(w)
|
|
|
|
dec := NewDecoder(r)
|
|
|
|
for pb.Next() {
|
|
|
|
if err := enc.Encode(v); err != nil {
|
|
|
|
b.Fatal("encode error:", err)
|
|
|
|
}
|
|
|
|
if err := dec.Decode(v); err != nil {
|
|
|
|
b.Fatal("decode error:", err)
|
|
|
|
}
|
2012-03-27 23:13:14 +00:00
|
|
|
}
|
2015-08-28 15:33:40 +00:00
|
|
|
})
|
2012-03-27 23:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkEndToEndPipe(b *testing.B) {
|
2015-08-28 15:33:40 +00:00
|
|
|
benchmarkEndToEnd(b, func() interface{} {
|
|
|
|
return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)}
|
|
|
|
}, func() (r io.Reader, w io.Writer, err error) {
|
|
|
|
r, w, err = os.Pipe()
|
|
|
|
return
|
|
|
|
})
|
2012-03-27 23:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkEndToEndByteBuffer(b *testing.B) {
|
2015-08-28 15:33:40 +00:00
|
|
|
benchmarkEndToEnd(b, func() interface{} {
|
|
|
|
return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)}
|
|
|
|
}, func() (r io.Reader, w io.Writer, err error) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
return &buf, &buf, nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkEndToEndSliceByteBuffer(b *testing.B) {
|
|
|
|
benchmarkEndToEnd(b, func() interface{} {
|
|
|
|
v := &Bench{7, 3.2, "now is the time", nil}
|
|
|
|
Register(v)
|
|
|
|
arr := make([]interface{}, 100)
|
|
|
|
for i := range arr {
|
|
|
|
arr[i] = v
|
|
|
|
}
|
|
|
|
return &arr
|
|
|
|
}, func() (r io.Reader, w io.Writer, err error) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
return &buf, &buf, nil
|
|
|
|
})
|
2012-03-27 23:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCountEncodeMallocs(t *testing.T) {
|
2014-09-21 17:33:12 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping malloc count in short mode")
|
|
|
|
}
|
|
|
|
if runtime.GOMAXPROCS(0) > 1 {
|
|
|
|
t.Skip("skipping; GOMAXPROCS>1")
|
|
|
|
}
|
|
|
|
|
|
|
|
const N = 1000
|
|
|
|
|
2012-03-27 23:13:14 +00:00
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
|
2014-09-21 17:33:12 +00:00
|
|
|
|
|
|
|
allocs := testing.AllocsPerRun(N, func() {
|
2012-03-27 23:13:14 +00:00
|
|
|
err := enc.Encode(bench)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("encode:", err)
|
|
|
|
}
|
2014-09-21 17:33:12 +00:00
|
|
|
})
|
|
|
|
if allocs != 0 {
|
|
|
|
t.Fatalf("mallocs per encode of type Bench: %v; wanted 0\n", allocs)
|
2012-03-27 23:13:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCountDecodeMallocs(t *testing.T) {
|
2014-09-21 17:33:12 +00:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping malloc count in short mode")
|
|
|
|
}
|
|
|
|
if runtime.GOMAXPROCS(0) > 1 {
|
|
|
|
t.Skip("skipping; GOMAXPROCS>1")
|
|
|
|
}
|
|
|
|
|
|
|
|
const N = 1000
|
|
|
|
|
2012-03-27 23:13:14 +00:00
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
|
2014-09-21 17:33:12 +00:00
|
|
|
|
|
|
|
// Fill the buffer with enough to decode
|
|
|
|
testing.AllocsPerRun(N, func() {
|
2012-03-27 23:13:14 +00:00
|
|
|
err := enc.Encode(bench)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("encode:", err)
|
|
|
|
}
|
2014-09-21 17:33:12 +00:00
|
|
|
})
|
|
|
|
|
2012-03-27 23:13:14 +00:00
|
|
|
dec := NewDecoder(&buf)
|
2014-09-21 17:33:12 +00:00
|
|
|
allocs := testing.AllocsPerRun(N, func() {
|
2012-03-27 23:13:14 +00:00
|
|
|
*bench = Bench{}
|
|
|
|
err := dec.Decode(&bench)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("decode:", err)
|
|
|
|
}
|
2014-09-21 17:33:12 +00:00
|
|
|
})
|
2015-08-28 15:33:40 +00:00
|
|
|
if allocs != 4 {
|
|
|
|
t.Fatalf("mallocs per decode of type Bench: %v; wanted 4\n", allocs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkEncodeComplex128Slice(b *testing.B) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
a := make([]complex128, 1000)
|
|
|
|
for i := range a {
|
|
|
|
a[i] = 1.2 + 3.4i
|
|
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
buf.Reset()
|
|
|
|
err := enc.Encode(a)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkEncodeFloat64Slice(b *testing.B) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
a := make([]float64, 1000)
|
|
|
|
for i := range a {
|
|
|
|
a[i] = 1.23e4
|
|
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
buf.Reset()
|
|
|
|
err := enc.Encode(a)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkEncodeInt32Slice(b *testing.B) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
a := make([]int32, 1000)
|
|
|
|
for i := range a {
|
|
|
|
a[i] = 1234
|
|
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
buf.Reset()
|
|
|
|
err := enc.Encode(a)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkEncodeStringSlice(b *testing.B) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
a := make([]string, 1000)
|
|
|
|
for i := range a {
|
|
|
|
a[i] = "now is the time"
|
|
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
buf.Reset()
|
|
|
|
err := enc.Encode(a)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// benchmarkBuf is a read buffer we can reset
|
|
|
|
type benchmarkBuf struct {
|
|
|
|
offset int
|
|
|
|
data []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *benchmarkBuf) Read(p []byte) (n int, err error) {
|
|
|
|
n = copy(p, b.data[b.offset:])
|
|
|
|
if n == 0 {
|
|
|
|
return 0, io.EOF
|
|
|
|
}
|
|
|
|
b.offset += n
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *benchmarkBuf) ReadByte() (c byte, err error) {
|
|
|
|
if b.offset >= len(b.data) {
|
|
|
|
return 0, io.EOF
|
|
|
|
}
|
|
|
|
c = b.data[b.offset]
|
|
|
|
b.offset++
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *benchmarkBuf) reset() {
|
|
|
|
b.offset = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkDecodeComplex128Slice(b *testing.B) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
a := make([]complex128, 1000)
|
|
|
|
for i := range a {
|
|
|
|
a[i] = 1.2 + 3.4i
|
|
|
|
}
|
|
|
|
err := enc.Encode(a)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
x := make([]complex128, 1000)
|
|
|
|
bbuf := benchmarkBuf{data: buf.Bytes()}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
bbuf.reset()
|
|
|
|
dec := NewDecoder(&bbuf)
|
|
|
|
err := dec.Decode(&x)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(i, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkDecodeFloat64Slice(b *testing.B) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
a := make([]float64, 1000)
|
|
|
|
for i := range a {
|
|
|
|
a[i] = 1.23e4
|
|
|
|
}
|
|
|
|
err := enc.Encode(a)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
x := make([]float64, 1000)
|
|
|
|
bbuf := benchmarkBuf{data: buf.Bytes()}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
bbuf.reset()
|
|
|
|
dec := NewDecoder(&bbuf)
|
|
|
|
err := dec.Decode(&x)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(i, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkDecodeInt32Slice(b *testing.B) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
a := make([]int32, 1000)
|
|
|
|
for i := range a {
|
|
|
|
a[i] = 1234
|
|
|
|
}
|
|
|
|
err := enc.Encode(a)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
x := make([]int32, 1000)
|
|
|
|
bbuf := benchmarkBuf{data: buf.Bytes()}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
bbuf.reset()
|
|
|
|
dec := NewDecoder(&bbuf)
|
|
|
|
err := dec.Decode(&x)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(i, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkDecodeStringSlice(b *testing.B) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
enc := NewEncoder(&buf)
|
|
|
|
a := make([]string, 1000)
|
|
|
|
for i := range a {
|
|
|
|
a[i] = "now is the time"
|
|
|
|
}
|
|
|
|
err := enc.Encode(a)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
x := make([]string, 1000)
|
|
|
|
bbuf := benchmarkBuf{data: buf.Bytes()}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
bbuf.reset()
|
|
|
|
dec := NewDecoder(&bbuf)
|
|
|
|
err := dec.Decode(&x)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(i, err)
|
|
|
|
}
|
2012-03-27 23:13:14 +00:00
|
|
|
}
|
|
|
|
}
|