| 1 | // Copyright 2014 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 main |
| 6 | |
| 7 | import ( |
| 8 | "math" |
| 9 | "reflect" |
| 10 | "sort" |
| 11 | "testing" |
| 12 | |
| 13 | "golang.org/x/tools/benchmark/parse" |
| 14 | ) |
| 15 | |
| 16 | func TestDelta(t *testing.T) { |
| 17 | cases := []struct { |
| 18 | before float64 |
| 19 | after float64 |
| 20 | mag float64 |
| 21 | f float64 |
| 22 | changed bool |
| 23 | pct string |
| 24 | mult string |
| 25 | }{ |
| 26 | {before: 1, after: 1, mag: 1, f: 1, changed: false, pct: "+0.00%", mult: "1.00x"}, |
| 27 | {before: 1, after: 2, mag: 0.5, f: 2, changed: true, pct: "+100.00%", mult: "2.00x"}, |
| 28 | {before: 2, after: 1, mag: 0.5, f: 0.5, changed: true, pct: "-50.00%", mult: "0.50x"}, |
| 29 | {before: 0, after: 0, mag: 1, f: 1, changed: false, pct: "+0.00%", mult: "1.00x"}, |
| 30 | {before: 1, after: 0, mag: math.Inf(1), f: 0, changed: true, pct: "-100.00%", mult: "0.00x"}, |
| 31 | {before: 0, after: 1, mag: math.Inf(1), f: math.Inf(1), changed: true, pct: "+Inf%", mult: "+Infx"}, |
| 32 | } |
| 33 | for _, tt := range cases { |
| 34 | d := Delta{tt.before, tt.after} |
| 35 | if want, have := tt.mag, d.mag(); want != have { |
| 36 | t.Errorf("%s.mag(): want %f have %f", d, want, have) |
| 37 | } |
| 38 | if want, have := tt.f, d.Float64(); want != have { |
| 39 | t.Errorf("%s.Float64(): want %f have %f", d, want, have) |
| 40 | } |
| 41 | if want, have := tt.changed, d.Changed(); want != have { |
| 42 | t.Errorf("%s.Changed(): want %t have %t", d, want, have) |
| 43 | } |
| 44 | if want, have := tt.pct, d.Percent(); want != have { |
| 45 | t.Errorf("%s.Percent(): want %q have %q", d, want, have) |
| 46 | } |
| 47 | if want, have := tt.mult, d.Multiple(); want != have { |
| 48 | t.Errorf("%s.Multiple(): want %q have %q", d, want, have) |
| 49 | } |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | func TestCorrelate(t *testing.T) { |
| 54 | // Benches that are going to be successfully correlated get N thus: |
| 55 | // 0x<counter><num benches><b = before | a = after> |
| 56 | // Read this: "<counter> of <num benches>, from <before|after>". |
| 57 | before := parse.Set{ |
| 58 | "BenchmarkOneEach": []*parse.Benchmark{{Name: "BenchmarkOneEach", N: 0x11b}}, |
| 59 | "BenchmarkOneToNone": []*parse.Benchmark{{Name: "BenchmarkOneToNone"}}, |
| 60 | "BenchmarkOneToTwo": []*parse.Benchmark{{Name: "BenchmarkOneToTwo"}}, |
| 61 | "BenchmarkTwoToOne": []*parse.Benchmark{ |
| 62 | {Name: "BenchmarkTwoToOne"}, |
| 63 | {Name: "BenchmarkTwoToOne"}, |
| 64 | }, |
| 65 | "BenchmarkTwoEach": []*parse.Benchmark{ |
| 66 | {Name: "BenchmarkTwoEach", N: 0x12b}, |
| 67 | {Name: "BenchmarkTwoEach", N: 0x22b}, |
| 68 | }, |
| 69 | } |
| 70 | |
| 71 | after := parse.Set{ |
| 72 | "BenchmarkOneEach": []*parse.Benchmark{{Name: "BenchmarkOneEach", N: 0x11a}}, |
| 73 | "BenchmarkNoneToOne": []*parse.Benchmark{{Name: "BenchmarkNoneToOne"}}, |
| 74 | "BenchmarkTwoToOne": []*parse.Benchmark{{Name: "BenchmarkTwoToOne"}}, |
| 75 | "BenchmarkOneToTwo": []*parse.Benchmark{ |
| 76 | {Name: "BenchmarkOneToTwo"}, |
| 77 | {Name: "BenchmarkOneToTwo"}, |
| 78 | }, |
| 79 | "BenchmarkTwoEach": []*parse.Benchmark{ |
| 80 | {Name: "BenchmarkTwoEach", N: 0x12a}, |
| 81 | {Name: "BenchmarkTwoEach", N: 0x22a}, |
| 82 | }, |
| 83 | } |
| 84 | |
| 85 | pairs, errs := Correlate(before, after) |
| 86 | |
| 87 | // Fail to match: BenchmarkOneToNone, BenchmarkOneToTwo, BenchmarkTwoToOne. |
| 88 | // Correlate does not notice BenchmarkNoneToOne. |
| 89 | if len(errs) != 3 { |
| 90 | t.Errorf("Correlated expected 4 errors, got %d: %v", len(errs), errs) |
| 91 | } |
| 92 | |
| 93 | // Want three correlated pairs: one BenchmarkOneEach, two BenchmarkTwoEach. |
| 94 | if len(pairs) != 3 { |
| 95 | t.Fatalf("Correlated expected 3 pairs, got %v", pairs) |
| 96 | } |
| 97 | |
| 98 | for _, pair := range pairs { |
| 99 | if pair.Before.N&0xF != 0xb { |
| 100 | t.Errorf("unexpected Before in pair %s", pair) |
| 101 | } |
| 102 | if pair.After.N&0xF != 0xa { |
| 103 | t.Errorf("unexpected After in pair %s", pair) |
| 104 | } |
| 105 | if pair.Before.N>>4 != pair.After.N>>4 { |
| 106 | t.Errorf("mismatched pair %s", pair) |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | func TestBenchCmpSorting(t *testing.T) { |
| 112 | c := []BenchCmp{ |
| 113 | {&parse.Benchmark{Name: "BenchmarkMuchFaster", NsPerOp: 10, Ord: 3}, &parse.Benchmark{Name: "BenchmarkMuchFaster", NsPerOp: 1}}, |
| 114 | {&parse.Benchmark{Name: "BenchmarkSameB", NsPerOp: 5, Ord: 1}, &parse.Benchmark{Name: "BenchmarkSameB", NsPerOp: 5}}, |
| 115 | {&parse.Benchmark{Name: "BenchmarkSameA", NsPerOp: 5, Ord: 2}, &parse.Benchmark{Name: "BenchmarkSameA", NsPerOp: 5}}, |
| 116 | {&parse.Benchmark{Name: "BenchmarkSlower", NsPerOp: 10, Ord: 0}, &parse.Benchmark{Name: "BenchmarkSlower", NsPerOp: 11}}, |
| 117 | } |
| 118 | |
| 119 | // Test just one magnitude-based sort order; they are symmetric. |
| 120 | sort.Sort(ByDeltaNsPerOp(c)) |
| 121 | want := []string{"BenchmarkMuchFaster", "BenchmarkSlower", "BenchmarkSameA", "BenchmarkSameB"} |
| 122 | have := []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()} |
| 123 | if !reflect.DeepEqual(want, have) { |
| 124 | t.Errorf("ByDeltaNsOp incorrect sorting: want %v have %v", want, have) |
| 125 | } |
| 126 | |
| 127 | sort.Sort(ByParseOrder(c)) |
| 128 | want = []string{"BenchmarkSlower", "BenchmarkSameB", "BenchmarkSameA", "BenchmarkMuchFaster"} |
| 129 | have = []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()} |
| 130 | if !reflect.DeepEqual(want, have) { |
| 131 | t.Errorf("ByParseOrder incorrect sorting: want %v have %v", want, have) |
| 132 | } |
| 133 | } |
| 134 |
Members