github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/encoding/gob/timing_test.go (about)

     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  }