Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / cmd / benchcmp / benchcmp.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
5 package main
6
7 import (
8         "flag"
9         "fmt"
10         "os"
11         "sort"
12         "strconv"
13         "text/tabwriter"
14
15         "golang.org/x/tools/benchmark/parse"
16 )
17
18 var (
19         changedOnly = flag.Bool("changed", false, "show only benchmarks that have changed")
20         magSort     = flag.Bool("mag", false, "sort benchmarks by magnitude of change")
21         best        = flag.Bool("best", false, "compare best times from old and new")
22 )
23
24 const usageFooter = `
25 Each input file should be from:
26         go test -run=NONE -bench=. > [old,new].txt
27
28 Benchcmp compares old and new for each benchmark.
29
30 If -test.benchmem=true is added to the "go test" command
31 benchcmp will also compare memory allocations.
32 `
33
34 func main() {
35         fmt.Fprintf(os.Stderr, "benchcmp is deprecated in favor of benchstat: https://pkg.go.dev/golang.org/x/perf/cmd/benchstat\n")
36         flag.Usage = func() {
37                 fmt.Fprintf(os.Stderr, "usage: %s old.txt new.txt\n\n", os.Args[0])
38                 flag.PrintDefaults()
39                 fmt.Fprint(os.Stderr, usageFooter)
40                 os.Exit(2)
41         }
42         flag.Parse()
43         if flag.NArg() != 2 {
44                 flag.Usage()
45         }
46
47         before := parseFile(flag.Arg(0))
48         after := parseFile(flag.Arg(1))
49
50         cmps, warnings := Correlate(before, after)
51
52         for _, warn := range warnings {
53                 fmt.Fprintln(os.Stderr, warn)
54         }
55
56         if len(cmps) == 0 {
57                 fatal("benchcmp: no repeated benchmarks")
58         }
59
60         w := new(tabwriter.Writer)
61         w.Init(os.Stdout, 0, 0, 5, ' ', 0)
62         defer w.Flush()
63
64         var header bool // Has the header has been displayed yet for a given block?
65
66         if *magSort {
67                 sort.Sort(ByDeltaNsPerOp(cmps))
68         } else {
69                 sort.Sort(ByParseOrder(cmps))
70         }
71         for _, cmp := range cmps {
72                 if !cmp.Measured(parse.NsPerOp) {
73                         continue
74                 }
75                 if delta := cmp.DeltaNsPerOp(); !*changedOnly || delta.Changed() {
76                         if !header {
77                                 fmt.Fprint(w, "benchmark\told ns/op\tnew ns/op\tdelta\n")
78                                 header = true
79                         }
80                         fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", cmp.Name(), formatNs(cmp.Before.NsPerOp), formatNs(cmp.After.NsPerOp), delta.Percent())
81                 }
82         }
83
84         header = false
85         if *magSort {
86                 sort.Sort(ByDeltaMBPerS(cmps))
87         }
88         for _, cmp := range cmps {
89                 if !cmp.Measured(parse.MBPerS) {
90                         continue
91                 }
92                 if delta := cmp.DeltaMBPerS(); !*changedOnly || delta.Changed() {
93                         if !header {
94                                 fmt.Fprint(w, "\nbenchmark\told MB/s\tnew MB/s\tspeedup\n")
95                                 header = true
96                         }
97                         fmt.Fprintf(w, "%s\t%.2f\t%.2f\t%s\n", cmp.Name(), cmp.Before.MBPerS, cmp.After.MBPerS, delta.Multiple())
98                 }
99         }
100
101         header = false
102         if *magSort {
103                 sort.Sort(ByDeltaAllocsPerOp(cmps))
104         }
105         for _, cmp := range cmps {
106                 if !cmp.Measured(parse.AllocsPerOp) {
107                         continue
108                 }
109                 if delta := cmp.DeltaAllocsPerOp(); !*changedOnly || delta.Changed() {
110                         if !header {
111                                 fmt.Fprint(w, "\nbenchmark\told allocs\tnew allocs\tdelta\n")
112                                 header = true
113                         }
114                         fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.AllocsPerOp, cmp.After.AllocsPerOp, delta.Percent())
115                 }
116         }
117
118         header = false
119         if *magSort {
120                 sort.Sort(ByDeltaAllocedBytesPerOp(cmps))
121         }
122         for _, cmp := range cmps {
123                 if !cmp.Measured(parse.AllocedBytesPerOp) {
124                         continue
125                 }
126                 if delta := cmp.DeltaAllocedBytesPerOp(); !*changedOnly || delta.Changed() {
127                         if !header {
128                                 fmt.Fprint(w, "\nbenchmark\told bytes\tnew bytes\tdelta\n")
129                                 header = true
130                         }
131                         fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.AllocedBytesPerOp, cmp.After.AllocedBytesPerOp, cmp.DeltaAllocedBytesPerOp().Percent())
132                 }
133         }
134 }
135
136 func fatal(msg interface{}) {
137         fmt.Fprintln(os.Stderr, msg)
138         os.Exit(1)
139 }
140
141 func parseFile(path string) parse.Set {
142         f, err := os.Open(path)
143         if err != nil {
144                 fatal(err)
145         }
146         defer f.Close()
147         bb, err := parse.ParseSet(f)
148         if err != nil {
149                 fatal(err)
150         }
151         if *best {
152                 selectBest(bb)
153         }
154         return bb
155 }
156
157 func selectBest(bs parse.Set) {
158         for name, bb := range bs {
159                 if len(bb) < 2 {
160                         continue
161                 }
162                 ord := bb[0].Ord
163                 best := bb[0]
164                 for _, b := range bb {
165                         if b.NsPerOp < best.NsPerOp {
166                                 b.Ord = ord
167                                 best = b
168                         }
169                 }
170                 bs[name] = []*parse.Benchmark{best}
171         }
172 }
173
174 // formatNs formats ns measurements to expose a useful amount of
175 // precision. It mirrors the ns precision logic of testing.B.
176 func formatNs(ns float64) string {
177         prec := 0
178         switch {
179         case ns < 10:
180                 prec = 2
181         case ns < 100:
182                 prec = 1
183         }
184         return strconv.FormatFloat(ns, 'f', prec, 64)
185 }