...

Source file src/encoding/gob/timing_test.go

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

View as plain text