github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/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 != 3 { 131 t.Fatalf("mallocs per decode of type Bench: %v; wanted 3\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 func BenchmarkEncodeInterfaceSlice(b *testing.B) { 204 var buf bytes.Buffer 205 enc := NewEncoder(&buf) 206 a := make([]interface{}, 1000) 207 for i := range a { 208 a[i] = "now is the time" 209 } 210 b.ResetTimer() 211 for i := 0; i < b.N; i++ { 212 buf.Reset() 213 err := enc.Encode(a) 214 if err != nil { 215 b.Fatal(err) 216 } 217 } 218 } 219 220 // benchmarkBuf is a read buffer we can reset 221 type benchmarkBuf struct { 222 offset int 223 data []byte 224 } 225 226 func (b *benchmarkBuf) Read(p []byte) (n int, err error) { 227 n = copy(p, b.data[b.offset:]) 228 if n == 0 { 229 return 0, io.EOF 230 } 231 b.offset += n 232 return 233 } 234 235 func (b *benchmarkBuf) ReadByte() (c byte, err error) { 236 if b.offset >= len(b.data) { 237 return 0, io.EOF 238 } 239 c = b.data[b.offset] 240 b.offset++ 241 return 242 } 243 244 func (b *benchmarkBuf) reset() { 245 b.offset = 0 246 } 247 248 func BenchmarkDecodeComplex128Slice(b *testing.B) { 249 var buf bytes.Buffer 250 enc := NewEncoder(&buf) 251 a := make([]complex128, 1000) 252 for i := range a { 253 a[i] = 1.2 + 3.4i 254 } 255 err := enc.Encode(a) 256 if err != nil { 257 b.Fatal(err) 258 } 259 x := make([]complex128, 1000) 260 bbuf := benchmarkBuf{data: buf.Bytes()} 261 b.ResetTimer() 262 for i := 0; i < b.N; i++ { 263 bbuf.reset() 264 dec := NewDecoder(&bbuf) 265 err := dec.Decode(&x) 266 if err != nil { 267 b.Fatal(i, err) 268 } 269 } 270 } 271 272 func BenchmarkDecodeFloat64Slice(b *testing.B) { 273 var buf bytes.Buffer 274 enc := NewEncoder(&buf) 275 a := make([]float64, 1000) 276 for i := range a { 277 a[i] = 1.23e4 278 } 279 err := enc.Encode(a) 280 if err != nil { 281 b.Fatal(err) 282 } 283 x := make([]float64, 1000) 284 bbuf := benchmarkBuf{data: buf.Bytes()} 285 b.ResetTimer() 286 for i := 0; i < b.N; i++ { 287 bbuf.reset() 288 dec := NewDecoder(&bbuf) 289 err := dec.Decode(&x) 290 if err != nil { 291 b.Fatal(i, err) 292 } 293 } 294 } 295 296 func BenchmarkDecodeInt32Slice(b *testing.B) { 297 var buf bytes.Buffer 298 enc := NewEncoder(&buf) 299 a := make([]int32, 1000) 300 for i := range a { 301 a[i] = 1234 302 } 303 err := enc.Encode(a) 304 if err != nil { 305 b.Fatal(err) 306 } 307 x := make([]int32, 1000) 308 bbuf := benchmarkBuf{data: buf.Bytes()} 309 b.ResetTimer() 310 for i := 0; i < b.N; i++ { 311 bbuf.reset() 312 dec := NewDecoder(&bbuf) 313 err := dec.Decode(&x) 314 if err != nil { 315 b.Fatal(i, err) 316 } 317 } 318 } 319 320 func BenchmarkDecodeStringSlice(b *testing.B) { 321 var buf bytes.Buffer 322 enc := NewEncoder(&buf) 323 a := make([]string, 1000) 324 for i := range a { 325 a[i] = "now is the time" 326 } 327 err := enc.Encode(a) 328 if err != nil { 329 b.Fatal(err) 330 } 331 x := make([]string, 1000) 332 bbuf := benchmarkBuf{data: buf.Bytes()} 333 b.ResetTimer() 334 for i := 0; i < b.N; i++ { 335 bbuf.reset() 336 dec := NewDecoder(&bbuf) 337 err := dec.Decode(&x) 338 if err != nil { 339 b.Fatal(i, err) 340 } 341 } 342 } 343 344 func BenchmarkDecodeInterfaceSlice(b *testing.B) { 345 var buf bytes.Buffer 346 enc := NewEncoder(&buf) 347 a := make([]interface{}, 1000) 348 for i := range a { 349 a[i] = "now is the time" 350 } 351 err := enc.Encode(a) 352 if err != nil { 353 b.Fatal(err) 354 } 355 x := make([]interface{}, 1000) 356 bbuf := benchmarkBuf{data: buf.Bytes()} 357 b.ResetTimer() 358 for i := 0; i < b.N; i++ { 359 bbuf.reset() 360 dec := NewDecoder(&bbuf) 361 err := dec.Decode(&x) 362 if err != nil { 363 b.Fatal(i, err) 364 } 365 } 366 }