]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/gob: parallelize Encode/Decode benchmarks
authorBryan C. Mills <bcmills@google.com>
Fri, 10 Feb 2017 19:13:06 +0000 (14:13 -0500)
committerBryan Mills <bcmills@google.com>
Wed, 26 Apr 2017 19:04:18 +0000 (19:04 +0000)
Results remain comparable with the non-parallel version with -cpu=1:

benchmark                              old ns/op     new ns/op     delta
BenchmarkEndToEndPipe                  6200          6171          -0.47%
BenchmarkEndToEndPipe-6                1073          1024          -4.57%
BenchmarkEndToEndByteBuffer            2925          2664          -8.92%
BenchmarkEndToEndByteBuffer-6          516           560           +8.53%
BenchmarkEndToEndSliceByteBuffer       231683        237450        +2.49%
BenchmarkEndToEndSliceByteBuffer-6     59080         59452         +0.63%
BenchmarkEncodeComplex128Slice         67541         66003         -2.28%
BenchmarkEncodeComplex128Slice-6       72740         11316         -84.44%
BenchmarkEncodeFloat64Slice            25769         27899         +8.27%
BenchmarkEncodeFloat64Slice-6          26655         4557          -82.90%
BenchmarkEncodeInt32Slice              18685         18845         +0.86%
BenchmarkEncodeInt32Slice-6            18389         3462          -81.17%
BenchmarkEncodeStringSlice             19089         19354         +1.39%
BenchmarkEncodeStringSlice-6           20155         3237          -83.94%
BenchmarkEncodeInterfaceSlice          659601        677129        +2.66%
BenchmarkEncodeInterfaceSlice-6        640974        251621        -60.74%
BenchmarkDecodeComplex128Slice         117130        129955        +10.95%
BenchmarkDecodeComplex128Slice-6       155447        24924         -83.97%
BenchmarkDecodeFloat64Slice            67695         68776         +1.60%
BenchmarkDecodeFloat64Slice-6          82966         15225         -81.65%
BenchmarkDecodeInt32Slice              63102         62733         -0.58%
BenchmarkDecodeInt32Slice-6            77857         13003         -83.30%
BenchmarkDecodeStringSlice             130240        129562        -0.52%
BenchmarkDecodeStringSlice-6           165500        31507         -80.96%
BenchmarkDecodeInterfaceSlice          937637        1060835       +13.14%
BenchmarkDecodeInterfaceSlice-6        973495        270613        -72.20%

updates #18177

Change-Id: Ib3579010faa70827d5cbd02a826dbbb66ca13eb7
Reviewed-on: https://go-review.googlesource.com/36722
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/encoding/gob/timing_test.go

index e3578992fcf148581c298934d83b1fcba71b08b9..2a503ebfc505fd4bef4c2420282354cc1345ed20 100644 (file)
@@ -8,6 +8,7 @@ import (
        "bytes"
        "io"
        "os"
+       "reflect"
        "runtime"
        "testing"
 )
@@ -132,89 +133,60 @@ func TestCountDecodeMallocs(t *testing.T) {
        }
 }
 
+func benchmarkEncodeSlice(b *testing.B, a interface{}) {
+       b.ResetTimer()
+       b.RunParallel(func(pb *testing.PB) {
+               var buf bytes.Buffer
+               enc := NewEncoder(&buf)
+
+               for pb.Next() {
+                       buf.Reset()
+                       err := enc.Encode(a)
+                       if err != nil {
+                               b.Fatal(err)
+                       }
+               }
+       })
+}
+
 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)
-               }
-       }
+       benchmarkEncodeSlice(b, a)
 }
 
 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)
-               }
-       }
+       benchmarkEncodeSlice(b, a)
 }
 
 func BenchmarkEncodeInt32Slice(b *testing.B) {
-       var buf bytes.Buffer
-       enc := NewEncoder(&buf)
        a := make([]int32, 1000)
        for i := range a {
                a[i] = int32(i * 100)
        }
-       b.ResetTimer()
-       for i := 0; i < b.N; i++ {
-               buf.Reset()
-               err := enc.Encode(a)
-               if err != nil {
-                       b.Fatal(err)
-               }
-       }
+       benchmarkEncodeSlice(b, a)
 }
 
 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)
-               }
-       }
+       benchmarkEncodeSlice(b, a)
 }
 
 func BenchmarkEncodeInterfaceSlice(b *testing.B) {
-       var buf bytes.Buffer
-       enc := NewEncoder(&buf)
        a := make([]interface{}, 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)
-               }
-       }
+       benchmarkEncodeSlice(b, a)
 }
 
 // benchmarkBuf is a read buffer we can reset
@@ -245,124 +217,75 @@ func (b *benchmarkBuf) reset() {
        b.offset = 0
 }
 
-func BenchmarkDecodeComplex128Slice(b *testing.B) {
+func benchmarkDecodeSlice(b *testing.B, a interface{}) {
        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()}
+
+       ra := reflect.ValueOf(a)
+       rt := ra.Type()
        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)
+
+       b.RunParallel(func(pb *testing.PB) {
+               // TODO(#19025): Move per-thread allocation before ResetTimer.
+               rp := reflect.New(rt)
+               rp.Elem().Set(reflect.MakeSlice(rt, ra.Len(), ra.Cap()))
+               p := rp.Interface()
+
+               bbuf := benchmarkBuf{data: buf.Bytes()}
+
+               for pb.Next() {
+                       bbuf.reset()
+                       dec := NewDecoder(&bbuf)
+                       err := dec.Decode(p)
+                       if err != nil {
+                               b.Fatal(err)
+                       }
                }
+       })
+}
+
+func BenchmarkDecodeComplex128Slice(b *testing.B) {
+       a := make([]complex128, 1000)
+       for i := range a {
+               a[i] = 1.2 + 3.4i
        }
+       benchmarkDecodeSlice(b, a)
 }
 
 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)
-               }
-       }
+       benchmarkDecodeSlice(b, a)
 }
 
 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)
-               }
-       }
+       benchmarkDecodeSlice(b, a)
 }
 
 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)
-               }
-       }
+       benchmarkDecodeSlice(b, a)
 }
 
 func BenchmarkDecodeInterfaceSlice(b *testing.B) {
-       var buf bytes.Buffer
-       enc := NewEncoder(&buf)
        a := make([]interface{}, 1000)
        for i := range a {
                a[i] = "now is the time"
        }
-       err := enc.Encode(a)
-       if err != nil {
-               b.Fatal(err)
-       }
-       x := make([]interface{}, 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)
-               }
-       }
+       benchmarkDecodeSlice(b, a)
 }
 
 func BenchmarkDecodeMap(b *testing.B) {