Skip to content

Commit e1fb0da

Browse files
committed
Add benchparse tool
1 parent 01c83fa commit e1fb0da

File tree

5 files changed

+305
-47
lines changed

5 files changed

+305
-47
lines changed

benchparse/main.go

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"io"
7+
"os"
8+
"sort"
9+
"strconv"
10+
"strings"
11+
12+
"golang.org/x/perf/benchstat"
13+
)
14+
15+
func main() {
16+
if len(os.Args) < 2 {
17+
panic("need to specify input file")
18+
}
19+
fIn, err := os.Open(os.Args[1])
20+
if err != nil {
21+
panic(err)
22+
}
23+
24+
c := benchstat.Collection{}
25+
if err := c.AddFile("config1", fIn); err != nil {
26+
panic(err)
27+
}
28+
tables := c.Tables()
29+
30+
reports, err := genReports(tables)
31+
if err != nil {
32+
panic(err)
33+
}
34+
if err := processReports(reports); err != nil {
35+
panic(err)
36+
}
37+
38+
fOut, err := os.Create("out.csv")
39+
if err != nil {
40+
panic(err)
41+
}
42+
defer fOut.Close()
43+
if err := writeReports(reports, fOut); err != nil {
44+
panic(err)
45+
}
46+
}
47+
48+
// All metrics for all benchmarks for one HAMT configuration
49+
type HAMTReport struct {
50+
ID string
51+
Benchmarks map[string]Benchmark
52+
}
53+
54+
func (hr *HAMTReport) Write(datawriter *bufio.Writer) error {
55+
// Write title
56+
if _, err := datawriter.WriteString(hr.ID + "\n"); err != nil {
57+
return err
58+
}
59+
60+
// Write benchmarks
61+
for _, benchmark := range hr.Benchmarks {
62+
if err := benchmark.Write(datawriter); err != nil {
63+
return err
64+
}
65+
}
66+
return nil
67+
}
68+
69+
type Benchmark struct {
70+
Name string
71+
Metrics map[string]struct{}
72+
Sweep map[int]map[string]float64 // map[Bitwidth]MetricsMap
73+
}
74+
75+
func (b *Benchmark) Write(datawriter *bufio.Writer) error {
76+
// Get sorted keys
77+
metrics := make([]string, 0)
78+
for metric := range b.Metrics {
79+
metrics = append(metrics, metric)
80+
}
81+
sort.Strings(metrics)
82+
83+
bws := make([]int, 0)
84+
for bw := range b.Sweep {
85+
bws = append(bws, bw)
86+
}
87+
sort.Ints(bws)
88+
89+
// Write headers
90+
headers := []string{"Benchmark", "Bitwidth"}
91+
headers = append(headers, metrics...)
92+
if _, err := datawriter.WriteString(strings.Join(headers, ",")); err != nil {
93+
return err
94+
}
95+
if _, err := datawriter.WriteString("\n"); err != nil {
96+
return err
97+
}
98+
99+
// Write sweeps
100+
for _, bw := range bws {
101+
if _, err := datawriter.WriteString(b.Name); err != nil {
102+
return err
103+
}
104+
if _, err := datawriter.WriteString("," + strconv.Itoa(bw)); err != nil {
105+
return err
106+
}
107+
for _, metric := range metrics {
108+
m, found := b.Sweep[bw][metric]
109+
if !found {
110+
// empty column
111+
if _, err := datawriter.WriteString(","); err != nil {
112+
return err
113+
}
114+
continue
115+
}
116+
if _, err := datawriter.WriteString(fmt.Sprintf(",%.3f", m)); err != nil {
117+
return err
118+
}
119+
}
120+
if _, err := datawriter.WriteString("\n"); err != nil {
121+
return err
122+
}
123+
}
124+
125+
return nil
126+
}
127+
128+
func writeReports(reports map[string]*HAMTReport, w io.Writer) error {
129+
datawriter := bufio.NewWriter(w)
130+
for _, report := range reports {
131+
if err := report.Write(datawriter); err != nil {
132+
return err
133+
}
134+
if _, err := datawriter.WriteString("\n\n"); err != nil {
135+
return err
136+
}
137+
}
138+
return datawriter.Flush()
139+
}
140+
141+
func genReports(tables []*benchstat.Table) (map[string]*HAMTReport, error) {
142+
reports := make(map[string]*HAMTReport)
143+
for _, table := range tables {
144+
for _, row := range table.Rows {
145+
if len(row.Metrics) == 0 {
146+
continue
147+
}
148+
if len(row.Metrics) >= 2 {
149+
panic("don't know how to handle lots of metrics")
150+
}
151+
good, bname, hamtID, bw := parseBench(row.Benchmark)
152+
if !good {
153+
continue
154+
}
155+
fmt.Printf("bname: %s, hamtID: %s, bw: %d\n", bname, hamtID, bw)
156+
157+
if _, found := reports[hamtID]; !found {
158+
reports[hamtID] = &HAMTReport{
159+
ID: hamtID,
160+
Benchmarks: make(map[string]Benchmark),
161+
}
162+
}
163+
if _, found := reports[hamtID].Benchmarks[bname]; !found {
164+
reports[hamtID].Benchmarks[bname] = Benchmark{
165+
Name: bname,
166+
Metrics: make(map[string]struct{}),
167+
Sweep: make(map[int]map[string]float64),
168+
}
169+
}
170+
if _, found := reports[hamtID].Benchmarks[bname].Sweep[bw]; !found {
171+
reports[hamtID].Benchmarks[bname].Sweep[bw] = make(map[string]float64)
172+
}
173+
reports[hamtID].Benchmarks[bname].Metrics[table.Metric] = struct{}{}
174+
reports[hamtID].Benchmarks[bname].Sweep[bw][table.Metric] = row.Metrics[0].Mean
175+
}
176+
}
177+
return reports, nil
178+
}
179+
180+
const GasCostGet = 114617
181+
const GasCostPut = 353640
182+
const GasCostPerBytePut = 1300
183+
184+
const EffectiveTimeGet = 11462
185+
const EffectiveTimePut = 35364
186+
187+
const getsKey = "getEvts"
188+
const putsKey = "putsEvts"
189+
const bytesPutKey = "bytesPut"
190+
const timeKey = "time/op"
191+
192+
// Add GasCost, Time/1000, and EffectiveRuntime
193+
func processReports(reports map[string]*HAMTReport) error {
194+
for _, report := range reports {
195+
for _, bench := range report.Benchmarks {
196+
bench.Metrics["gasCost"] = struct{}{}
197+
bench.Metrics["time/1000"] = struct{}{}
198+
bench.Metrics["effectiveRuntime"] = struct{}{}
199+
200+
for _, row := range bench.Sweep {
201+
row["gasCost"] = row[getsKey]*GasCostGet + row[putsKey]*GasCostPut + row[bytesPutKey]*GasCostPerBytePut
202+
row["time/1000"] = row[timeKey] / float64(1000)
203+
row["effectiveRuntime"] = row["time/1000"] + row[getsKey]*EffectiveTimeGet + row[putsKey]*EffectiveTimePut
204+
}
205+
}
206+
}
207+
return nil
208+
}
209+
210+
// Unedited hamt benchmark strings are ugly but consistent
211+
// BenchmarkName/hamtID_--_bw=Bitwidth-8
212+
// This can be simplified once we clean up generation
213+
func parseBench(bstatBench string) (bool, string, string, int) {
214+
slashSeps := strings.Split(bstatBench, "/")
215+
if len(slashSeps) != 2 {
216+
return false, "", "", 0
217+
}
218+
bname := slashSeps[0]
219+
220+
uScoreSeps := strings.Split(slashSeps[1], "_")
221+
if len(uScoreSeps) != 3 {
222+
return false, "", "", 0
223+
}
224+
hamtID := uScoreSeps[0]
225+
226+
bitwidthStr := strings.TrimPrefix(uScoreSeps[2], "bw=")
227+
bitwidthStr = strings.TrimSuffix(bitwidthStr, "-8")
228+
bw, err := strconv.Atoi(bitwidthStr)
229+
if err != nil {
230+
panic(err)
231+
}
232+
return true, bname, hamtID, bw
233+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/spaolacci/murmur3 v1.1.0
88
github.com/stretchr/testify v1.6.1
99
github.com/whyrusleeping/cbor-gen v0.0.0-20200806213330-63aa96ca5488
10+
golang.org/x/perf v0.0.0-20200918155509-d949658356f9
1011
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
1112
)
1213

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
22
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
33
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
4+
github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
45
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
56
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
67
github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU=
@@ -22,6 +23,7 @@ github.com/ipfs/go-ipld-format v0.0.1 h1:HCu4eB/Gh+KD/Q0M8u888RFkorTWNIL3da4oc5d
2223
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
2324
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
2425
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
26+
github.com/mattn/go-sqlite3 v0.0.0-20161215041557-2d44decb4941/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
2527
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
2628
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
2729
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ=
@@ -75,8 +77,14 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
7577
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
7678
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU=
7779
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
80+
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
81+
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
7882
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
7983
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
84+
golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
85+
golang.org/x/perf v0.0.0-20200918155509-d949658356f9 h1:yVBHF5pcQLKR9B+y+dOJ6y68nqJBDWaZ9DhB1Ohg0qE=
86+
golang.org/x/perf v0.0.0-20200918155509-d949658356f9/go.mod h1:FrqOtQDO3iMDVUtw5nNTDFpR1HUCGh00M3kj2wiSzLQ=
87+
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
8088
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
8189
golang.org/x/sys v0.0.0-20190219092855-153ac476189d h1:Z0Ahzd7HltpJtjAHHxX8QFP3j1yYgiuvjbjRzDj/KH0=
8290
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

0 commit comments

Comments
 (0)