GoPLS Viewer

Home|gopls/cmd/benchcmp/compare.go
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
5package main
6
7import (
8    "fmt"
9    "math"
10
11    "golang.org/x/tools/benchmark/parse"
12)
13
14// BenchCmp is a pair of benchmarks.
15type BenchCmp struct {
16    Before *parse.Benchmark
17    After  *parse.Benchmark
18}
19
20// Correlate correlates benchmarks from two BenchSets.
21func Correlate(beforeafter parse.Set) (cmps []BenchCmpwarnings []string) {
22    cmps = make([]BenchCmp0len(after))
23    for namebeforebb := range before {
24        afterbb := after[name]
25        if len(beforebb) != len(afterbb) {
26            warnings = append(warningsfmt.Sprintf("ignoring %s: before has %d instances, after has %d"namelen(beforebb), len(afterbb)))
27            continue
28        }
29        for ibeforeb := range beforebb {
30            afterb := afterbb[i]
31            cmps = append(cmpsBenchCmp{beforebafterb})
32        }
33    }
34    return
35}
36
37func (c BenchCmpName() string           { return c.Before.Name }
38func (c BenchCmpString() string         { return fmt.Sprintf("<%s, %s>"c.Beforec.After) }
39func (c BenchCmpMeasured(flag intbool { return (c.Before.Measured & c.After.Measured & flag) != 0 }
40func (c BenchCmpDeltaNsPerOp() Delta    { return Delta{c.Before.NsPerOpc.After.NsPerOp} }
41func (c BenchCmpDeltaMBPerS() Delta     { return Delta{c.Before.MBPerSc.After.MBPerS} }
42func (c BenchCmpDeltaAllocedBytesPerOp() Delta {
43    return Delta{float64(c.Before.AllocedBytesPerOp), float64(c.After.AllocedBytesPerOp)}
44}
45func (c BenchCmpDeltaAllocsPerOp() Delta {
46    return Delta{float64(c.Before.AllocsPerOp), float64(c.After.AllocsPerOp)}
47}
48
49// Delta is the before and after value for a benchmark measurement.
50// Both must be non-negative.
51type Delta struct {
52    Before float64
53    After  float64
54}
55
56// mag calculates the magnitude of a change, regardless of the direction of
57// the change. mag is intended for sorting and has no independent meaning.
58func (d Deltamag() float64 {
59    switch {
60    case d.Before != 0 && d.After != 0 && d.Before >= d.After:
61        return d.After / d.Before
62    case d.Before != 0 && d.After != 0 && d.Before < d.After:
63        return d.Before / d.After
64    case d.Before == 0 && d.After == 0:
65        return 1
66    default:
67        // 0 -> 1 or 1 -> 0
68        // These are significant changes and worth surfacing.
69        return math.Inf(1)
70    }
71}
72
73// Changed reports whether the benchmark quantities are different.
74func (d DeltaChanged() bool { return d.Before != d.After }
75
76// Float64 returns After / Before. If Before is 0, Float64 returns
77// 1 if After is also 0, and +Inf otherwise.
78func (d DeltaFloat64() float64 {
79    switch {
80    case d.Before != 0:
81        return d.After / d.Before
82    case d.After == 0:
83        return 1
84    default:
85        return math.Inf(1)
86    }
87}
88
89// Percent formats a Delta as a percent change, ranging from -100% up.
90func (d DeltaPercent() string {
91    return fmt.Sprintf("%+.2f%%"100*d.Float64()-100)
92}
93
94// Multiple formats a Delta as a multiplier, ranging from 0.00x up.
95func (d DeltaMultiple() string {
96    return fmt.Sprintf("%.2fx"d.Float64())
97}
98
99func (d DeltaString() string {
100    return fmt.Sprintf("Δ(%f, %f)"d.Befored.After)
101}
102
103// ByParseOrder sorts BenchCmps to match the order in
104// which the Before benchmarks were presented to Parse.
105type ByParseOrder []BenchCmp
106
107func (x ByParseOrderLen() int           { return len(x) }
108func (x ByParseOrderSwap(ij int)      { x[i], x[j] = x[j], x[i] }
109func (x ByParseOrderLess(ij intbool { return x[i].Before.Ord < x[j].Before.Ord }
110
111// lessByDelta provides lexicographic ordering:
112//   - largest delta by magnitude
113//   - alphabetic by name
114func lessByDelta(ij BenchCmpcalcDelta func(BenchCmpDeltabool {
115    iDeltajDelta := calcDelta(i).mag(), calcDelta(j).mag()
116    if iDelta != jDelta {
117        return iDelta < jDelta
118    }
119    return i.Name() < j.Name()
120}
121
122// ByDeltaNsPerOp sorts BenchCmps lexicographically by change
123// in ns/op, descending, then by benchmark name.
124type ByDeltaNsPerOp []BenchCmp
125
126func (x ByDeltaNsPerOpLen() int           { return len(x) }
127func (x ByDeltaNsPerOpSwap(ij int)      { x[i], x[j] = x[j], x[i] }
128func (x ByDeltaNsPerOpLess(ij intbool { return lessByDelta(x[i], x[j], BenchCmp.DeltaNsPerOp) }
129
130// ByDeltaMBPerS sorts BenchCmps lexicographically by change
131// in MB/s, descending, then by benchmark name.
132type ByDeltaMBPerS []BenchCmp
133
134func (x ByDeltaMBPerSLen() int           { return len(x) }
135func (x ByDeltaMBPerSSwap(ij int)      { x[i], x[j] = x[j], x[i] }
136func (x ByDeltaMBPerSLess(ij intbool { return lessByDelta(x[i], x[j], BenchCmp.DeltaMBPerS) }
137
138// ByDeltaAllocedBytesPerOp sorts BenchCmps lexicographically by change
139// in B/op, descending, then by benchmark name.
140type ByDeltaAllocedBytesPerOp []BenchCmp
141
142func (x ByDeltaAllocedBytesPerOpLen() int      { return len(x) }
143func (x ByDeltaAllocedBytesPerOpSwap(ij int) { x[i], x[j] = x[j], x[i] }
144func (x ByDeltaAllocedBytesPerOpLess(ij intbool {
145    return lessByDelta(x[i], x[j], BenchCmp.DeltaAllocedBytesPerOp)
146}
147
148// ByDeltaAllocsPerOp sorts BenchCmps lexicographically by change
149// in allocs/op, descending, then by benchmark name.
150type ByDeltaAllocsPerOp []BenchCmp
151
152func (x ByDeltaAllocsPerOpLen() int      { return len(x) }
153func (x ByDeltaAllocsPerOpSwap(ij int) { x[i], x[j] = x[j], x[i] }
154func (x ByDeltaAllocsPerOpLess(ij intbool {
155    return lessByDelta(x[i], x[j], BenchCmp.DeltaAllocsPerOp)
156}
157
MembersX
ByDeltaNsPerOp.Swap
ByDeltaNsPerOp.Swap.i
ByDeltaNsPerOp.Less.j
ByDeltaMBPerS.Len.x
ByDeltaMBPerS.Swap
BenchCmp.Name
Delta.Percent.d
ByParseOrder.Less
ByDeltaMBPerS
ByDeltaAllocedBytesPerOp.Swap
ByDeltaAllocsPerOp.Len.x
BenchCmp.DeltaNsPerOp
BenchCmp.DeltaMBPerS.c
ByParseOrder.Swap
ByDeltaMBPerS.Less
ByDeltaAllocedBytesPerOp.Swap.i
BenchCmp.Measured.c
BenchCmp.DeltaNsPerOp.c
lessByDelta.jDelta
Delta.Float64.d
ByDeltaNsPerOp.Len.x
ByDeltaNsPerOp.Less.i
ByDeltaAllocedBytesPerOp
ByDeltaAllocedBytesPerOp.Less.x
Correlate.before
Correlate.after
BenchCmp.DeltaAllocedBytesPerOp
ByDeltaAllocedBytesPerOp.Less.j
Correlate.RangeStmt_529.BlockStmt.RangeStmt_779.beforeb
BenchCmp.Measured.flag
lessByDelta
Delta.After
ByDeltaMBPerS.Swap.x
ByDeltaMBPerS.Swap.j
ByDeltaAllocsPerOp.Swap.x
ByDeltaAllocsPerOp.Swap.j
BenchCmp.After
Correlate.warnings
BenchCmp.DeltaAllocsPerOp
ByDeltaNsPerOp.Less
Correlate.RangeStmt_529.BlockStmt.RangeStmt_779.i
BenchCmp.Measured
ByParseOrder.Swap.x
ByDeltaAllocedBytesPerOp.Less.i
ByDeltaAllocsPerOp.Swap
BenchCmp.DeltaMBPerS
lessByDelta.i
ByDeltaAllocedBytesPerOp.Len.x
ByDeltaMBPerS.Less.x
ByDeltaAllocedBytesPerOp.Swap.x
ByDeltaAllocsPerOp.Len
ByDeltaAllocsPerOp.Less.x
Correlate.RangeStmt_529.beforebb
ByDeltaNsPerOp
ByDeltaNsPerOp.Len
Delta.Changed
ByParseOrder
ByDeltaMBPerS.Len
Correlate.cmps
BenchCmp.String
Delta.mag
ByDeltaAllocedBytesPerOp.Len
Delta.Multiple.d
Delta.String
lessByDelta.calcDelta
ByDeltaNsPerOp.Swap.x
ByDeltaAllocsPerOp.Less
BenchCmp
ByParseOrder.Swap.j
ByParseOrder.Less.x
lessByDelta.j
lessByDelta.iDelta
ByDeltaMBPerS.Swap.i
ByDeltaMBPerS.Less.i
ByDeltaMBPerS.Less.j
BenchCmp.Before
Delta.Float64
ByParseOrder.Len
ByDeltaAllocsPerOp.Less.i
ByDeltaAllocsPerOp.Less.j
Delta
ByParseOrder.Swap.i
ByParseOrder.Less.i
ByDeltaNsPerOp.Less.x
ByDeltaAllocedBytesPerOp.Swap.j
Correlate
BenchCmp.Name.c
BenchCmp.DeltaAllocsPerOp.c
Delta.Percent
Delta.Multiple
Delta.String.d
ByParseOrder.Len.x
ByDeltaAllocedBytesPerOp.Less
Delta.Before
Delta.mag.d
Delta.Changed.d
ByDeltaAllocsPerOp.Swap.i
BenchCmp.DeltaAllocedBytesPerOp.c
ByParseOrder.Less.j
ByDeltaNsPerOp.Swap.j
ByDeltaAllocsPerOp
math
Correlate.RangeStmt_529.name
BenchCmp.String.c
Members
X