Commit fc59af58 authored by Russ Cox's avatar Russ Cox

benchstat: more css-friendly html output

- tag old-vs-new tables with tbody class oldnew
- tag better, worse, unchanged rows with classes
- print one big table, to keep alignment across tables
- tag note column and don't right-align

Change-Id: Ifd3b2103e02781904f6b73eeb47b00340484caf6
Reviewed-on: https://go-review.googlesource.com/35939Reviewed-by: default avatarQuentin Smith <quentin@golang.org>
parent 1b4493ff
......@@ -9,17 +9,28 @@ import (
"html/template"
)
var htmlTemplate = template.Must(template.New("").Parse(
`{{range $i, $table := .}}{{if gt $i 0}}
{{end}}<style>.benchstat tbody td:nth-child(1n+2) { text-align: right; padding: 0em 1em; }</style>
var htmlTemplate = template.Must(template.New("").Parse(`
<table class='benchstat'>
{{if .OldNewDelta}}<tr><th>name</th><th>old {{.Metric}}</th><th>new {{.Metric}}</th><th>delta</th>
{{else if eq (len .Configs) 1}}<tr><th>name</th><th>{{.Metric}}</th>
{{else}}<tr><th>name \ {{.Metric}}</th>{{range .Configs}}<th>{{.}}</th>{{end}}
{{end}}{{range $row := $table.Rows}}<tr><td>{{.Benchmark}}</td>{{range $m := .Metrics}}<td>{{$m.Format $row.Scaler}}</td>{{end}}{{if $table.OldNewDelta}}<td>{{.Delta}}</td><td>{{.Note}}</td>{{end}}
{{- range $i, $table := .}}
<tbody {{if .OldNewDelta}}class='oldnew'{{end}}>
{{if .OldNewDelta -}}
<tr><th>name<th>old {{.Metric}}<th>new {{.Metric}}<th>delta
{{else if eq (len .Configs) 1}}
<tr><th>name<th>{{.Metric}}
{{else -}}
<tr><th>name \ {{.Metric}}{{range .Configs}}<th>{{.}}{{end}}
{{end}}{{range $row := $table.Rows -}}
{{if $table.OldNewDelta -}}
<tr class='{{if eq .Change 1}}better{{else if eq .Change -1}}worse{{else}}unchanged{{end}}'>
{{- else -}}
<tr>
{{- end -}}
<td>{{.Benchmark}}{{range .Metrics}}<td>{{.Format $row.Scaler}}{{end}}{{if $table.OldNewDelta}}<td>{{.Delta}}<td class='note'>{{.Note}}{{end}}
{{end -}}
</tbody>
{{end}}
</table>
{{end}}`))
`))
// FormatHTML appends an HTML formatting of the tables to buf.
func FormatHTML(buf *bytes.Buffer, tables []*Table) {
......
......@@ -147,9 +147,13 @@ func main() {
var buf bytes.Buffer
if *flagHTML {
buf.WriteString(htmlStyle)
FormatHTML(&buf, tables)
} else {
FormatText(&buf, tables)
}
os.Stdout.Write(buf.Bytes())
}
var htmlStyle = `<style>.benchstat tbody td:nth-child(1n+2):not(.note) { text-align: right; padding: 0em 1em; }</style>
`
......@@ -25,7 +25,7 @@ type Row struct {
Metrics []*Metrics // columns of statistics
Delta string // formatted percent change
Note string // additional information
Same bool // likely no change
Change int // +1 better, -1 worse, 0 unchanged
}
// Tables returns tables comparing the benchmarks in the collection.
......@@ -81,7 +81,13 @@ func (c *Collection) Tables(deltaTest DeltaTest) []*Table {
} else if testerr != nil {
row.Note = fmt.Sprintf("(%s)", testerr)
} else if pval < *flagAlpha {
row.Delta = fmt.Sprintf("%+.2f%%", ((new.Mean/old.Mean)-1.0)*100.0)
pct := ((new.Mean / old.Mean) - 1.0) * 100.0
row.Delta = fmt.Sprintf("%+.2f%%", pct)
if pct < 0 == (table.Metric != "speed") { // smaller is better, except speeds
row.Change = +1
} else {
row.Change = -1
}
}
if row.Note == "" && pval != -1 {
row.Note = fmt.Sprintf("(p=%0.3f n=%d+%d)", pval, len(old.RValues), len(new.RValues))
......
<style>.benchstat tbody td:nth-child(1n+2) { text-align: right; padding: 0em 1em; }</style>
<table class='benchstat'>
<tr><th>name</th><th>old time/op</th><th>new time/op</th><th>delta</th>
<tr><td>GobEncode</td><td>13.6ms ± 1%</td><td>11.8ms ± 1%</td><td>-13.31%</td><td>(p=0.016 n=4&#43;5)</td>
<tr><td>JSONEncode</td><td>32.1ms ± 1%</td><td>31.8ms ± 1%</td><td>~</td><td>(p=0.286 n=4&#43;5)</td>
</table>
<style>.benchstat tbody td:nth-child(1n+2):not(.note) { text-align: right; padding: 0em 1em; }</style>
<style>.benchstat tbody td:nth-child(1n+2) { text-align: right; padding: 0em 1em; }</style>
<table class='benchstat'>
<tr><th>name</th><th>old speed</th><th>new speed</th><th>delta</th>
<tr><td>GobEncode</td><td>56.4MB/s ± 1%</td><td>65.1MB/s ± 1%</td><td>&#43;15.36%</td><td>(p=0.016 n=4&#43;5)</td>
<tr><td>JSONEncode</td><td>60.4MB/s ± 1%</td><td>61.1MB/s ± 2%</td><td>~</td><td>(p=0.286 n=4&#43;5)</td>
<tbody class='oldnew'>
<tr><th>name<th>old time/op<th>new time/op<th>delta
<tr class='better'><td>GobEncode<td>13.6ms ± 1%<td>11.8ms ± 1%<td>-13.31%<td class='note'>(p=0.016 n=4&#43;5)
<tr class='unchanged'><td>JSONEncode<td>32.1ms ± 1%<td>31.8ms ± 1%<td>~<td class='note'>(p=0.286 n=4&#43;5)
</tbody>
<tbody class='oldnew'>
<tr><th>name<th>old speed<th>new speed<th>delta
<tr class='better'><td>GobEncode<td>56.4MB/s ± 1%<td>65.1MB/s ± 1%<td>&#43;15.36%<td class='note'>(p=0.016 n=4&#43;5)
<tr class='unchanged'><td>JSONEncode<td>60.4MB/s ± 1%<td>61.1MB/s ± 2%<td>~<td class='note'>(p=0.286 n=4&#43;5)
</tbody>
</table>
<style>.benchstat tbody td:nth-child(1n+2) { text-align: right; padding: 0em 1em; }</style>
<table class='benchstat'>
<tr><th>name</th><th>time/op</th>
<tr><td>GobEncode</td><td>13.6ms ± 1%</td>
<tr><td>JSONEncode</td><td>32.1ms ± 1%</td>
</table>
<style>.benchstat tbody td:nth-child(1n+2):not(.note) { text-align: right; padding: 0em 1em; }</style>
<style>.benchstat tbody td:nth-child(1n+2) { text-align: right; padding: 0em 1em; }</style>
<table class='benchstat'>
<tr><th>name</th><th>speed</th>
<tr><td>GobEncode</td><td>56.4MB/s ± 1%</td>
<tr><td>JSONEncode</td><td>60.4MB/s ± 1%</td>
<tbody >
<tr><th>name<th>time/op
<tr><td>GobEncode<td>13.6ms ± 1%
<tr><td>JSONEncode<td>32.1ms ± 1%
</tbody>
<tbody >
<tr><th>name<th>speed
<tr><td>GobEncode<td>56.4MB/s ± 1%
<tr><td>JSONEncode<td>60.4MB/s ± 1%
</tbody>
</table>
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment