mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
benchmark/parser, cmd/benchcmp: improve names of exported identifiers
Most of the names have been brought in line with the names used in testing/BenchmarkResult. For example, NsOp becomes NsPerOp. Additionally, "Bench" becomes "Benchmark" and "BenchSet" becomes "Set". Change-Id: I7dfca68a804e285a87ab9692b5bb99ccb676da7f Reviewed-on: https://go-review.googlesource.com/2610 Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
d272cc0504
commit
9f20d8c198
@ -15,29 +15,30 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flags used by Bench.Measured to indicate
|
// Flags used by Benchmark.Measured to indicate
|
||||||
// which measurements a Bench contains.
|
// which measurements a Benchmark contains.
|
||||||
const (
|
const (
|
||||||
NsOp = 1 << iota
|
NsPerOp = 1 << iota
|
||||||
MbS
|
MBPerS
|
||||||
BOp
|
AllocedBytesPerOp
|
||||||
AllocsOp
|
AllocsPerOp
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bench is one run of a single benchmark.
|
// Benchmark is one run of a single benchmark.
|
||||||
type Bench struct {
|
type Benchmark struct {
|
||||||
Name string // benchmark name
|
Name string // benchmark name
|
||||||
N int // number of iterations
|
N int // number of iterations
|
||||||
NsOp float64 // nanoseconds per iteration
|
NsPerOp float64 // nanoseconds per iteration
|
||||||
MbS float64 // MB processed per second
|
AllocedBytesPerOp uint64 // bytes allocated per iteration
|
||||||
BOp uint64 // bytes allocated per iteration
|
AllocsPerOp uint64 // allocs per iteration
|
||||||
AllocsOp uint64 // allocs per iteration
|
MBPerS float64 // MB processed per second
|
||||||
Measured int // which measurements were recorded
|
Measured int // which measurements were recorded
|
||||||
Ord int // ordinal position within a benchmark run
|
Ord int // ordinal position within a benchmark run
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseLine extracts a Bench from a single line of testing.B output.
|
// ParseLine extracts a Benchmark from a single line of testing.B
|
||||||
func ParseLine(line string) (*Bench, error) {
|
// output.
|
||||||
|
func ParseLine(line string) (*Benchmark, error) {
|
||||||
fields := strings.Fields(line)
|
fields := strings.Fields(line)
|
||||||
|
|
||||||
// Two required, positional fields: Name and iterations.
|
// Two required, positional fields: Name and iterations.
|
||||||
@ -51,7 +52,7 @@ func ParseLine(line string) (*Bench, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
b := &Bench{Name: fields[0], N: n}
|
b := &Benchmark{Name: fields[0], N: n}
|
||||||
|
|
||||||
// Parse any remaining pairs of fields; we've parsed one pair already.
|
// Parse any remaining pairs of fields; we've parsed one pair already.
|
||||||
for i := 1; i < len(fields)/2; i++ {
|
for i := 1; i < len(fields)/2; i++ {
|
||||||
@ -60,58 +61,58 @@ func ParseLine(line string) (*Bench, error) {
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bench) parseMeasurement(quant string, unit string) {
|
func (b *Benchmark) parseMeasurement(quant string, unit string) {
|
||||||
switch unit {
|
switch unit {
|
||||||
case "ns/op":
|
case "ns/op":
|
||||||
if f, err := strconv.ParseFloat(quant, 64); err == nil {
|
if f, err := strconv.ParseFloat(quant, 64); err == nil {
|
||||||
b.NsOp = f
|
b.NsPerOp = f
|
||||||
b.Measured |= NsOp
|
b.Measured |= NsPerOp
|
||||||
}
|
}
|
||||||
case "MB/s":
|
case "MB/s":
|
||||||
if f, err := strconv.ParseFloat(quant, 64); err == nil {
|
if f, err := strconv.ParseFloat(quant, 64); err == nil {
|
||||||
b.MbS = f
|
b.MBPerS = f
|
||||||
b.Measured |= MbS
|
b.Measured |= MBPerS
|
||||||
}
|
}
|
||||||
case "B/op":
|
case "B/op":
|
||||||
if i, err := strconv.ParseUint(quant, 10, 64); err == nil {
|
if i, err := strconv.ParseUint(quant, 10, 64); err == nil {
|
||||||
b.BOp = i
|
b.AllocedBytesPerOp = i
|
||||||
b.Measured |= BOp
|
b.Measured |= AllocedBytesPerOp
|
||||||
}
|
}
|
||||||
case "allocs/op":
|
case "allocs/op":
|
||||||
if i, err := strconv.ParseUint(quant, 10, 64); err == nil {
|
if i, err := strconv.ParseUint(quant, 10, 64); err == nil {
|
||||||
b.AllocsOp = i
|
b.AllocsPerOp = i
|
||||||
b.Measured |= AllocsOp
|
b.Measured |= AllocsPerOp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bench) String() string {
|
func (b *Benchmark) String() string {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
fmt.Fprintf(buf, "%s %d", b.Name, b.N)
|
fmt.Fprintf(buf, "%s %d", b.Name, b.N)
|
||||||
if b.Measured&NsOp != 0 {
|
if (b.Measured & NsPerOp) != 0 {
|
||||||
fmt.Fprintf(buf, " %.2f ns/op", b.NsOp)
|
fmt.Fprintf(buf, " %.2f ns/op", b.NsPerOp)
|
||||||
}
|
}
|
||||||
if b.Measured&MbS != 0 {
|
if (b.Measured & MBPerS) != 0 {
|
||||||
fmt.Fprintf(buf, " %.2f MB/s", b.MbS)
|
fmt.Fprintf(buf, " %.2f MB/s", b.MBPerS)
|
||||||
}
|
}
|
||||||
if b.Measured&BOp != 0 {
|
if (b.Measured & AllocedBytesPerOp) != 0 {
|
||||||
fmt.Fprintf(buf, " %d B/op", b.BOp)
|
fmt.Fprintf(buf, " %d B/op", b.AllocedBytesPerOp)
|
||||||
}
|
}
|
||||||
if b.Measured&AllocsOp != 0 {
|
if (b.Measured & AllocsPerOp) != 0 {
|
||||||
fmt.Fprintf(buf, " %d allocs/op", b.AllocsOp)
|
fmt.Fprintf(buf, " %d allocs/op", b.AllocsPerOp)
|
||||||
}
|
}
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// BenchSet is a collection of benchmarks from one
|
// Set is a collection of benchmarks from one
|
||||||
// testing.B run, keyed by name to facilitate comparison.
|
// testing.B run, keyed by name to facilitate comparison.
|
||||||
type BenchSet map[string][]*Bench
|
type Set map[string][]*Benchmark
|
||||||
|
|
||||||
// ParseBenchSet extracts a BenchSet from testing.B output.
|
// ParseSet extracts a Set from testing.B output.
|
||||||
// ParseBenchSet preserves the order of benchmarks that have identical
|
// ParseSet preserves the order of benchmarks that have identical
|
||||||
// names.
|
// names.
|
||||||
func ParseBenchSet(r io.Reader) (BenchSet, error) {
|
func ParseSet(r io.Reader) (Set, error) {
|
||||||
bb := make(BenchSet)
|
bb := make(Set)
|
||||||
scan := bufio.NewScanner(r)
|
scan := bufio.NewScanner(r)
|
||||||
ord := 0
|
ord := 0
|
||||||
for scan.Scan() {
|
for scan.Scan() {
|
||||||
|
@ -13,47 +13,47 @@ import (
|
|||||||
func TestParseLine(t *testing.T) {
|
func TestParseLine(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
line string
|
line string
|
||||||
want *Bench
|
want *Benchmark
|
||||||
err bool // expect an error
|
err bool // expect an error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
line: "BenchmarkEncrypt 100000000 19.6 ns/op",
|
line: "BenchmarkEncrypt 100000000 19.6 ns/op",
|
||||||
want: &Bench{
|
want: &Benchmark{
|
||||||
Name: "BenchmarkEncrypt",
|
Name: "BenchmarkEncrypt",
|
||||||
N: 100000000, NsOp: 19.6,
|
N: 100000000, NsPerOp: 19.6,
|
||||||
Measured: NsOp,
|
Measured: NsPerOp,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
line: "BenchmarkEncrypt 100000000 19.6 ns/op 817.77 MB/s",
|
line: "BenchmarkEncrypt 100000000 19.6 ns/op 817.77 MB/s",
|
||||||
want: &Bench{
|
want: &Benchmark{
|
||||||
Name: "BenchmarkEncrypt",
|
Name: "BenchmarkEncrypt",
|
||||||
N: 100000000, NsOp: 19.6, MbS: 817.77,
|
N: 100000000, NsPerOp: 19.6, MBPerS: 817.77,
|
||||||
Measured: NsOp | MbS,
|
Measured: NsPerOp | MBPerS,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
line: "BenchmarkEncrypt 100000000 19.6 ns/op 817.77",
|
line: "BenchmarkEncrypt 100000000 19.6 ns/op 817.77",
|
||||||
want: &Bench{
|
want: &Benchmark{
|
||||||
Name: "BenchmarkEncrypt",
|
Name: "BenchmarkEncrypt",
|
||||||
N: 100000000, NsOp: 19.6,
|
N: 100000000, NsPerOp: 19.6,
|
||||||
Measured: NsOp,
|
Measured: NsPerOp,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
line: "BenchmarkEncrypt 100000000 19.6 ns/op 817.77 MB/s 5 allocs/op",
|
line: "BenchmarkEncrypt 100000000 19.6 ns/op 817.77 MB/s 5 allocs/op",
|
||||||
want: &Bench{
|
want: &Benchmark{
|
||||||
Name: "BenchmarkEncrypt",
|
Name: "BenchmarkEncrypt",
|
||||||
N: 100000000, NsOp: 19.6, MbS: 817.77, AllocsOp: 5,
|
N: 100000000, NsPerOp: 19.6, MBPerS: 817.77, AllocsPerOp: 5,
|
||||||
Measured: NsOp | MbS | AllocsOp,
|
Measured: NsPerOp | MBPerS | AllocsPerOp,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
line: "BenchmarkEncrypt 100000000 19.6 ns/op 817.77 MB/s 3 B/op 5 allocs/op",
|
line: "BenchmarkEncrypt 100000000 19.6 ns/op 817.77 MB/s 3 B/op 5 allocs/op",
|
||||||
want: &Bench{
|
want: &Benchmark{
|
||||||
Name: "BenchmarkEncrypt",
|
Name: "BenchmarkEncrypt",
|
||||||
N: 100000000, NsOp: 19.6, MbS: 817.77, BOp: 3, AllocsOp: 5,
|
N: 100000000, NsPerOp: 19.6, MBPerS: 817.77, AllocedBytesPerOp: 3, AllocsPerOp: 5,
|
||||||
Measured: NsOp | MbS | BOp | AllocsOp,
|
Measured: NsPerOp | MBPerS | AllocedBytesPerOp | AllocsPerOp,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// error handling cases
|
// error handling cases
|
||||||
@ -67,7 +67,7 @@ func TestParseLine(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
line: "BenchmarkBridge 100000000 19.6 smoots", // unknown unit
|
line: "BenchmarkBridge 100000000 19.6 smoots", // unknown unit
|
||||||
want: &Bench{
|
want: &Benchmark{
|
||||||
Name: "BenchmarkBridge",
|
Name: "BenchmarkBridge",
|
||||||
N: 100000000,
|
N: 100000000,
|
||||||
},
|
},
|
||||||
@ -90,7 +90,7 @@ func TestParseLine(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseBenchSet(t *testing.T) {
|
func TestParseSet(t *testing.T) {
|
||||||
// Test two things:
|
// Test two things:
|
||||||
// 1. The noise that can accompany testing.B output gets ignored.
|
// 1. The noise that can accompany testing.B output gets ignored.
|
||||||
// 2. Benchmarks with the same name have their order preserved.
|
// 2. Benchmarks with the same name have their order preserved.
|
||||||
@ -111,42 +111,42 @@ func TestParseBenchSet(t *testing.T) {
|
|||||||
ok net/http 95.783s
|
ok net/http 95.783s
|
||||||
`
|
`
|
||||||
|
|
||||||
want := BenchSet{
|
want := Set{
|
||||||
"BenchmarkReadRequestApachebench": []*Bench{
|
"BenchmarkReadRequestApachebench": []*Benchmark{
|
||||||
{
|
{
|
||||||
Name: "BenchmarkReadRequestApachebench",
|
Name: "BenchmarkReadRequestApachebench",
|
||||||
N: 1000000, NsOp: 2960, MbS: 27.70, BOp: 839, AllocsOp: 9,
|
N: 1000000, NsPerOp: 2960, MBPerS: 27.70, AllocedBytesPerOp: 839, AllocsPerOp: 9,
|
||||||
Measured: NsOp | MbS | BOp | AllocsOp,
|
Measured: NsPerOp | MBPerS | AllocedBytesPerOp | AllocsPerOp,
|
||||||
Ord: 2,
|
Ord: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"BenchmarkClientServerParallel64": []*Bench{
|
"BenchmarkClientServerParallel64": []*Benchmark{
|
||||||
{
|
{
|
||||||
Name: "BenchmarkClientServerParallel64",
|
Name: "BenchmarkClientServerParallel64",
|
||||||
N: 50000, NsOp: 59192, BOp: 7028, AllocsOp: 60,
|
N: 50000, NsPerOp: 59192, AllocedBytesPerOp: 7028, AllocsPerOp: 60,
|
||||||
Measured: NsOp | BOp | AllocsOp,
|
Measured: NsPerOp | AllocedBytesPerOp | AllocsPerOp,
|
||||||
Ord: 3,
|
Ord: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"BenchmarkEncrypt": []*Bench{
|
"BenchmarkEncrypt": []*Benchmark{
|
||||||
{
|
{
|
||||||
Name: "BenchmarkEncrypt",
|
Name: "BenchmarkEncrypt",
|
||||||
N: 100000000, NsOp: 19.6,
|
N: 100000000, NsPerOp: 19.6,
|
||||||
Measured: NsOp,
|
Measured: NsPerOp,
|
||||||
Ord: 0,
|
Ord: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "BenchmarkEncrypt",
|
Name: "BenchmarkEncrypt",
|
||||||
N: 5000000, NsOp: 517,
|
N: 5000000, NsPerOp: 517,
|
||||||
Measured: NsOp,
|
Measured: NsPerOp,
|
||||||
Ord: 1,
|
Ord: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
have, err := ParseBenchSet(strings.NewReader(in))
|
have, err := ParseSet(strings.NewReader(in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err during ParseBenchSet: %v", err)
|
t.Fatalf("unexpected err during ParseSet: %v", err)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(want, have) {
|
if !reflect.DeepEqual(want, have) {
|
||||||
t.Errorf("parsed bench set incorrectly, want %v have %v", want, have)
|
t.Errorf("parsed bench set incorrectly, want %v have %v", want, have)
|
||||||
|
@ -63,71 +63,71 @@ func main() {
|
|||||||
var header bool // Has the header has been displayed yet for a given block?
|
var header bool // Has the header has been displayed yet for a given block?
|
||||||
|
|
||||||
if *magSort {
|
if *magSort {
|
||||||
sort.Sort(ByDeltaNsOp(cmps))
|
sort.Sort(ByDeltaNsPerOp(cmps))
|
||||||
} else {
|
} else {
|
||||||
sort.Sort(ByParseOrder(cmps))
|
sort.Sort(ByParseOrder(cmps))
|
||||||
}
|
}
|
||||||
for _, cmp := range cmps {
|
for _, cmp := range cmps {
|
||||||
if !cmp.Measured(parse.NsOp) {
|
if !cmp.Measured(parse.NsPerOp) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if delta := cmp.DeltaNsOp(); !*changedOnly || delta.Changed() {
|
if delta := cmp.DeltaNsPerOp(); !*changedOnly || delta.Changed() {
|
||||||
if !header {
|
if !header {
|
||||||
fmt.Fprint(w, "benchmark\told ns/op\tnew ns/op\tdelta\n")
|
fmt.Fprint(w, "benchmark\told ns/op\tnew ns/op\tdelta\n")
|
||||||
header = true
|
header = true
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", cmp.Name(), formatNs(cmp.Before.NsOp), formatNs(cmp.After.NsOp), delta.Percent())
|
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", cmp.Name(), formatNs(cmp.Before.NsPerOp), formatNs(cmp.After.NsPerOp), delta.Percent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header = false
|
header = false
|
||||||
if *magSort {
|
if *magSort {
|
||||||
sort.Sort(ByDeltaMbS(cmps))
|
sort.Sort(ByDeltaMBPerS(cmps))
|
||||||
}
|
}
|
||||||
for _, cmp := range cmps {
|
for _, cmp := range cmps {
|
||||||
if !cmp.Measured(parse.MbS) {
|
if !cmp.Measured(parse.MBPerS) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if delta := cmp.DeltaMbS(); !*changedOnly || delta.Changed() {
|
if delta := cmp.DeltaMBPerS(); !*changedOnly || delta.Changed() {
|
||||||
if !header {
|
if !header {
|
||||||
fmt.Fprint(w, "\nbenchmark\told MB/s\tnew MB/s\tspeedup\n")
|
fmt.Fprint(w, "\nbenchmark\told MB/s\tnew MB/s\tspeedup\n")
|
||||||
header = true
|
header = true
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "%s\t%.2f\t%.2f\t%s\n", cmp.Name(), cmp.Before.MbS, cmp.After.MbS, delta.Multiple())
|
fmt.Fprintf(w, "%s\t%.2f\t%.2f\t%s\n", cmp.Name(), cmp.Before.MBPerS, cmp.After.MBPerS, delta.Multiple())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header = false
|
header = false
|
||||||
if *magSort {
|
if *magSort {
|
||||||
sort.Sort(ByDeltaAllocsOp(cmps))
|
sort.Sort(ByDeltaAllocsPerOp(cmps))
|
||||||
}
|
}
|
||||||
for _, cmp := range cmps {
|
for _, cmp := range cmps {
|
||||||
if !cmp.Measured(parse.AllocsOp) {
|
if !cmp.Measured(parse.AllocsPerOp) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if delta := cmp.DeltaAllocsOp(); !*changedOnly || delta.Changed() {
|
if delta := cmp.DeltaAllocsPerOp(); !*changedOnly || delta.Changed() {
|
||||||
if !header {
|
if !header {
|
||||||
fmt.Fprint(w, "\nbenchmark\told allocs\tnew allocs\tdelta\n")
|
fmt.Fprint(w, "\nbenchmark\told allocs\tnew allocs\tdelta\n")
|
||||||
header = true
|
header = true
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.AllocsOp, cmp.After.AllocsOp, delta.Percent())
|
fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.AllocsPerOp, cmp.After.AllocsPerOp, delta.Percent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header = false
|
header = false
|
||||||
if *magSort {
|
if *magSort {
|
||||||
sort.Sort(ByDeltaBOp(cmps))
|
sort.Sort(ByDeltaAllocedBytesPerOp(cmps))
|
||||||
}
|
}
|
||||||
for _, cmp := range cmps {
|
for _, cmp := range cmps {
|
||||||
if !cmp.Measured(parse.BOp) {
|
if !cmp.Measured(parse.AllocedBytesPerOp) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if delta := cmp.DeltaBOp(); !*changedOnly || delta.Changed() {
|
if delta := cmp.DeltaAllocedBytesPerOp(); !*changedOnly || delta.Changed() {
|
||||||
if !header {
|
if !header {
|
||||||
fmt.Fprint(w, "\nbenchmark\told bytes\tnew bytes\tdelta\n")
|
fmt.Fprint(w, "\nbenchmark\told bytes\tnew bytes\tdelta\n")
|
||||||
header = true
|
header = true
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.BOp, cmp.After.BOp, cmp.DeltaBOp().Percent())
|
fmt.Fprintf(w, "%s\t%d\t%d\t%s\n", cmp.Name(), cmp.Before.AllocedBytesPerOp, cmp.After.AllocedBytesPerOp, cmp.DeltaAllocedBytesPerOp().Percent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,13 +137,13 @@ func fatal(msg interface{}) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFile(path string) parse.BenchSet {
|
func parseFile(path string) parse.Set {
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
bb, err := parse.ParseBenchSet(f)
|
bb, err := parse.ParseSet(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ func parseFile(path string) parse.BenchSet {
|
|||||||
return bb
|
return bb
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectBest(bs parse.BenchSet) {
|
func selectBest(bs parse.Set) {
|
||||||
for name, bb := range bs {
|
for name, bb := range bs {
|
||||||
if len(bb) < 2 {
|
if len(bb) < 2 {
|
||||||
continue
|
continue
|
||||||
@ -161,12 +161,12 @@ func selectBest(bs parse.BenchSet) {
|
|||||||
ord := bb[0].Ord
|
ord := bb[0].Ord
|
||||||
best := bb[0]
|
best := bb[0]
|
||||||
for _, b := range bb {
|
for _, b := range bb {
|
||||||
if b.NsOp < best.NsOp {
|
if b.NsPerOp < best.NsPerOp {
|
||||||
b.Ord = ord
|
b.Ord = ord
|
||||||
best = b
|
best = b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bs[name] = []*parse.Bench{best}
|
bs[name] = []*parse.Benchmark{best}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,45 +8,45 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestSelectBest(t *testing.T) {
|
func TestSelectBest(t *testing.T) {
|
||||||
have := parse.BenchSet{
|
have := parse.Set{
|
||||||
"Benchmark1": []*parse.Bench{
|
"Benchmark1": []*parse.Benchmark{
|
||||||
{
|
{
|
||||||
Name: "Benchmark1",
|
Name: "Benchmark1",
|
||||||
N: 10, NsOp: 100, Measured: parse.NsOp,
|
N: 10, NsPerOp: 100, Measured: parse.NsPerOp,
|
||||||
Ord: 0,
|
Ord: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Benchmark1",
|
Name: "Benchmark1",
|
||||||
N: 10, NsOp: 50, Measured: parse.NsOp,
|
N: 10, NsPerOp: 50, Measured: parse.NsPerOp,
|
||||||
Ord: 3,
|
Ord: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Benchmark2": []*parse.Bench{
|
"Benchmark2": []*parse.Benchmark{
|
||||||
{
|
{
|
||||||
Name: "Benchmark2",
|
Name: "Benchmark2",
|
||||||
N: 10, NsOp: 60, Measured: parse.NsOp,
|
N: 10, NsPerOp: 60, Measured: parse.NsPerOp,
|
||||||
Ord: 1,
|
Ord: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Benchmark2",
|
Name: "Benchmark2",
|
||||||
N: 10, NsOp: 500, Measured: parse.NsOp,
|
N: 10, NsPerOp: 500, Measured: parse.NsPerOp,
|
||||||
Ord: 2,
|
Ord: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
want := parse.BenchSet{
|
want := parse.Set{
|
||||||
"Benchmark1": []*parse.Bench{
|
"Benchmark1": []*parse.Benchmark{
|
||||||
{
|
{
|
||||||
Name: "Benchmark1",
|
Name: "Benchmark1",
|
||||||
N: 10, NsOp: 50, Measured: parse.NsOp,
|
N: 10, NsPerOp: 50, Measured: parse.NsPerOp,
|
||||||
Ord: 0,
|
Ord: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Benchmark2": []*parse.Bench{
|
"Benchmark2": []*parse.Benchmark{
|
||||||
{
|
{
|
||||||
Name: "Benchmark2",
|
Name: "Benchmark2",
|
||||||
N: 10, NsOp: 60, Measured: parse.NsOp,
|
N: 10, NsPerOp: 60, Measured: parse.NsPerOp,
|
||||||
Ord: 1,
|
Ord: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -13,12 +13,12 @@ import (
|
|||||||
|
|
||||||
// BenchCmp is a pair of benchmarks.
|
// BenchCmp is a pair of benchmarks.
|
||||||
type BenchCmp struct {
|
type BenchCmp struct {
|
||||||
Before *parse.Bench
|
Before *parse.Benchmark
|
||||||
After *parse.Bench
|
After *parse.Benchmark
|
||||||
}
|
}
|
||||||
|
|
||||||
// Correlate correlates benchmarks from two BenchSets.
|
// Correlate correlates benchmarks from two BenchSets.
|
||||||
func Correlate(before, after parse.BenchSet) (cmps []BenchCmp, warnings []string) {
|
func Correlate(before, after parse.Set) (cmps []BenchCmp, warnings []string) {
|
||||||
cmps = make([]BenchCmp, 0, len(after))
|
cmps = make([]BenchCmp, 0, len(after))
|
||||||
for name, beforebb := range before {
|
for name, beforebb := range before {
|
||||||
afterbb := after[name]
|
afterbb := after[name]
|
||||||
@ -36,12 +36,14 @@ func Correlate(before, after parse.BenchSet) (cmps []BenchCmp, warnings []string
|
|||||||
|
|
||||||
func (c BenchCmp) Name() string { return c.Before.Name }
|
func (c BenchCmp) Name() string { return c.Before.Name }
|
||||||
func (c BenchCmp) String() string { return fmt.Sprintf("<%s, %s>", c.Before, c.After) }
|
func (c BenchCmp) String() string { return fmt.Sprintf("<%s, %s>", c.Before, c.After) }
|
||||||
func (c BenchCmp) Measured(flag int) bool { return c.Before.Measured&c.After.Measured&flag != 0 }
|
func (c BenchCmp) Measured(flag int) bool { return (c.Before.Measured & c.After.Measured & flag) != 0 }
|
||||||
func (c BenchCmp) DeltaNsOp() Delta { return Delta{c.Before.NsOp, c.After.NsOp} }
|
func (c BenchCmp) DeltaNsPerOp() Delta { return Delta{c.Before.NsPerOp, c.After.NsPerOp} }
|
||||||
func (c BenchCmp) DeltaMbS() Delta { return Delta{c.Before.MbS, c.After.MbS} }
|
func (c BenchCmp) DeltaMBPerS() Delta { return Delta{c.Before.MBPerS, c.After.MBPerS} }
|
||||||
func (c BenchCmp) DeltaBOp() Delta { return Delta{float64(c.Before.BOp), float64(c.After.BOp)} }
|
func (c BenchCmp) DeltaAllocedBytesPerOp() Delta {
|
||||||
func (c BenchCmp) DeltaAllocsOp() Delta {
|
return Delta{float64(c.Before.AllocedBytesPerOp), float64(c.After.AllocedBytesPerOp)}
|
||||||
return Delta{float64(c.Before.AllocsOp), float64(c.After.AllocsOp)}
|
}
|
||||||
|
func (c BenchCmp) DeltaAllocsPerOp() Delta {
|
||||||
|
return Delta{float64(c.Before.AllocsPerOp), float64(c.After.AllocsPerOp)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delta is the before and after value for a benchmark measurement.
|
// Delta is the before and after value for a benchmark measurement.
|
||||||
@ -117,34 +119,38 @@ func lessByDelta(i, j BenchCmp, calcDelta func(BenchCmp) Delta) bool {
|
|||||||
return i.Name() < j.Name()
|
return i.Name() < j.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByDeltaNsOp sorts BenchCmps lexicographically by change
|
// ByDeltaNsPerOp sorts BenchCmps lexicographically by change
|
||||||
// in ns/op, descending, then by benchmark name.
|
// in ns/op, descending, then by benchmark name.
|
||||||
type ByDeltaNsOp []BenchCmp
|
type ByDeltaNsPerOp []BenchCmp
|
||||||
|
|
||||||
func (x ByDeltaNsOp) Len() int { return len(x) }
|
func (x ByDeltaNsPerOp) Len() int { return len(x) }
|
||||||
func (x ByDeltaNsOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
func (x ByDeltaNsPerOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
func (x ByDeltaNsOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaNsOp) }
|
func (x ByDeltaNsPerOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaNsPerOp) }
|
||||||
|
|
||||||
// ByDeltaMbS sorts BenchCmps lexicographically by change
|
// ByDeltaMBPerS sorts BenchCmps lexicographically by change
|
||||||
// in MB/s, descending, then by benchmark name.
|
// in MB/s, descending, then by benchmark name.
|
||||||
type ByDeltaMbS []BenchCmp
|
type ByDeltaMBPerS []BenchCmp
|
||||||
|
|
||||||
func (x ByDeltaMbS) Len() int { return len(x) }
|
func (x ByDeltaMBPerS) Len() int { return len(x) }
|
||||||
func (x ByDeltaMbS) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
func (x ByDeltaMBPerS) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
func (x ByDeltaMbS) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaMbS) }
|
func (x ByDeltaMBPerS) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaMBPerS) }
|
||||||
|
|
||||||
// ByDeltaBOp sorts BenchCmps lexicographically by change
|
// ByDeltaAllocedBytesPerOp sorts BenchCmps lexicographically by change
|
||||||
// in B/op, descending, then by benchmark name.
|
// in B/op, descending, then by benchmark name.
|
||||||
type ByDeltaBOp []BenchCmp
|
type ByDeltaAllocedBytesPerOp []BenchCmp
|
||||||
|
|
||||||
func (x ByDeltaBOp) Len() int { return len(x) }
|
func (x ByDeltaAllocedBytesPerOp) Len() int { return len(x) }
|
||||||
func (x ByDeltaBOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
func (x ByDeltaAllocedBytesPerOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
func (x ByDeltaBOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaBOp) }
|
func (x ByDeltaAllocedBytesPerOp) Less(i, j int) bool {
|
||||||
|
return lessByDelta(x[i], x[j], BenchCmp.DeltaAllocedBytesPerOp)
|
||||||
|
}
|
||||||
|
|
||||||
// ByDeltaAllocsOp sorts BenchCmps lexicographically by change
|
// ByDeltaAllocsPerOp sorts BenchCmps lexicographically by change
|
||||||
// in allocs/op, descending, then by benchmark name.
|
// in allocs/op, descending, then by benchmark name.
|
||||||
type ByDeltaAllocsOp []BenchCmp
|
type ByDeltaAllocsPerOp []BenchCmp
|
||||||
|
|
||||||
func (x ByDeltaAllocsOp) Len() int { return len(x) }
|
func (x ByDeltaAllocsPerOp) Len() int { return len(x) }
|
||||||
func (x ByDeltaAllocsOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
func (x ByDeltaAllocsPerOp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
func (x ByDeltaAllocsOp) Less(i, j int) bool { return lessByDelta(x[i], x[j], BenchCmp.DeltaAllocsOp) }
|
func (x ByDeltaAllocsPerOp) Less(i, j int) bool {
|
||||||
|
return lessByDelta(x[i], x[j], BenchCmp.DeltaAllocsPerOp)
|
||||||
|
}
|
||||||
|
@ -54,29 +54,29 @@ func TestCorrelate(t *testing.T) {
|
|||||||
// Benches that are going to be successfully correlated get N thus:
|
// Benches that are going to be successfully correlated get N thus:
|
||||||
// 0x<counter><num benches><b = before | a = after>
|
// 0x<counter><num benches><b = before | a = after>
|
||||||
// Read this: "<counter> of <num benches>, from <before|after>".
|
// Read this: "<counter> of <num benches>, from <before|after>".
|
||||||
before := parse.BenchSet{
|
before := parse.Set{
|
||||||
"BenchmarkOneEach": []*parse.Bench{{Name: "BenchmarkOneEach", N: 0x11b}},
|
"BenchmarkOneEach": []*parse.Benchmark{{Name: "BenchmarkOneEach", N: 0x11b}},
|
||||||
"BenchmarkOneToNone": []*parse.Bench{{Name: "BenchmarkOneToNone"}},
|
"BenchmarkOneToNone": []*parse.Benchmark{{Name: "BenchmarkOneToNone"}},
|
||||||
"BenchmarkOneToTwo": []*parse.Bench{{Name: "BenchmarkOneToTwo"}},
|
"BenchmarkOneToTwo": []*parse.Benchmark{{Name: "BenchmarkOneToTwo"}},
|
||||||
"BenchmarkTwoToOne": []*parse.Bench{
|
"BenchmarkTwoToOne": []*parse.Benchmark{
|
||||||
{Name: "BenchmarkTwoToOne"},
|
{Name: "BenchmarkTwoToOne"},
|
||||||
{Name: "BenchmarkTwoToOne"},
|
{Name: "BenchmarkTwoToOne"},
|
||||||
},
|
},
|
||||||
"BenchmarkTwoEach": []*parse.Bench{
|
"BenchmarkTwoEach": []*parse.Benchmark{
|
||||||
{Name: "BenchmarkTwoEach", N: 0x12b},
|
{Name: "BenchmarkTwoEach", N: 0x12b},
|
||||||
{Name: "BenchmarkTwoEach", N: 0x22b},
|
{Name: "BenchmarkTwoEach", N: 0x22b},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
after := parse.BenchSet{
|
after := parse.Set{
|
||||||
"BenchmarkOneEach": []*parse.Bench{{Name: "BenchmarkOneEach", N: 0x11a}},
|
"BenchmarkOneEach": []*parse.Benchmark{{Name: "BenchmarkOneEach", N: 0x11a}},
|
||||||
"BenchmarkNoneToOne": []*parse.Bench{{Name: "BenchmarkNoneToOne"}},
|
"BenchmarkNoneToOne": []*parse.Benchmark{{Name: "BenchmarkNoneToOne"}},
|
||||||
"BenchmarkTwoToOne": []*parse.Bench{{Name: "BenchmarkTwoToOne"}},
|
"BenchmarkTwoToOne": []*parse.Benchmark{{Name: "BenchmarkTwoToOne"}},
|
||||||
"BenchmarkOneToTwo": []*parse.Bench{
|
"BenchmarkOneToTwo": []*parse.Benchmark{
|
||||||
{Name: "BenchmarkOneToTwo"},
|
{Name: "BenchmarkOneToTwo"},
|
||||||
{Name: "BenchmarkOneToTwo"},
|
{Name: "BenchmarkOneToTwo"},
|
||||||
},
|
},
|
||||||
"BenchmarkTwoEach": []*parse.Bench{
|
"BenchmarkTwoEach": []*parse.Benchmark{
|
||||||
{Name: "BenchmarkTwoEach", N: 0x12a},
|
{Name: "BenchmarkTwoEach", N: 0x12a},
|
||||||
{Name: "BenchmarkTwoEach", N: 0x22a},
|
{Name: "BenchmarkTwoEach", N: 0x22a},
|
||||||
},
|
},
|
||||||
@ -110,14 +110,14 @@ func TestCorrelate(t *testing.T) {
|
|||||||
|
|
||||||
func TestBenchCmpSorting(t *testing.T) {
|
func TestBenchCmpSorting(t *testing.T) {
|
||||||
c := []BenchCmp{
|
c := []BenchCmp{
|
||||||
{&parse.Bench{Name: "BenchmarkMuchFaster", NsOp: 10, Ord: 3}, &parse.Bench{Name: "BenchmarkMuchFaster", NsOp: 1}},
|
{&parse.Benchmark{Name: "BenchmarkMuchFaster", NsPerOp: 10, Ord: 3}, &parse.Benchmark{Name: "BenchmarkMuchFaster", NsPerOp: 1}},
|
||||||
{&parse.Bench{Name: "BenchmarkSameB", NsOp: 5, Ord: 1}, &parse.Bench{Name: "BenchmarkSameB", NsOp: 5}},
|
{&parse.Benchmark{Name: "BenchmarkSameB", NsPerOp: 5, Ord: 1}, &parse.Benchmark{Name: "BenchmarkSameB", NsPerOp: 5}},
|
||||||
{&parse.Bench{Name: "BenchmarkSameA", NsOp: 5, Ord: 2}, &parse.Bench{Name: "BenchmarkSameA", NsOp: 5}},
|
{&parse.Benchmark{Name: "BenchmarkSameA", NsPerOp: 5, Ord: 2}, &parse.Benchmark{Name: "BenchmarkSameA", NsPerOp: 5}},
|
||||||
{&parse.Bench{Name: "BenchmarkSlower", NsOp: 10, Ord: 0}, &parse.Bench{Name: "BenchmarkSlower", NsOp: 11}},
|
{&parse.Benchmark{Name: "BenchmarkSlower", NsPerOp: 10, Ord: 0}, &parse.Benchmark{Name: "BenchmarkSlower", NsPerOp: 11}},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test just one magnitude-based sort order; they are symmetric.
|
// Test just one magnitude-based sort order; they are symmetric.
|
||||||
sort.Sort(ByDeltaNsOp(c))
|
sort.Sort(ByDeltaNsPerOp(c))
|
||||||
want := []string{"BenchmarkMuchFaster", "BenchmarkSlower", "BenchmarkSameA", "BenchmarkSameB"}
|
want := []string{"BenchmarkMuchFaster", "BenchmarkSlower", "BenchmarkSameA", "BenchmarkSameB"}
|
||||||
have := []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()}
|
have := []string{c[0].Name(), c[1].Name(), c[2].Name(), c[3].Name()}
|
||||||
if !reflect.DeepEqual(want, have) {
|
if !reflect.DeepEqual(want, have) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user