Skip to content
This repository was archived by the owner on Dec 14, 2023. It is now read-only.

Commit 8183eb4

Browse files
committed
Merge pull request #198 from pcc/libgo-benchcomp
Tools for analyzing benchmark results
2 parents 2b72ce9 + 62ad680 commit 8183eb4

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

utils/benchcomp/README

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
These are some quick and dirty tools for measuring the performance impact
2+
of a change to llgo by sampling the results of running the libgo benchmark
3+
suite. They can be used to calculate the geo-mean and 95% confidence interval
4+
using the Student's t-test. The benchcomp program massages the output of the
5+
Go benchmark tools into a form that can be read by the R program analyze.R
6+
which runs the statistics.
7+
8+
To use, clpatch this into gofrontend:
9+
https://codereview.appspot.com/103550047/
10+
11+
then run:
12+
13+
make
14+
make -C workdir/gofrontend_build/libgo-stage1 bench 2>&1 | tee before.out
15+
# make changes
16+
make
17+
make -C workdir/gofrontend_build/libgo-stage1 bench 2>&1 | tee after.out
18+
utils/benchcomp/benchcomp benchns before.out after.out | R -f utils/benchcomp/analyze.R
19+
20+
The results should be displayed on stdout.

utils/benchcomp/analyze.R

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
sc <- read.table(file('stdin'))
2+
3+
# Take the log of the ratio. Our null hypothesis is a normal distribution
4+
# around zero.
5+
tt <- t.test(log(sc$V2 / sc$V3))
6+
tt
7+
8+
# This gives us the geo-mean as we are taking the exponent of the linear mean
9+
# of logarithms.
10+
1 - 1/exp(tt$estimate)
11+
12+
# Likewise for the confidence interval.
13+
1 - 1/exp(tt$conf.int)

utils/benchcomp/main.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"debug/elf"
6+
"fmt"
7+
"os"
8+
"strconv"
9+
"strings"
10+
)
11+
12+
func symsizes(path string) map[string]float64 {
13+
m := make(map[string]float64)
14+
f, err := elf.Open(path)
15+
if err != nil {
16+
panic(err.Error())
17+
}
18+
syms, err := f.Symbols()
19+
if err != nil {
20+
panic(err.Error())
21+
}
22+
for _, sym := range syms {
23+
if sym.Section < elf.SectionIndex(len(f.Sections)) && f.Sections[sym.Section].Name == ".text" {
24+
m[sym.Name] = float64(sym.Size)
25+
}
26+
}
27+
return m
28+
}
29+
30+
func benchnums(path, stat string) map[string]float64 {
31+
m := make(map[string]float64)
32+
33+
fh, err := os.Open(path)
34+
if err != nil {
35+
panic(err.Error())
36+
}
37+
38+
scanner := bufio.NewScanner(fh)
39+
for scanner.Scan() {
40+
elems := strings.Split(scanner.Text(), "\t")
41+
if !strings.HasPrefix(elems[0], "Benchmark") || len(elems) < 3 {
42+
continue
43+
}
44+
var s string
45+
for _, elem := range elems[2:] {
46+
selems := strings.Split(strings.TrimSpace(elem), " ")
47+
if selems[1] == stat {
48+
s = selems[0]
49+
}
50+
}
51+
if s != "" {
52+
ns, err := strconv.ParseFloat(s, 64)
53+
if err != nil {
54+
panic(scanner.Text() + " ---- " + err.Error())
55+
}
56+
m[elems[0]] = ns
57+
}
58+
}
59+
60+
if err := scanner.Err(); err != nil {
61+
panic(err)
62+
}
63+
64+
return m
65+
}
66+
67+
func main() {
68+
var cmp func(string) map[string]float64
69+
switch os.Args[1] {
70+
case "symsizes":
71+
cmp = symsizes
72+
73+
case "benchns":
74+
cmp = func(path string) map[string]float64 {
75+
return benchnums(path, "ns/op")
76+
}
77+
78+
case "benchallocs":
79+
cmp = func(path string) map[string]float64 {
80+
return benchnums(path, "allocs/op")
81+
}
82+
}
83+
84+
syms1 := cmp(os.Args[2])
85+
syms2 := cmp(os.Args[3])
86+
87+
for n, z1 := range syms1 {
88+
if z2, ok := syms2[n]; ok && z2 != 0 {
89+
fmt.Printf("%s %f %f %f\n", n, z1, z2, z1/z2)
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)