Home | History | Annotate | Download | only in gob
      1 // Copyright 2011 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package gob
      6 
      7 import (
      8 	"bytes"
      9 	"io"
     10 	"os"
     11 	"runtime"
     12 	"testing"
     13 )
     14 
     15 type Bench struct {
     16 	A int
     17 	B float64
     18 	C string
     19 	D []byte
     20 }
     21 
     22 func benchmarkEndToEnd(b *testing.B, ctor func() interface{}, pipe func() (r io.Reader, w io.Writer, err error)) {
     23 	b.RunParallel(func(pb *testing.PB) {
     24 		r, w, err := pipe()
     25 		if err != nil {
     26 			b.Fatal("can't get pipe:", err)
     27 		}
     28 		v := ctor()
     29 		enc := NewEncoder(w)
     30 		dec := NewDecoder(r)
     31 		for pb.Next() {
     32 			if err := enc.Encode(v); err != nil {
     33 				b.Fatal("encode error:", err)
     34 			}
     35 			if err := dec.Decode(v); err != nil {
     36 				b.Fatal("decode error:", err)
     37 			}
     38 		}
     39 	})
     40 }
     41 
     42 func BenchmarkEndToEndPipe(b *testing.B) {
     43 	benchmarkEndToEnd(b, func() interface{} {
     44 		return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)}
     45 	}, func() (r io.Reader, w io.Writer, err error) {
     46 		r, w, err = os.Pipe()
     47 		return
     48 	})
     49 }
     50 
     51 func BenchmarkEndToEndByteBuffer(b *testing.B) {
     52 	benchmarkEndToEnd(b, func() interface{} {
     53 		return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)}
     54 	}, func() (r io.Reader, w io.Writer, err error) {
     55 		var buf bytes.Buffer
     56 		return &buf, &buf, nil
     57 	})
     58 }
     59 
     60 func BenchmarkEndToEndSliceByteBuffer(b *testing.B) {
     61 	benchmarkEndToEnd(b, func() interface{} {
     62 		v := &Bench{7, 3.2, "now is the time", nil}
     63 		Register(v)
     64 		arr := make([]interface{}, 100)
     65 		for i := range arr {
     66 			arr[i] = v
     67 		}
     68 		return &arr
     69 	}, func() (r io.Reader, w io.Writer, err error) {
     70 		var buf bytes.Buffer
     71 		return &buf, &buf, nil
     72 	})
     73 }
     74 
     75 func TestCountEncodeMallocs(t *testing.T) {
     76 	if testing.Short() {
     77 		t.Skip("skipping malloc count in short mode")
     78 	}
     79 	if runtime.GOMAXPROCS(0) > 1 {
     80 		t.Skip("skipping; GOMAXPROCS>1")
     81 	}
     82 
     83 	const N = 1000
     84 
     85 	var buf bytes.Buffer
     86 	enc := NewEncoder(&buf)
     87 	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
     88 
     89 	allocs := testing.AllocsPerRun(N, func() {
     90 		err := enc.Encode(bench)
     91 		if err != nil {
     92 			t.Fatal("encode:", err)
     93 		}
     94 	})
     95 	if allocs != 0 {
     96 		t.Fatalf("mallocs per encode of type Bench: %v; wanted 0\n", allocs)
     97 	}
     98 }
     99 
    100 func TestCountDecodeMallocs(t *testing.T) {
    101 	if testing.Short() {
    102 		t.Skip("skipping malloc count in short mode")
    103 	}
    104 	if runtime.GOMAXPROCS(0) > 1 {
    105 		t.Skip("skipping; GOMAXPROCS>1")
    106 	}
    107 
    108 	const N = 1000
    109 
    110 	var buf bytes.Buffer
    111 	enc := NewEncoder(&buf)
    112 	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
    113 
    114 	// Fill the buffer with enough to decode
    115 	testing.AllocsPerRun(N, func() {
    116 		err := enc.Encode(bench)
    117 		if err != nil {
    118 			t.Fatal("encode:", err)
    119 		}
    120 	})
    121 
    122 	dec := NewDecoder(&buf)
    123 	allocs := testing.AllocsPerRun(N, func() {
    124 		*bench = Bench{}
    125 		err := dec.Decode(&bench)
    126 		if err != nil {
    127 			t.Fatal("decode:", err)
    128 		}
    129 	})
    130 	if allocs != 4 {
    131 		t.Fatalf("mallocs per decode of type Bench: %v; wanted 4\n", allocs)
    132 	}
    133 }
    134 
    135 func BenchmarkEncodeComplex128Slice(b *testing.B) {
    136 	var buf bytes.Buffer
    137 	enc := NewEncoder(&buf)
    138 	a := make([]complex128, 1000)
    139 	for i := range a {
    140 		a[i] = 1.2 + 3.4i
    141 	}
    142 	b.ResetTimer()
    143 	for i := 0; i < b.N; i++ {
    144 		buf.Reset()
    145 		err := enc.Encode(a)
    146 		if err != nil {
    147 			b.Fatal(err)
    148 		}
    149 	}
    150 }
    151 
    152 func BenchmarkEncodeFloat64Slice(b *testing.B) {
    153 	var buf bytes.Buffer
    154 	enc := NewEncoder(&buf)
    155 	a := make([]float64, 1000)
    156 	for i := range a {
    157 		a[i] = 1.23e4
    158 	}
    159 	b.ResetTimer()
    160 	for i := 0; i < b.N; i++ {
    161 		buf.Reset()
    162 		err := enc.Encode(a)
    163 		if err != nil {
    164 			b.Fatal(err)
    165 		}
    166 	}
    167 }
    168 
    169 func BenchmarkEncodeInt32Slice(b *testing.B) {
    170 	var buf bytes.Buffer
    171 	enc := NewEncoder(&buf)
    172 	a := make([]int32, 1000)
    173 	for i := range a {
    174 		a[i] = 1234
    175 	}
    176 	b.ResetTimer()
    177 	for i := 0; i < b.N; i++ {
    178 		buf.Reset()
    179 		err := enc.Encode(a)
    180 		if err != nil {
    181 			b.Fatal(err)
    182 		}
    183 	}
    184 }
    185 
    186 func BenchmarkEncodeStringSlice(b *testing.B) {
    187 	var buf bytes.Buffer
    188 	enc := NewEncoder(&buf)
    189 	a := make([]string, 1000)
    190 	for i := range a {
    191 		a[i] = "now is the time"
    192 	}
    193 	b.ResetTimer()
    194 	for i := 0; i < b.N; i++ {
    195 		buf.Reset()
    196 		err := enc.Encode(a)
    197 		if err != nil {
    198 			b.Fatal(err)
    199 		}
    200 	}
    201 }
    202 
    203 // benchmarkBuf is a read buffer we can reset
    204 type benchmarkBuf struct {
    205 	offset int
    206 	data   []byte
    207 }
    208 
    209 func (b *benchmarkBuf) Read(p []byte) (n int, err error) {
    210 	n = copy(p, b.data[b.offset:])
    211 	if n == 0 {
    212 		return 0, io.EOF
    213 	}
    214 	b.offset += n
    215 	return
    216 }
    217 
    218 func (b *benchmarkBuf) ReadByte() (c byte, err error) {
    219 	if b.offset >= len(b.data) {
    220 		return 0, io.EOF
    221 	}
    222 	c = b.data[b.offset]
    223 	b.offset++
    224 	return
    225 }
    226 
    227 func (b *benchmarkBuf) reset() {
    228 	b.offset = 0
    229 }
    230 
    231 func BenchmarkDecodeComplex128Slice(b *testing.B) {
    232 	var buf bytes.Buffer
    233 	enc := NewEncoder(&buf)
    234 	a := make([]complex128, 1000)
    235 	for i := range a {
    236 		a[i] = 1.2 + 3.4i
    237 	}
    238 	err := enc.Encode(a)
    239 	if err != nil {
    240 		b.Fatal(err)
    241 	}
    242 	x := make([]complex128, 1000)
    243 	bbuf := benchmarkBuf{data: buf.Bytes()}
    244 	b.ResetTimer()
    245 	for i := 0; i < b.N; i++ {
    246 		bbuf.reset()
    247 		dec := NewDecoder(&bbuf)
    248 		err := dec.Decode(&x)
    249 		if err != nil {
    250 			b.Fatal(i, err)
    251 		}
    252 	}
    253 }
    254 
    255 func BenchmarkDecodeFloat64Slice(b *testing.B) {
    256 	var buf bytes.Buffer
    257 	enc := NewEncoder(&buf)
    258 	a := make([]float64, 1000)
    259 	for i := range a {
    260 		a[i] = 1.23e4
    261 	}
    262 	err := enc.Encode(a)
    263 	if err != nil {
    264 		b.Fatal(err)
    265 	}
    266 	x := make([]float64, 1000)
    267 	bbuf := benchmarkBuf{data: buf.Bytes()}
    268 	b.ResetTimer()
    269 	for i := 0; i < b.N; i++ {
    270 		bbuf.reset()
    271 		dec := NewDecoder(&bbuf)
    272 		err := dec.Decode(&x)
    273 		if err != nil {
    274 			b.Fatal(i, err)
    275 		}
    276 	}
    277 }
    278 
    279 func BenchmarkDecodeInt32Slice(b *testing.B) {
    280 	var buf bytes.Buffer
    281 	enc := NewEncoder(&buf)
    282 	a := make([]int32, 1000)
    283 	for i := range a {
    284 		a[i] = 1234
    285 	}
    286 	err := enc.Encode(a)
    287 	if err != nil {
    288 		b.Fatal(err)
    289 	}
    290 	x := make([]int32, 1000)
    291 	bbuf := benchmarkBuf{data: buf.Bytes()}
    292 	b.ResetTimer()
    293 	for i := 0; i < b.N; i++ {
    294 		bbuf.reset()
    295 		dec := NewDecoder(&bbuf)
    296 		err := dec.Decode(&x)
    297 		if err != nil {
    298 			b.Fatal(i, err)
    299 		}
    300 	}
    301 }
    302 
    303 func BenchmarkDecodeStringSlice(b *testing.B) {
    304 	var buf bytes.Buffer
    305 	enc := NewEncoder(&buf)
    306 	a := make([]string, 1000)
    307 	for i := range a {
    308 		a[i] = "now is the time"
    309 	}
    310 	err := enc.Encode(a)
    311 	if err != nil {
    312 		b.Fatal(err)
    313 	}
    314 	x := make([]string, 1000)
    315 	bbuf := benchmarkBuf{data: buf.Bytes()}
    316 	b.ResetTimer()
    317 	for i := 0; i < b.N; i++ {
    318 		bbuf.reset()
    319 		dec := NewDecoder(&bbuf)
    320 		err := dec.Decode(&x)
    321 		if err != nil {
    322 			b.Fatal(i, err)
    323 		}
    324 	}
    325 }
    326