benchstat: use template to generate html

The generated html changes in a few minor ways,
either unavoidable or not worth working around:

- Trailing <td></td> at end of row no longer removed.
- <td>~</td> instead of <td>~    </td>
- Literal + escaped to &#43;

Change-Id: I73a0d1f74ff4c3597dd96b1a4dac2d6a3d5cc462
Reviewed-on: https://go-review.googlesource.com/35938
Reviewed-by: Quentin Smith <quentin@golang.org>
diff --git a/cmd/benchstat/data.go b/cmd/benchstat/data.go
index c6ac4ec..998dd1e 100644
--- a/cmd/benchstat/data.go
+++ b/cmd/benchstat/data.go
@@ -44,9 +44,6 @@
 
 // FormatMean formats m.Mean using scaler.
 func (m *Metrics) FormatMean(scaler Scaler) string {
-	if m == nil {
-		return ""
-	}
 	var s string
 	if scaler != nil {
 		s = scaler(m.Mean)
@@ -59,7 +56,7 @@
 // FormatDiff computes and formats the percent variation of max and min compared to mean.
 // If b.Mean or b.Max is zero, FormatDiff returns an empty string.
 func (m *Metrics) FormatDiff() string {
-	if m == nil || m.Mean == 0 || m.Max == 0 {
+	if m.Mean == 0 || m.Max == 0 {
 		return ""
 	}
 	diff := 1 - m.Min/m.Mean
@@ -71,7 +68,7 @@
 
 // Format returns a textual formatting of "Mean ±Diff" using scaler.
 func (m *Metrics) Format(scaler Scaler) string {
-	if m == nil {
+	if m.Unit == "" {
 		return ""
 	}
 	mean := m.FormatMean(scaler)
diff --git a/cmd/benchstat/html.go b/cmd/benchstat/html.go
index c4280ab..b4c9511 100644
--- a/cmd/benchstat/html.go
+++ b/cmd/benchstat/html.go
@@ -6,34 +6,27 @@
 
 import (
 	"bytes"
-	"fmt"
-	"html"
+	"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>
+<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}}
+{{end -}}
+</table>
+{{end}}`))
+
 // FormatHTML appends an HTML formatting of the tables to buf.
 func FormatHTML(buf *bytes.Buffer, tables []*Table) {
-	var textTables [][]*textRow
-	for _, t := range tables {
-		textTables = append(textTables, toText(t))
-	}
-
-	for i, table := range textTables {
-		if i > 0 {
-			fmt.Fprintf(buf, "\n")
-		}
-		fmt.Fprintf(buf, "<style>.benchstat tbody td:nth-child(1n+2) { text-align: right; padding: 0em 1em; }</style>\n")
-		fmt.Fprintf(buf, "<table class='benchstat'>\n")
-		printRow := func(row *textRow, tag string) {
-			fmt.Fprintf(buf, "<tr>")
-			for _, cell := range row.cols {
-				fmt.Fprintf(buf, "<%s>%s</%s>", tag, html.EscapeString(cell), tag)
-			}
-			fmt.Fprintf(buf, "\n")
-		}
-		printRow(table[0], "th")
-		for _, row := range table[1:] {
-			printRow(row, "td")
-		}
-		fmt.Fprintf(buf, "</table>\n")
+	err := htmlTemplate.Execute(buf, tables)
+	if err != nil {
+		// Only possible errors here are template not matching data structure.
+		// Don't make caller check - it's our fault.
+		panic(err)
 	}
 }
diff --git a/cmd/benchstat/main_test.go b/cmd/benchstat/main_test.go
index 67c2fe8..331b29f 100644
--- a/cmd/benchstat/main_test.go
+++ b/cmd/benchstat/main_test.go
@@ -22,6 +22,7 @@
 	if t.Failed() {
 		t.Fatal("skipping other tests")
 	}
+	check(t, "exampleoldhtml", "-html", "exampleold.txt")
 	check(t, "examplehtml", "-html", "exampleold.txt", "examplenew.txt")
 	if t.Failed() {
 		t.Fatal("skipping other tests")
diff --git a/cmd/benchstat/table.go b/cmd/benchstat/table.go
index 51be88c..9c7c937 100644
--- a/cmd/benchstat/table.go
+++ b/cmd/benchstat/table.go
@@ -12,16 +12,17 @@
 
 // A Table is a table for display in the benchstat output.
 type Table struct {
-	Metric  string
-	Configs []string
-	Rows    []*Row
+	Metric      string
+	OldNewDelta bool // is this an old-new-delta table?
+	Configs     []string
+	Rows        []*Row
 }
 
 // A Row is a table row for display in the benchstat output.
 type Row struct {
 	Benchmark string     // benchmark name
 	Scaler    Scaler     // formatter for stats means
-	Metrics   []*Metrics // columns of statistics (nil slice entry means no data)
+	Metrics   []*Metrics // columns of statistics
 	Delta     string     // formatted percent change
 	Note      string     // additional information
 	Same      bool       // likely no change
@@ -40,31 +41,33 @@
 		table := new(Table)
 		table.Configs = c.Configs
 		table.Metric = metricOf(key.Unit)
+		table.OldNewDelta = len(c.Configs) == 2
 		for _, key.Benchmark = range c.Benchmarks {
 			row := &Row{Benchmark: key.Benchmark}
 
 			for _, key.Config = range c.Configs {
 				m := c.Metrics[key]
-				row.Metrics = append(row.Metrics, m)
 				if m == nil {
+					row.Metrics = append(row.Metrics, new(Metrics))
 					continue
 				}
+				row.Metrics = append(row.Metrics, m)
 				if row.Scaler == nil {
 					row.Scaler = NewScaler(m.Mean, m.Unit)
 				}
 			}
 
 			// If there are only two configs being compared, add stats.
-			// If one is missing, omit line entirely.
-			// TODO: Control this better.
-			if len(c.Configs) == 2 {
+			if table.OldNewDelta {
 				k0 := key
 				k0.Config = c.Configs[0]
 				k1 := key
 				k1.Config = c.Configs[1]
 				old := c.Metrics[k0]
 				new := c.Metrics[k1]
-				if old == nil || new == nil {
+				// If one is missing, omit row entirely.
+				// TODO: Control this better.
+				if old == new || new == nil {
 					continue
 				}
 				pval, testerr := deltaTest(old, new)
@@ -90,7 +93,7 @@
 
 		if len(table.Rows) > 0 {
 			if *flagGeomean {
-				addGeomean(c, table, key.Unit, len(c.Configs) == 2)
+				addGeomean(c, table, key.Unit, table.OldNewDelta)
 			}
 			tables = append(tables, table)
 		}
@@ -128,7 +131,7 @@
 			}
 		}
 		if len(means) == 0 {
-			row.Metrics = append(row.Metrics, nil)
+			row.Metrics = append(row.Metrics, new(Metrics))
 			delta = false
 		} else {
 			geomean := stats.GeoMean(means)
diff --git a/cmd/benchstat/testdata/examplehtml.golden b/cmd/benchstat/testdata/examplehtml.golden
index 34c4c05..b47e1fd 100644
--- a/cmd/benchstat/testdata/examplehtml.golden
+++ b/cmd/benchstat/testdata/examplehtml.golden
@@ -1,13 +1,13 @@
 <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+5)</td>
-<tr><td>JSONEncode</td><td>32.1ms ± 1%</td><td>31.8ms ± 1%</td><td>~   </td><td>(p=0.286 n=4+5)</td>
+<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) { 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>+15.36%</td><td>(p=0.016 n=4+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+5)</td>
+<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>
 </table>
diff --git a/cmd/benchstat/testdata/exampleoldhtml.golden b/cmd/benchstat/testdata/exampleoldhtml.golden
new file mode 100644
index 0000000..b056fc6
--- /dev/null
+++ b/cmd/benchstat/testdata/exampleoldhtml.golden
@@ -0,0 +1,13 @@
+<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) { 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>
+</table>
diff --git a/cmd/benchstat/testdata/oldnew4html.golden b/cmd/benchstat/testdata/oldnew4html.golden
index 85cb796..7b070ef 100644
--- a/cmd/benchstat/testdata/oldnew4html.golden
+++ b/cmd/benchstat/testdata/oldnew4html.golden
@@ -1,81 +1,81 @@
 <style>.benchstat tbody td:nth-child(1n+2) { text-align: right; padding: 0em 1em; }</style>
 <table class='benchstat'>
 <tr><th>name \ time/op</th><th>old.txt</th><th>new.txt</th><th>slashslash4.txt</th>
-<tr><td>CRC32/poly=IEEE/size=15/align=0-8</td><td>46.9ns ± 8%</td><td>44.5ns ± 3%</td>
-<tr><td>CRC32/poly=IEEE/size=15/align=1-8</td><td>44.7ns ± 5%</td><td>44.5ns ± 4%</td>
+<tr><td>CRC32/poly=IEEE/size=15/align=0-8</td><td>46.9ns ± 8%</td><td>44.5ns ± 3%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=15/align=1-8</td><td>44.7ns ± 5%</td><td>44.5ns ± 4%</td><td></td>
 <tr><td>CRC32/poly=IEEE/size=40/align=0-8</td><td>41.0ns ± 1%</td><td>42.5ns ± 6%</td><td>42.1ns ± 3%</td>
 <tr><td>CRC32/poly=IEEE/size=40/align=1-8</td><td>41.1ns ± 1%</td><td>42.0ns ± 3%</td><td>41.7ns ± 5%</td>
-<tr><td>CRC32/poly=IEEE/size=512/align=0-8</td><td>238ns ± 5%</td><td>57ns ± 3%</td>
-<tr><td>CRC32/poly=IEEE/size=512/align=1-8</td><td>236ns ± 3%</td><td>57ns ± 3%</td>
-<tr><td>CRC32/poly=IEEE/size=1kB/align=0-8</td><td>452ns ± 4%</td><td>94ns ± 2%</td>
-<tr><td>CRC32/poly=IEEE/size=1kB/align=1-8</td><td>444ns ± 2%</td><td>93ns ± 2%</td>
+<tr><td>CRC32/poly=IEEE/size=512/align=0-8</td><td>238ns ± 5%</td><td>57ns ± 3%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=512/align=1-8</td><td>236ns ± 3%</td><td>57ns ± 3%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=1kB/align=0-8</td><td>452ns ± 4%</td><td>94ns ± 2%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=1kB/align=1-8</td><td>444ns ± 2%</td><td>93ns ± 2%</td><td></td>
 <tr><td>CRC32/poly=IEEE/size=4kB/align=0-8</td><td>1.74µs ± 8%</td><td>0.30µs ± 1%</td><td>1.68µs ± 2%</td>
 <tr><td>CRC32/poly=IEEE/size=4kB/align=1-8</td><td>1.76µs ± 6%</td><td>0.30µs ± 3%</td><td>1.69µs ± 4%</td>
-<tr><td>CRC32/poly=IEEE/size=32kB/align=0-8</td><td>15.0µs ± 7%</td><td>2.2µs ± 3%</td>
-<tr><td>CRC32/poly=IEEE/size=32kB/align=1-8</td><td>14.2µs ± 7%</td><td>2.2µs ± 3%</td>
-<tr><td>CRC32/poly=Castagnoli/size=15/align=0-8</td><td>16.4ns ± 3%</td><td>16.3ns ± 2%</td>
-<tr><td>CRC32/poly=Castagnoli/size=15/align=1-8</td><td>17.2ns ± 2%</td><td>17.3ns ± 2%</td>
+<tr><td>CRC32/poly=IEEE/size=32kB/align=0-8</td><td>15.0µs ± 7%</td><td>2.2µs ± 3%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=32kB/align=1-8</td><td>14.2µs ± 7%</td><td>2.2µs ± 3%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=15/align=0-8</td><td>16.4ns ± 3%</td><td>16.3ns ± 2%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=15/align=1-8</td><td>17.2ns ± 2%</td><td>17.3ns ± 2%</td><td></td>
 <tr><td>CRC32/poly=Castagnoli/size=40/align=0-8</td><td>17.4ns ± 2%</td><td>17.5ns ± 4%</td><td>18.6ns ±11%</td>
 <tr><td>CRC32/poly=Castagnoli/size=40/align=1-8</td><td>19.7ns ± 3%</td><td>19.4ns ± 2%</td><td>19.6ns ± 2%</td>
-<tr><td>CRC32/poly=Castagnoli/size=512/align=0-8</td><td>40.2ns ± 2%</td><td>40.1ns ± 4%</td>
-<tr><td>CRC32/poly=Castagnoli/size=512/align=1-8</td><td>42.1ns ± 3%</td><td>41.9ns ± 2%</td>
-<tr><td>CRC32/poly=Castagnoli/size=1kB/align=0-8</td><td>65.5ns ± 1%</td><td>66.2ns ± 1%</td>
-<tr><td>CRC32/poly=Castagnoli/size=1kB/align=1-8</td><td>70.1ns ± 6%</td><td>68.5ns ± 2%</td>
+<tr><td>CRC32/poly=Castagnoli/size=512/align=0-8</td><td>40.2ns ± 2%</td><td>40.1ns ± 4%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=512/align=1-8</td><td>42.1ns ± 3%</td><td>41.9ns ± 2%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=1kB/align=0-8</td><td>65.5ns ± 1%</td><td>66.2ns ± 1%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=1kB/align=1-8</td><td>70.1ns ± 6%</td><td>68.5ns ± 2%</td><td></td>
 <tr><td>CRC32/poly=Castagnoli/size=4kB/align=0-8</td><td>163ns ± 5%</td><td>159ns ± 3%</td><td>161ns ± 8%</td>
 <tr><td>CRC32/poly=Castagnoli/size=4kB/align=1-8</td><td>169ns ± 6%</td><td>162ns ± 3%</td><td>170ns ± 8%</td>
-<tr><td>CRC32/poly=Castagnoli/size=32kB/align=0-8</td><td>1.22µs ± 4%</td><td>1.21µs ± 3%</td>
-<tr><td>CRC32/poly=Castagnoli/size=32kB/align=1-8</td><td>1.26µs ± 3%</td><td>1.22µs ± 4%</td>
-<tr><td>CRC32/poly=Koopman/size=15/align=0-8</td><td>36.5ns ±11%</td><td>35.6ns ± 3%</td>
-<tr><td>CRC32/poly=Koopman/size=15/align=1-8</td><td>35.1ns ± 5%</td><td>35.5ns ± 1%</td>
+<tr><td>CRC32/poly=Castagnoli/size=32kB/align=0-8</td><td>1.22µs ± 4%</td><td>1.21µs ± 3%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=32kB/align=1-8</td><td>1.26µs ± 3%</td><td>1.22µs ± 4%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=15/align=0-8</td><td>36.5ns ±11%</td><td>35.6ns ± 3%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=15/align=1-8</td><td>35.1ns ± 5%</td><td>35.5ns ± 1%</td><td></td>
 <tr><td>CRC32/poly=Koopman/size=40/align=0-8</td><td>91.6ns ± 9%</td><td>87.6ns ± 2%</td><td>93.8ns ±13%</td>
 <tr><td>CRC32/poly=Koopman/size=40/align=1-8</td><td>91.1ns ± 6%</td><td>88.0ns ± 3%</td><td>86.9ns ± 3%</td>
-<tr><td>CRC32/poly=Koopman/size=512/align=0-8</td><td>1.13µs ± 5%</td><td>1.08µs ± 3%</td>
-<tr><td>CRC32/poly=Koopman/size=512/align=1-8</td><td>1.13µs ± 6%</td><td>1.17µs ± 8%</td>
-<tr><td>CRC32/poly=Koopman/size=1kB/align=0-8</td><td>2.24µs ± 6%</td><td>2.34µs ± 4%</td>
-<tr><td>CRC32/poly=Koopman/size=1kB/align=1-8</td><td>2.15µs ± 2%</td><td>2.36µs ± 5%</td>
+<tr><td>CRC32/poly=Koopman/size=512/align=0-8</td><td>1.13µs ± 5%</td><td>1.08µs ± 3%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=512/align=1-8</td><td>1.13µs ± 6%</td><td>1.17µs ± 8%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=1kB/align=0-8</td><td>2.24µs ± 6%</td><td>2.34µs ± 4%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=1kB/align=1-8</td><td>2.15µs ± 2%</td><td>2.36µs ± 5%</td><td></td>
 <tr><td>CRC32/poly=Koopman/size=4kB/align=0-8</td><td>9.03µs ± 6%</td><td>9.00µs ± 6%</td><td>9.08µs ± 8%</td>
 <tr><td>CRC32/poly=Koopman/size=4kB/align=1-8</td><td>8.94µs ±10%</td><td>9.05µs ±12%</td><td>9.46µs ± 8%</td>
-<tr><td>CRC32/poly=Koopman/size=32kB/align=0-8</td><td>72.4µs ± 9%</td><td>72.9µs ± 4%</td>
-<tr><td>CRC32/poly=Koopman/size=32kB/align=1-8</td><td>69.6µs ± 3%</td><td>74.3µs ± 3%</td>
+<tr><td>CRC32/poly=Koopman/size=32kB/align=0-8</td><td>72.4µs ± 9%</td><td>72.9µs ± 4%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=32kB/align=1-8</td><td>69.6µs ± 3%</td><td>74.3µs ± 3%</td><td></td>
 </table>
 
 <style>.benchstat tbody td:nth-child(1n+2) { text-align: right; padding: 0em 1em; }</style>
 <table class='benchstat'>
 <tr><th>name \ speed</th><th>old.txt</th><th>new.txt</th><th>slashslash4.txt</th>
-<tr><td>CRC32/poly=IEEE/size=15/align=0-8</td><td>321MB/s ± 8%</td><td>337MB/s ± 3%</td>
-<tr><td>CRC32/poly=IEEE/size=15/align=1-8</td><td>336MB/s ± 4%</td><td>337MB/s ± 4%</td>
+<tr><td>CRC32/poly=IEEE/size=15/align=0-8</td><td>321MB/s ± 8%</td><td>337MB/s ± 3%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=15/align=1-8</td><td>336MB/s ± 4%</td><td>337MB/s ± 4%</td><td></td>
 <tr><td>CRC32/poly=IEEE/size=40/align=0-8</td><td>975MB/s ± 1%</td><td>942MB/s ± 5%</td><td>951MB/s ± 3%</td>
 <tr><td>CRC32/poly=IEEE/size=40/align=1-8</td><td>974MB/s ± 1%</td><td>952MB/s ± 3%</td><td>960MB/s ± 4%</td>
-<tr><td>CRC32/poly=IEEE/size=512/align=0-8</td><td>2.15GB/s ± 4%</td><td>8.97GB/s ± 3%</td>
-<tr><td>CRC32/poly=IEEE/size=512/align=1-8</td><td>2.17GB/s ± 3%</td><td>8.96GB/s ± 3%</td>
-<tr><td>CRC32/poly=IEEE/size=1kB/align=0-8</td><td>2.26GB/s ± 4%</td><td>10.88GB/s ± 2%</td>
-<tr><td>CRC32/poly=IEEE/size=1kB/align=1-8</td><td>2.31GB/s ± 2%</td><td>10.98GB/s ± 2%</td>
+<tr><td>CRC32/poly=IEEE/size=512/align=0-8</td><td>2.15GB/s ± 4%</td><td>8.97GB/s ± 3%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=512/align=1-8</td><td>2.17GB/s ± 3%</td><td>8.96GB/s ± 3%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=1kB/align=0-8</td><td>2.26GB/s ± 4%</td><td>10.88GB/s ± 2%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=1kB/align=1-8</td><td>2.31GB/s ± 2%</td><td>10.98GB/s ± 2%</td><td></td>
 <tr><td>CRC32/poly=IEEE/size=4kB/align=0-8</td><td>2.36GB/s ± 7%</td><td>13.73GB/s ± 1%</td><td>2.43GB/s ± 2%</td>
 <tr><td>CRC32/poly=IEEE/size=4kB/align=1-8</td><td>2.33GB/s ± 6%</td><td>13.68GB/s ± 3%</td><td>2.42GB/s ± 4%</td>
-<tr><td>CRC32/poly=IEEE/size=32kB/align=0-8</td><td>2.19GB/s ± 7%</td><td>15.19GB/s ± 3%</td>
-<tr><td>CRC32/poly=IEEE/size=32kB/align=1-8</td><td>2.31GB/s ± 8%</td><td>15.04GB/s ± 3%</td>
-<tr><td>CRC32/poly=Castagnoli/size=15/align=0-8</td><td>916MB/s ± 2%</td><td>920MB/s ± 2%</td>
-<tr><td>CRC32/poly=Castagnoli/size=15/align=1-8</td><td>870MB/s ± 2%</td><td>867MB/s ± 2%</td>
+<tr><td>CRC32/poly=IEEE/size=32kB/align=0-8</td><td>2.19GB/s ± 7%</td><td>15.19GB/s ± 3%</td><td></td>
+<tr><td>CRC32/poly=IEEE/size=32kB/align=1-8</td><td>2.31GB/s ± 8%</td><td>15.04GB/s ± 3%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=15/align=0-8</td><td>916MB/s ± 2%</td><td>920MB/s ± 2%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=15/align=1-8</td><td>870MB/s ± 2%</td><td>867MB/s ± 2%</td><td></td>
 <tr><td>CRC32/poly=Castagnoli/size=40/align=0-8</td><td>2.30GB/s ± 2%</td><td>2.28GB/s ± 4%</td><td>2.16GB/s ±11%</td>
 <tr><td>CRC32/poly=Castagnoli/size=40/align=1-8</td><td>2.03GB/s ± 3%</td><td>2.06GB/s ± 2%</td><td>2.04GB/s ± 2%</td>
-<tr><td>CRC32/poly=Castagnoli/size=512/align=0-8</td><td>12.7GB/s ± 2%</td><td>12.8GB/s ± 4%</td>
-<tr><td>CRC32/poly=Castagnoli/size=512/align=1-8</td><td>12.1GB/s ± 3%</td><td>12.2GB/s ± 1%</td>
-<tr><td>CRC32/poly=Castagnoli/size=1kB/align=0-8</td><td>15.6GB/s ± 1%</td><td>15.5GB/s ± 1%</td>
-<tr><td>CRC32/poly=Castagnoli/size=1kB/align=1-8</td><td>14.6GB/s ± 6%</td><td>15.0GB/s ± 2%</td>
+<tr><td>CRC32/poly=Castagnoli/size=512/align=0-8</td><td>12.7GB/s ± 2%</td><td>12.8GB/s ± 4%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=512/align=1-8</td><td>12.1GB/s ± 3%</td><td>12.2GB/s ± 1%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=1kB/align=0-8</td><td>15.6GB/s ± 1%</td><td>15.5GB/s ± 1%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=1kB/align=1-8</td><td>14.6GB/s ± 6%</td><td>15.0GB/s ± 2%</td><td></td>
 <tr><td>CRC32/poly=Castagnoli/size=4kB/align=0-8</td><td>25.1GB/s ± 5%</td><td>25.7GB/s ± 3%</td><td>25.4GB/s ± 7%</td>
 <tr><td>CRC32/poly=Castagnoli/size=4kB/align=1-8</td><td>24.1GB/s ± 6%</td><td>25.3GB/s ± 3%</td><td>24.1GB/s ± 8%</td>
-<tr><td>CRC32/poly=Castagnoli/size=32kB/align=0-8</td><td>26.9GB/s ± 4%</td><td>26.8GB/s ± 5%</td>
-<tr><td>CRC32/poly=Castagnoli/size=32kB/align=1-8</td><td>25.9GB/s ± 3%</td><td>26.8GB/s ± 4%</td>
-<tr><td>CRC32/poly=Koopman/size=15/align=0-8</td><td>412MB/s ±10%</td><td>421MB/s ± 3%</td>
-<tr><td>CRC32/poly=Koopman/size=15/align=1-8</td><td>427MB/s ± 5%</td><td>422MB/s ± 1%</td>
+<tr><td>CRC32/poly=Castagnoli/size=32kB/align=0-8</td><td>26.9GB/s ± 4%</td><td>26.8GB/s ± 5%</td><td></td>
+<tr><td>CRC32/poly=Castagnoli/size=32kB/align=1-8</td><td>25.9GB/s ± 3%</td><td>26.8GB/s ± 4%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=15/align=0-8</td><td>412MB/s ±10%</td><td>421MB/s ± 3%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=15/align=1-8</td><td>427MB/s ± 5%</td><td>422MB/s ± 1%</td><td></td>
 <tr><td>CRC32/poly=Koopman/size=40/align=0-8</td><td>437MB/s ± 9%</td><td>456MB/s ± 2%</td><td>428MB/s ±12%</td>
 <tr><td>CRC32/poly=Koopman/size=40/align=1-8</td><td>440MB/s ± 6%</td><td>455MB/s ± 3%</td><td>461MB/s ± 3%</td>
-<tr><td>CRC32/poly=Koopman/size=512/align=0-8</td><td>453MB/s ± 5%</td><td>476MB/s ± 3%</td>
-<tr><td>CRC32/poly=Koopman/size=512/align=1-8</td><td>455MB/s ± 6%</td><td>440MB/s ± 8%</td>
-<tr><td>CRC32/poly=Koopman/size=1kB/align=0-8</td><td>452MB/s ± 9%</td><td>438MB/s ± 4%</td>
-<tr><td>CRC32/poly=Koopman/size=1kB/align=1-8</td><td>477MB/s ± 2%</td><td>434MB/s ± 5%</td>
+<tr><td>CRC32/poly=Koopman/size=512/align=0-8</td><td>453MB/s ± 5%</td><td>476MB/s ± 3%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=512/align=1-8</td><td>455MB/s ± 6%</td><td>440MB/s ± 8%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=1kB/align=0-8</td><td>452MB/s ± 9%</td><td>438MB/s ± 4%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=1kB/align=1-8</td><td>477MB/s ± 2%</td><td>434MB/s ± 5%</td><td></td>
 <tr><td>CRC32/poly=Koopman/size=4kB/align=0-8</td><td>454MB/s ± 5%</td><td>455MB/s ± 6%</td><td>452MB/s ± 8%</td>
 <tr><td>CRC32/poly=Koopman/size=4kB/align=1-8</td><td>459MB/s ± 9%</td><td>455MB/s ±11%</td><td>434MB/s ± 9%</td>
-<tr><td>CRC32/poly=Koopman/size=32kB/align=0-8</td><td>453MB/s ± 8%</td><td>450MB/s ± 4%</td>
-<tr><td>CRC32/poly=Koopman/size=32kB/align=1-8</td><td>471MB/s ± 3%</td><td>441MB/s ± 3%</td>
+<tr><td>CRC32/poly=Koopman/size=32kB/align=0-8</td><td>453MB/s ± 8%</td><td>450MB/s ± 4%</td><td></td>
+<tr><td>CRC32/poly=Koopman/size=32kB/align=1-8</td><td>471MB/s ± 3%</td><td>441MB/s ± 3%</td><td></td>
 </table>
diff --git a/cmd/benchstat/testdata/oldnewhtml.golden b/cmd/benchstat/testdata/oldnewhtml.golden
index c4f39ba..2037c69 100644
--- a/cmd/benchstat/testdata/oldnewhtml.golden
+++ b/cmd/benchstat/testdata/oldnewhtml.golden
@@ -1,81 +1,81 @@
 <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>CRC32/poly=IEEE/size=15/align=0-8</td><td>46.9ns ± 8%</td><td>44.5ns ± 3%</td><td>-5.01%</td><td>(p=0.008 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=15/align=1-8</td><td>44.7ns ± 5%</td><td>44.5ns ± 4%</td><td>~   </td><td>(p=0.539 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=40/align=0-8</td><td>41.0ns ± 1%</td><td>42.5ns ± 6%</td><td>+3.56%</td><td>(p=0.000 n=8+10)</td>
-<tr><td>CRC32/poly=IEEE/size=40/align=1-8</td><td>41.1ns ± 1%</td><td>42.0ns ± 3%</td><td>+2.34%</td><td>(p=0.000 n=9+10)</td>
-<tr><td>CRC32/poly=IEEE/size=512/align=0-8</td><td>238ns ± 5%</td><td>57ns ± 3%</td><td>-76.00%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=512/align=1-8</td><td>236ns ± 3%</td><td>57ns ± 3%</td><td>-75.72%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=1kB/align=0-8</td><td>452ns ± 4%</td><td>94ns ± 2%</td><td>-79.20%</td><td>(p=0.000 n=10+8)</td>
-<tr><td>CRC32/poly=IEEE/size=1kB/align=1-8</td><td>444ns ± 2%</td><td>93ns ± 2%</td><td>-78.97%</td><td>(p=0.000 n=10+8)</td>
-<tr><td>CRC32/poly=IEEE/size=4kB/align=0-8</td><td>1.74µs ± 8%</td><td>0.30µs ± 1%</td><td>-82.87%</td><td>(p=0.000 n=10+9)</td>
-<tr><td>CRC32/poly=IEEE/size=4kB/align=1-8</td><td>1.76µs ± 6%</td><td>0.30µs ± 3%</td><td>-83.05%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=32kB/align=0-8</td><td>15.0µs ± 7%</td><td>2.2µs ± 3%</td><td>-85.57%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=32kB/align=1-8</td><td>14.2µs ± 7%</td><td>2.2µs ± 3%</td><td>-84.65%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=15/align=0-8</td><td>16.4ns ± 3%</td><td>16.3ns ± 2%</td><td>~   </td><td>(p=0.615 n=9+9)</td>
-<tr><td>CRC32/poly=Castagnoli/size=15/align=1-8</td><td>17.2ns ± 2%</td><td>17.3ns ± 2%</td><td>~   </td><td>(p=0.650 n=9+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=40/align=0-8</td><td>17.4ns ± 2%</td><td>17.5ns ± 4%</td><td>~   </td><td>(p=0.694 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=40/align=1-8</td><td>19.7ns ± 3%</td><td>19.4ns ± 2%</td><td>-1.62%</td><td>(p=0.036 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=512/align=0-8</td><td>40.2ns ± 2%</td><td>40.1ns ± 4%</td><td>~   </td><td>(p=0.614 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=512/align=1-8</td><td>42.1ns ± 3%</td><td>41.9ns ± 2%</td><td>~   </td><td>(p=0.952 n=10+9)</td>
-<tr><td>CRC32/poly=Castagnoli/size=1kB/align=0-8</td><td>65.5ns ± 1%</td><td>66.2ns ± 1%</td><td>+1.01%</td><td>(p=0.003 n=9+8)</td>
-<tr><td>CRC32/poly=Castagnoli/size=1kB/align=1-8</td><td>70.1ns ± 6%</td><td>68.5ns ± 2%</td><td>~   </td><td>(p=0.190 n=10+9)</td>
-<tr><td>CRC32/poly=Castagnoli/size=4kB/align=0-8</td><td>163ns ± 5%</td><td>159ns ± 3%</td><td>-2.46%</td><td>(p=0.032 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=4kB/align=1-8</td><td>169ns ± 6%</td><td>162ns ± 3%</td><td>-4.60%</td><td>(p=0.005 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=32kB/align=0-8</td><td>1.22µs ± 4%</td><td>1.21µs ± 3%</td><td>~   </td><td>(p=0.882 n=9+9)</td>
-<tr><td>CRC32/poly=Castagnoli/size=32kB/align=1-8</td><td>1.26µs ± 3%</td><td>1.22µs ± 4%</td><td>-3.48%</td><td>(p=0.002 n=9+10)</td>
-<tr><td>CRC32/poly=Koopman/size=15/align=0-8</td><td>36.5ns ±11%</td><td>35.6ns ± 3%</td><td>~   </td><td>(p=0.216 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=15/align=1-8</td><td>35.1ns ± 5%</td><td>35.5ns ± 1%</td><td>~   </td><td>(p=0.508 n=10+9)</td>
-<tr><td>CRC32/poly=Koopman/size=40/align=0-8</td><td>91.6ns ± 9%</td><td>87.6ns ± 2%</td><td>-4.35%</td><td>(p=0.002 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=40/align=1-8</td><td>91.1ns ± 6%</td><td>88.0ns ± 3%</td><td>~   </td><td>(p=0.055 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=512/align=0-8</td><td>1.13µs ± 5%</td><td>1.08µs ± 3%</td><td>-4.93%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=512/align=1-8</td><td>1.13µs ± 6%</td><td>1.17µs ± 8%</td><td>~   </td><td>(p=0.143 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=1kB/align=0-8</td><td>2.24µs ± 6%</td><td>2.34µs ± 4%</td><td>+4.34%</td><td>(p=0.010 n=9+10)</td>
-<tr><td>CRC32/poly=Koopman/size=1kB/align=1-8</td><td>2.15µs ± 2%</td><td>2.36µs ± 5%</td><td>+9.84%</td><td>(p=0.000 n=9+10)</td>
-<tr><td>CRC32/poly=Koopman/size=4kB/align=0-8</td><td>9.03µs ± 6%</td><td>9.00µs ± 6%</td><td>~   </td><td>(p=0.971 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=4kB/align=1-8</td><td>8.94µs ±10%</td><td>9.05µs ±12%</td><td>~   </td><td>(p=0.754 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=32kB/align=0-8</td><td>72.4µs ± 9%</td><td>72.9µs ± 4%</td><td>~   </td><td>(p=0.684 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=32kB/align=1-8</td><td>69.6µs ± 3%</td><td>74.3µs ± 3%</td><td>+6.70%</td><td>(p=0.000 n=8+10)</td>
+<tr><td>CRC32/poly=IEEE/size=15/align=0-8</td><td>46.9ns ± 8%</td><td>44.5ns ± 3%</td><td>-5.01%</td><td>(p=0.008 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=15/align=1-8</td><td>44.7ns ± 5%</td><td>44.5ns ± 4%</td><td>~</td><td>(p=0.539 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=40/align=0-8</td><td>41.0ns ± 1%</td><td>42.5ns ± 6%</td><td>&#43;3.56%</td><td>(p=0.000 n=8&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=40/align=1-8</td><td>41.1ns ± 1%</td><td>42.0ns ± 3%</td><td>&#43;2.34%</td><td>(p=0.000 n=9&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=512/align=0-8</td><td>238ns ± 5%</td><td>57ns ± 3%</td><td>-76.00%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=512/align=1-8</td><td>236ns ± 3%</td><td>57ns ± 3%</td><td>-75.72%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=1kB/align=0-8</td><td>452ns ± 4%</td><td>94ns ± 2%</td><td>-79.20%</td><td>(p=0.000 n=10&#43;8)</td>
+<tr><td>CRC32/poly=IEEE/size=1kB/align=1-8</td><td>444ns ± 2%</td><td>93ns ± 2%</td><td>-78.97%</td><td>(p=0.000 n=10&#43;8)</td>
+<tr><td>CRC32/poly=IEEE/size=4kB/align=0-8</td><td>1.74µs ± 8%</td><td>0.30µs ± 1%</td><td>-82.87%</td><td>(p=0.000 n=10&#43;9)</td>
+<tr><td>CRC32/poly=IEEE/size=4kB/align=1-8</td><td>1.76µs ± 6%</td><td>0.30µs ± 3%</td><td>-83.05%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=32kB/align=0-8</td><td>15.0µs ± 7%</td><td>2.2µs ± 3%</td><td>-85.57%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=32kB/align=1-8</td><td>14.2µs ± 7%</td><td>2.2µs ± 3%</td><td>-84.65%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=15/align=0-8</td><td>16.4ns ± 3%</td><td>16.3ns ± 2%</td><td>~</td><td>(p=0.615 n=9&#43;9)</td>
+<tr><td>CRC32/poly=Castagnoli/size=15/align=1-8</td><td>17.2ns ± 2%</td><td>17.3ns ± 2%</td><td>~</td><td>(p=0.650 n=9&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=40/align=0-8</td><td>17.4ns ± 2%</td><td>17.5ns ± 4%</td><td>~</td><td>(p=0.694 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=40/align=1-8</td><td>19.7ns ± 3%</td><td>19.4ns ± 2%</td><td>-1.62%</td><td>(p=0.036 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=512/align=0-8</td><td>40.2ns ± 2%</td><td>40.1ns ± 4%</td><td>~</td><td>(p=0.614 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=512/align=1-8</td><td>42.1ns ± 3%</td><td>41.9ns ± 2%</td><td>~</td><td>(p=0.952 n=10&#43;9)</td>
+<tr><td>CRC32/poly=Castagnoli/size=1kB/align=0-8</td><td>65.5ns ± 1%</td><td>66.2ns ± 1%</td><td>&#43;1.01%</td><td>(p=0.003 n=9&#43;8)</td>
+<tr><td>CRC32/poly=Castagnoli/size=1kB/align=1-8</td><td>70.1ns ± 6%</td><td>68.5ns ± 2%</td><td>~</td><td>(p=0.190 n=10&#43;9)</td>
+<tr><td>CRC32/poly=Castagnoli/size=4kB/align=0-8</td><td>163ns ± 5%</td><td>159ns ± 3%</td><td>-2.46%</td><td>(p=0.032 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=4kB/align=1-8</td><td>169ns ± 6%</td><td>162ns ± 3%</td><td>-4.60%</td><td>(p=0.005 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=32kB/align=0-8</td><td>1.22µs ± 4%</td><td>1.21µs ± 3%</td><td>~</td><td>(p=0.882 n=9&#43;9)</td>
+<tr><td>CRC32/poly=Castagnoli/size=32kB/align=1-8</td><td>1.26µs ± 3%</td><td>1.22µs ± 4%</td><td>-3.48%</td><td>(p=0.002 n=9&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=15/align=0-8</td><td>36.5ns ±11%</td><td>35.6ns ± 3%</td><td>~</td><td>(p=0.216 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=15/align=1-8</td><td>35.1ns ± 5%</td><td>35.5ns ± 1%</td><td>~</td><td>(p=0.508 n=10&#43;9)</td>
+<tr><td>CRC32/poly=Koopman/size=40/align=0-8</td><td>91.6ns ± 9%</td><td>87.6ns ± 2%</td><td>-4.35%</td><td>(p=0.002 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=40/align=1-8</td><td>91.1ns ± 6%</td><td>88.0ns ± 3%</td><td>~</td><td>(p=0.055 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=512/align=0-8</td><td>1.13µs ± 5%</td><td>1.08µs ± 3%</td><td>-4.93%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=512/align=1-8</td><td>1.13µs ± 6%</td><td>1.17µs ± 8%</td><td>~</td><td>(p=0.143 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=1kB/align=0-8</td><td>2.24µs ± 6%</td><td>2.34µs ± 4%</td><td>&#43;4.34%</td><td>(p=0.010 n=9&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=1kB/align=1-8</td><td>2.15µs ± 2%</td><td>2.36µs ± 5%</td><td>&#43;9.84%</td><td>(p=0.000 n=9&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=4kB/align=0-8</td><td>9.03µs ± 6%</td><td>9.00µs ± 6%</td><td>~</td><td>(p=0.971 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=4kB/align=1-8</td><td>8.94µs ±10%</td><td>9.05µs ±12%</td><td>~</td><td>(p=0.754 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=32kB/align=0-8</td><td>72.4µs ± 9%</td><td>72.9µs ± 4%</td><td>~</td><td>(p=0.684 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=32kB/align=1-8</td><td>69.6µs ± 3%</td><td>74.3µs ± 3%</td><td>&#43;6.70%</td><td>(p=0.000 n=8&#43;10)</td>
 </table>
 
 <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>CRC32/poly=IEEE/size=15/align=0-8</td><td>321MB/s ± 8%</td><td>337MB/s ± 3%</td><td>+5.06%</td><td>(p=0.009 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=15/align=1-8</td><td>336MB/s ± 4%</td><td>337MB/s ± 4%</td><td>~   </td><td>(p=0.579 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=40/align=0-8</td><td>975MB/s ± 1%</td><td>942MB/s ± 5%</td><td>-3.37%</td><td>(p=0.001 n=8+10)</td>
-<tr><td>CRC32/poly=IEEE/size=40/align=1-8</td><td>974MB/s ± 1%</td><td>952MB/s ± 3%</td><td>-2.25%</td><td>(p=0.000 n=9+10)</td>
-<tr><td>CRC32/poly=IEEE/size=512/align=0-8</td><td>2.15GB/s ± 4%</td><td>8.97GB/s ± 3%</td><td>+317.65%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=512/align=1-8</td><td>2.17GB/s ± 3%</td><td>8.96GB/s ± 3%</td><td>+312.89%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=1kB/align=0-8</td><td>2.26GB/s ± 4%</td><td>10.88GB/s ± 2%</td><td>+381.12%</td><td>(p=0.000 n=10+8)</td>
-<tr><td>CRC32/poly=IEEE/size=1kB/align=1-8</td><td>2.31GB/s ± 2%</td><td>10.98GB/s ± 2%</td><td>+375.97%</td><td>(p=0.000 n=10+8)</td>
-<tr><td>CRC32/poly=IEEE/size=4kB/align=0-8</td><td>2.36GB/s ± 7%</td><td>13.73GB/s ± 1%</td><td>+482.26%</td><td>(p=0.000 n=10+9)</td>
-<tr><td>CRC32/poly=IEEE/size=4kB/align=1-8</td><td>2.33GB/s ± 6%</td><td>13.68GB/s ± 3%</td><td>+488.23%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=32kB/align=0-8</td><td>2.19GB/s ± 7%</td><td>15.19GB/s ± 3%</td><td>+591.99%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=IEEE/size=32kB/align=1-8</td><td>2.31GB/s ± 8%</td><td>15.04GB/s ± 3%</td><td>+550.07%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=15/align=0-8</td><td>916MB/s ± 2%</td><td>920MB/s ± 2%</td><td>~   </td><td>(p=0.489 n=9+9)</td>
-<tr><td>CRC32/poly=Castagnoli/size=15/align=1-8</td><td>870MB/s ± 2%</td><td>867MB/s ± 2%</td><td>~   </td><td>(p=0.661 n=9+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=40/align=0-8</td><td>2.30GB/s ± 2%</td><td>2.28GB/s ± 4%</td><td>~   </td><td>(p=0.684 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=40/align=1-8</td><td>2.03GB/s ± 3%</td><td>2.06GB/s ± 2%</td><td>~   </td><td>(p=0.063 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=512/align=0-8</td><td>12.7GB/s ± 2%</td><td>12.8GB/s ± 4%</td><td>~   </td><td>(p=0.529 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=512/align=1-8</td><td>12.1GB/s ± 3%</td><td>12.2GB/s ± 1%</td><td>~   </td><td>(p=0.780 n=10+9)</td>
-<tr><td>CRC32/poly=Castagnoli/size=1kB/align=0-8</td><td>15.6GB/s ± 1%</td><td>15.5GB/s ± 1%</td><td>-1.02%</td><td>(p=0.002 n=9+8)</td>
-<tr><td>CRC32/poly=Castagnoli/size=1kB/align=1-8</td><td>14.6GB/s ± 6%</td><td>15.0GB/s ± 2%</td><td>~   </td><td>(p=0.211 n=10+9)</td>
-<tr><td>CRC32/poly=Castagnoli/size=4kB/align=0-8</td><td>25.1GB/s ± 5%</td><td>25.7GB/s ± 3%</td><td>~   </td><td>(p=0.052 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=4kB/align=1-8</td><td>24.1GB/s ± 6%</td><td>25.3GB/s ± 3%</td><td>+4.71%</td><td>(p=0.005 n=10+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=32kB/align=0-8</td><td>26.9GB/s ± 4%</td><td>26.8GB/s ± 5%</td><td>~   </td><td>(p=0.842 n=9+10)</td>
-<tr><td>CRC32/poly=Castagnoli/size=32kB/align=1-8</td><td>25.9GB/s ± 3%</td><td>26.8GB/s ± 4%</td><td>+3.62%</td><td>(p=0.002 n=9+10)</td>
-<tr><td>CRC32/poly=Koopman/size=15/align=0-8</td><td>412MB/s ±10%</td><td>421MB/s ± 3%</td><td>~   </td><td>(p=0.218 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=15/align=1-8</td><td>427MB/s ± 5%</td><td>422MB/s ± 1%</td><td>~   </td><td>(p=0.497 n=10+9)</td>
-<tr><td>CRC32/poly=Koopman/size=40/align=0-8</td><td>437MB/s ± 9%</td><td>456MB/s ± 2%</td><td>+4.50%</td><td>(p=0.002 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=40/align=1-8</td><td>440MB/s ± 6%</td><td>455MB/s ± 3%</td><td>~   </td><td>(p=0.052 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=512/align=0-8</td><td>453MB/s ± 5%</td><td>476MB/s ± 3%</td><td>+5.09%</td><td>(p=0.000 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=512/align=1-8</td><td>455MB/s ± 6%</td><td>440MB/s ± 8%</td><td>~   </td><td>(p=0.143 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=1kB/align=0-8</td><td>452MB/s ± 9%</td><td>438MB/s ± 4%</td><td>~   </td><td>(p=0.052 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=1kB/align=1-8</td><td>477MB/s ± 2%</td><td>434MB/s ± 5%</td><td>-8.92%</td><td>(p=0.000 n=9+10)</td>
-<tr><td>CRC32/poly=Koopman/size=4kB/align=0-8</td><td>454MB/s ± 5%</td><td>455MB/s ± 6%</td><td>~   </td><td>(p=0.971 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=4kB/align=1-8</td><td>459MB/s ± 9%</td><td>455MB/s ±11%</td><td>~   </td><td>(p=0.739 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=32kB/align=0-8</td><td>453MB/s ± 8%</td><td>450MB/s ± 4%</td><td>~   </td><td>(p=0.684 n=10+10)</td>
-<tr><td>CRC32/poly=Koopman/size=32kB/align=1-8</td><td>471MB/s ± 3%</td><td>441MB/s ± 3%</td><td>-6.25%</td><td>(p=0.000 n=8+10)</td>
+<tr><td>CRC32/poly=IEEE/size=15/align=0-8</td><td>321MB/s ± 8%</td><td>337MB/s ± 3%</td><td>&#43;5.06%</td><td>(p=0.009 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=15/align=1-8</td><td>336MB/s ± 4%</td><td>337MB/s ± 4%</td><td>~</td><td>(p=0.579 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=40/align=0-8</td><td>975MB/s ± 1%</td><td>942MB/s ± 5%</td><td>-3.37%</td><td>(p=0.001 n=8&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=40/align=1-8</td><td>974MB/s ± 1%</td><td>952MB/s ± 3%</td><td>-2.25%</td><td>(p=0.000 n=9&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=512/align=0-8</td><td>2.15GB/s ± 4%</td><td>8.97GB/s ± 3%</td><td>&#43;317.65%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=512/align=1-8</td><td>2.17GB/s ± 3%</td><td>8.96GB/s ± 3%</td><td>&#43;312.89%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=1kB/align=0-8</td><td>2.26GB/s ± 4%</td><td>10.88GB/s ± 2%</td><td>&#43;381.12%</td><td>(p=0.000 n=10&#43;8)</td>
+<tr><td>CRC32/poly=IEEE/size=1kB/align=1-8</td><td>2.31GB/s ± 2%</td><td>10.98GB/s ± 2%</td><td>&#43;375.97%</td><td>(p=0.000 n=10&#43;8)</td>
+<tr><td>CRC32/poly=IEEE/size=4kB/align=0-8</td><td>2.36GB/s ± 7%</td><td>13.73GB/s ± 1%</td><td>&#43;482.26%</td><td>(p=0.000 n=10&#43;9)</td>
+<tr><td>CRC32/poly=IEEE/size=4kB/align=1-8</td><td>2.33GB/s ± 6%</td><td>13.68GB/s ± 3%</td><td>&#43;488.23%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=32kB/align=0-8</td><td>2.19GB/s ± 7%</td><td>15.19GB/s ± 3%</td><td>&#43;591.99%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=IEEE/size=32kB/align=1-8</td><td>2.31GB/s ± 8%</td><td>15.04GB/s ± 3%</td><td>&#43;550.07%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=15/align=0-8</td><td>916MB/s ± 2%</td><td>920MB/s ± 2%</td><td>~</td><td>(p=0.489 n=9&#43;9)</td>
+<tr><td>CRC32/poly=Castagnoli/size=15/align=1-8</td><td>870MB/s ± 2%</td><td>867MB/s ± 2%</td><td>~</td><td>(p=0.661 n=9&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=40/align=0-8</td><td>2.30GB/s ± 2%</td><td>2.28GB/s ± 4%</td><td>~</td><td>(p=0.684 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=40/align=1-8</td><td>2.03GB/s ± 3%</td><td>2.06GB/s ± 2%</td><td>~</td><td>(p=0.063 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=512/align=0-8</td><td>12.7GB/s ± 2%</td><td>12.8GB/s ± 4%</td><td>~</td><td>(p=0.529 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=512/align=1-8</td><td>12.1GB/s ± 3%</td><td>12.2GB/s ± 1%</td><td>~</td><td>(p=0.780 n=10&#43;9)</td>
+<tr><td>CRC32/poly=Castagnoli/size=1kB/align=0-8</td><td>15.6GB/s ± 1%</td><td>15.5GB/s ± 1%</td><td>-1.02%</td><td>(p=0.002 n=9&#43;8)</td>
+<tr><td>CRC32/poly=Castagnoli/size=1kB/align=1-8</td><td>14.6GB/s ± 6%</td><td>15.0GB/s ± 2%</td><td>~</td><td>(p=0.211 n=10&#43;9)</td>
+<tr><td>CRC32/poly=Castagnoli/size=4kB/align=0-8</td><td>25.1GB/s ± 5%</td><td>25.7GB/s ± 3%</td><td>~</td><td>(p=0.052 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=4kB/align=1-8</td><td>24.1GB/s ± 6%</td><td>25.3GB/s ± 3%</td><td>&#43;4.71%</td><td>(p=0.005 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=32kB/align=0-8</td><td>26.9GB/s ± 4%</td><td>26.8GB/s ± 5%</td><td>~</td><td>(p=0.842 n=9&#43;10)</td>
+<tr><td>CRC32/poly=Castagnoli/size=32kB/align=1-8</td><td>25.9GB/s ± 3%</td><td>26.8GB/s ± 4%</td><td>&#43;3.62%</td><td>(p=0.002 n=9&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=15/align=0-8</td><td>412MB/s ±10%</td><td>421MB/s ± 3%</td><td>~</td><td>(p=0.218 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=15/align=1-8</td><td>427MB/s ± 5%</td><td>422MB/s ± 1%</td><td>~</td><td>(p=0.497 n=10&#43;9)</td>
+<tr><td>CRC32/poly=Koopman/size=40/align=0-8</td><td>437MB/s ± 9%</td><td>456MB/s ± 2%</td><td>&#43;4.50%</td><td>(p=0.002 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=40/align=1-8</td><td>440MB/s ± 6%</td><td>455MB/s ± 3%</td><td>~</td><td>(p=0.052 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=512/align=0-8</td><td>453MB/s ± 5%</td><td>476MB/s ± 3%</td><td>&#43;5.09%</td><td>(p=0.000 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=512/align=1-8</td><td>455MB/s ± 6%</td><td>440MB/s ± 8%</td><td>~</td><td>(p=0.143 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=1kB/align=0-8</td><td>452MB/s ± 9%</td><td>438MB/s ± 4%</td><td>~</td><td>(p=0.052 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=1kB/align=1-8</td><td>477MB/s ± 2%</td><td>434MB/s ± 5%</td><td>-8.92%</td><td>(p=0.000 n=9&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=4kB/align=0-8</td><td>454MB/s ± 5%</td><td>455MB/s ± 6%</td><td>~</td><td>(p=0.971 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=4kB/align=1-8</td><td>459MB/s ± 9%</td><td>455MB/s ±11%</td><td>~</td><td>(p=0.739 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=32kB/align=0-8</td><td>453MB/s ± 8%</td><td>450MB/s ± 4%</td><td>~</td><td>(p=0.684 n=10&#43;10)</td>
+<tr><td>CRC32/poly=Koopman/size=32kB/align=1-8</td><td>471MB/s ± 3%</td><td>441MB/s ± 3%</td><td>-6.25%</td><td>(p=0.000 n=8&#43;10)</td>
 </table>