github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/testing/benchmark_test.go (about) 1 // Copyright 2013 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 testing_test 6 7 import ( 8 "github.com/x04/go/src/bytes" 9 "github.com/x04/go/src/runtime" 10 "github.com/x04/go/src/sort" 11 "github.com/x04/go/src/strings" 12 "github.com/x04/go/src/sync/atomic" 13 "github.com/x04/go/src/testing" 14 "github.com/x04/go/src/text/template" 15 "github.com/x04/go/src/time" 16 ) 17 18 var prettyPrintTests = []struct { 19 v float64 20 expected string 21 }{ 22 {0, " 0 x"}, 23 {1234.1, " 1234 x"}, 24 {-1234.1, " -1234 x"}, 25 {99.950001, " 100 x"}, 26 {99.949999, " 99.9 x"}, 27 {9.9950001, " 10.0 x"}, 28 {9.9949999, " 9.99 x"}, 29 {-9.9949999, " -9.99 x"}, 30 {0.0099950001, " 0.0100 x"}, 31 {0.0099949999, " 0.00999 x"}, 32 } 33 34 func TestPrettyPrint(t *testing.T) { 35 for _, tt := range prettyPrintTests { 36 buf := new(strings.Builder) 37 testing.PrettyPrint(buf, tt.v, "x") 38 if tt.expected != buf.String() { 39 t.Errorf("prettyPrint(%v): expected %q, actual %q", tt.v, tt.expected, buf.String()) 40 } 41 } 42 } 43 44 func TestResultString(t *testing.T) { 45 // Test fractional ns/op handling 46 r := testing.BenchmarkResult{ 47 N: 100, 48 T: 240 * time.Nanosecond, 49 } 50 if r.NsPerOp() != 2 { 51 t.Errorf("NsPerOp: expected 2, actual %v", r.NsPerOp()) 52 } 53 if want, got := " 100\t 2.40 ns/op", r.String(); want != got { 54 t.Errorf("String: expected %q, actual %q", want, got) 55 } 56 57 // Test sub-1 ns/op (issue #31005) 58 r.T = 40 * time.Nanosecond 59 if want, got := " 100\t 0.400 ns/op", r.String(); want != got { 60 t.Errorf("String: expected %q, actual %q", want, got) 61 } 62 63 // Test 0 ns/op 64 r.T = 0 65 if want, got := " 100", r.String(); want != got { 66 t.Errorf("String: expected %q, actual %q", want, got) 67 } 68 } 69 70 func TestRunParallel(t *testing.T) { 71 if testing.Short() { 72 t.Skip("skipping in short mode") 73 } 74 testing.Benchmark(func(b *testing.B) { 75 procs := uint32(0) 76 iters := uint64(0) 77 b.SetParallelism(3) 78 b.RunParallel(func(pb *testing.PB) { 79 atomic.AddUint32(&procs, 1) 80 for pb.Next() { 81 atomic.AddUint64(&iters, 1) 82 } 83 }) 84 if want := uint32(3 * runtime.GOMAXPROCS(0)); procs != want { 85 t.Errorf("got %v procs, want %v", procs, want) 86 } 87 if iters != uint64(b.N) { 88 t.Errorf("got %v iters, want %v", iters, b.N) 89 } 90 }) 91 } 92 93 func TestRunParallelFail(t *testing.T) { 94 testing.Benchmark(func(b *testing.B) { 95 b.RunParallel(func(pb *testing.PB) { 96 // The function must be able to log/abort 97 // w/o crashing/deadlocking the whole benchmark. 98 b.Log("log") 99 b.Error("error") 100 }) 101 }) 102 } 103 104 func ExampleB_RunParallel() { 105 // Parallel benchmark for text/template.Template.Execute on a single object. 106 testing.Benchmark(func(b *testing.B) { 107 templ := template.Must(template.New("test").Parse("Hello, {{.}}!")) 108 // RunParallel will create GOMAXPROCS goroutines 109 // and distribute work among them. 110 b.RunParallel(func(pb *testing.PB) { 111 // Each goroutine has its own bytes.Buffer. 112 var buf bytes.Buffer 113 for pb.Next() { 114 // The loop body is executed b.N times total across all goroutines. 115 buf.Reset() 116 templ.Execute(&buf, "World") 117 } 118 }) 119 }) 120 } 121 122 func TestReportMetric(t *testing.T) { 123 res := testing.Benchmark(func(b *testing.B) { 124 b.ReportMetric(12345, "ns/op") 125 b.ReportMetric(0.2, "frobs/op") 126 }) 127 // Test built-in overriding. 128 if res.NsPerOp() != 12345 { 129 t.Errorf("NsPerOp: expected %v, actual %v", 12345, res.NsPerOp()) 130 } 131 // Test stringing. 132 res.N = 1 // Make the output stable 133 want := " 1\t 12345 ns/op\t 0.200 frobs/op" 134 if want != res.String() { 135 t.Errorf("expected %q, actual %q", want, res.String()) 136 } 137 } 138 139 func ExampleB_ReportMetric() { 140 // This reports a custom benchmark metric relevant to a 141 // specific algorithm (in this case, sorting). 142 testing.Benchmark(func(b *testing.B) { 143 var compares int64 144 for i := 0; i < b.N; i++ { 145 s := []int{5, 4, 3, 2, 1} 146 sort.Slice(s, func(i, j int) bool { 147 compares++ 148 return s[i] < s[j] 149 }) 150 } 151 // This metric is per-operation, so divide by b.N and 152 // report it as a "/op" unit. 153 b.ReportMetric(float64(compares)/float64(b.N), "compares/op") 154 }) 155 }