Commit d2aa5f95 authored by Marcel van Lohuizen's avatar Marcel van Lohuizen

compress/flate: simplify using subtests and sub-benchmarks

This causes the large files to be loaded only once per benchmark.

This CL also serves as an example use case of sub(tests|-benchmarks).

This CL ensures that names are identical to the original
except for an added slashes. Things could be
simplified further if this restriction were dropped.

Change-Id: I45e303e158e3152e33d0d751adfef784713bf997
Reviewed-on: https://go-review.googlesource.com/23420Reviewed-by: default avatarRuss Cox <rsc@golang.org>
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: default avatarJoe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 89283781
...@@ -22,31 +22,21 @@ func TestNlitOutOfRange(t *testing.T) { ...@@ -22,31 +22,21 @@ func TestNlitOutOfRange(t *testing.T) {
"\x75\xc4\xf8\x0f\x12\x11\xb9\xb4\x4b\x09\xa0\xbe\x8b\x91\x4c"))) "\x75\xc4\xf8\x0f\x12\x11\xb9\xb4\x4b\x09\xa0\xbe\x8b\x91\x4c")))
} }
const ( var suites = []struct{ name, file string }{
digits = iota
twain
)
var testfiles = []string{
// Digits is the digits of the irrational number e. Its decimal representation // Digits is the digits of the irrational number e. Its decimal representation
// does not repeat, but there are only 10 possible digits, so it should be // does not repeat, but there are only 10 possible digits, so it should be
// reasonably compressible. // reasonably compressible.
digits: "../testdata/e.txt", {"Digits", "../testdata/e.txt"},
// Twain is Mark Twain's classic English novel. // Twain is Mark Twain's classic English novel.
twain: "../testdata/Mark.Twain-Tom.Sawyer.txt", {"Twain", "../testdata/Mark.Twain-Tom.Sawyer.txt"},
} }
func benchmarkDecode(b *testing.B, testfile, level, n int) { func BenchmarkDecode(b *testing.B) {
doBench(b, func(b *testing.B, buf0 []byte, level, n int) {
b.ReportAllocs() b.ReportAllocs()
b.StopTimer() b.StopTimer()
b.SetBytes(int64(n)) b.SetBytes(int64(n))
buf0, err := ioutil.ReadFile(testfiles[testfile])
if err != nil {
b.Fatal(err)
}
if len(buf0) == 0 {
b.Fatalf("test file %q has no data", testfiles[testfile])
}
compressed := new(bytes.Buffer) compressed := new(bytes.Buffer)
w, err := NewWriter(compressed, level) w, err := NewWriter(compressed, level)
if err != nil { if err != nil {
...@@ -66,38 +56,43 @@ func benchmarkDecode(b *testing.B, testfile, level, n int) { ...@@ -66,38 +56,43 @@ func benchmarkDecode(b *testing.B, testfile, level, n int) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1))) io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1)))
} }
})
} }
// These short names are so that gofmt doesn't break the BenchmarkXxx function var levelTests = []struct {
// bodies below over multiple lines. name string
const ( level int
speed = BestSpeed }{
default_ = DefaultCompression {"Huffman", HuffmanOnly},
compress = BestCompression {"Speed", BestSpeed},
huffman = HuffmanOnly {"Default", DefaultCompression},
) {"Compression", BestCompression},
}
func BenchmarkDecodeDigitsHuffman1e4(b *testing.B) { benchmarkDecode(b, digits, huffman, 1e4) } var sizes = []struct {
func BenchmarkDecodeDigitsHuffman1e5(b *testing.B) { benchmarkDecode(b, digits, huffman, 1e5) } name string
func BenchmarkDecodeDigitsHuffman1e6(b *testing.B) { benchmarkDecode(b, digits, huffman, 1e6) } n int
func BenchmarkDecodeDigitsSpeed1e4(b *testing.B) { benchmarkDecode(b, digits, speed, 1e4) } }{
func BenchmarkDecodeDigitsSpeed1e5(b *testing.B) { benchmarkDecode(b, digits, speed, 1e5) } {"1e4", 1e4},
func BenchmarkDecodeDigitsSpeed1e6(b *testing.B) { benchmarkDecode(b, digits, speed, 1e6) } {"1e5", 1e5},
func BenchmarkDecodeDigitsDefault1e4(b *testing.B) { benchmarkDecode(b, digits, default_, 1e4) } {"1e6", 1e6},
func BenchmarkDecodeDigitsDefault1e5(b *testing.B) { benchmarkDecode(b, digits, default_, 1e5) } }
func BenchmarkDecodeDigitsDefault1e6(b *testing.B) { benchmarkDecode(b, digits, default_, 1e6) }
func BenchmarkDecodeDigitsCompress1e4(b *testing.B) { benchmarkDecode(b, digits, compress, 1e4) } func doBench(b *testing.B, f func(b *testing.B, buf []byte, level, n int)) {
func BenchmarkDecodeDigitsCompress1e5(b *testing.B) { benchmarkDecode(b, digits, compress, 1e5) } for _, suite := range suites {
func BenchmarkDecodeDigitsCompress1e6(b *testing.B) { benchmarkDecode(b, digits, compress, 1e6) } buf, err := ioutil.ReadFile(suite.file)
func BenchmarkDecodeTwainHuffman1e4(b *testing.B) { benchmarkDecode(b, twain, huffman, 1e4) } if err != nil {
func BenchmarkDecodeTwainHuffman1e5(b *testing.B) { benchmarkDecode(b, twain, huffman, 1e5) } b.Fatal(err)
func BenchmarkDecodeTwainHuffman1e6(b *testing.B) { benchmarkDecode(b, twain, huffman, 1e6) } }
func BenchmarkDecodeTwainSpeed1e4(b *testing.B) { benchmarkDecode(b, twain, speed, 1e4) } if len(buf) == 0 {
func BenchmarkDecodeTwainSpeed1e5(b *testing.B) { benchmarkDecode(b, twain, speed, 1e5) } b.Fatalf("test file %q has no data", suite.file)
func BenchmarkDecodeTwainSpeed1e6(b *testing.B) { benchmarkDecode(b, twain, speed, 1e6) } }
func BenchmarkDecodeTwainDefault1e4(b *testing.B) { benchmarkDecode(b, twain, default_, 1e4) } for _, l := range levelTests {
func BenchmarkDecodeTwainDefault1e5(b *testing.B) { benchmarkDecode(b, twain, default_, 1e5) } for _, s := range sizes {
func BenchmarkDecodeTwainDefault1e6(b *testing.B) { benchmarkDecode(b, twain, default_, 1e6) } b.Run(suite.name+"/"+l.name+"/"+s.name, func(b *testing.B) {
func BenchmarkDecodeTwainCompress1e4(b *testing.B) { benchmarkDecode(b, twain, compress, 1e4) } f(b, buf, l.level, s.n)
func BenchmarkDecodeTwainCompress1e5(b *testing.B) { benchmarkDecode(b, twain, compress, 1e5) } })
func BenchmarkDecodeTwainCompress1e6(b *testing.B) { benchmarkDecode(b, twain, compress, 1e6) } }
}
}
}
...@@ -14,16 +14,11 @@ import ( ...@@ -14,16 +14,11 @@ import (
"testing" "testing"
) )
func benchmarkEncoder(b *testing.B, testfile, level, n int) { func BenchmarkEncode(b *testing.B) {
doBench(b, func(b *testing.B, buf0 []byte, level, n int) {
b.StopTimer() b.StopTimer()
b.SetBytes(int64(n)) b.SetBytes(int64(n))
buf0, err := ioutil.ReadFile(testfiles[testfile])
if err != nil {
b.Fatal(err)
}
if len(buf0) == 0 {
b.Fatalf("test file %q has no data", testfiles[testfile])
}
buf1 := make([]byte, n) buf1 := make([]byte, n)
for i := 0; i < n; i += len(buf0) { for i := 0; i < n; i += len(buf0) {
if len(buf0) > n-i { if len(buf0) > n-i {
...@@ -43,33 +38,9 @@ func benchmarkEncoder(b *testing.B, testfile, level, n int) { ...@@ -43,33 +38,9 @@ func benchmarkEncoder(b *testing.B, testfile, level, n int) {
w.Write(buf1) w.Write(buf1)
w.Close() w.Close()
} }
})
} }
func BenchmarkEncodeDigitsHuffman1e4(b *testing.B) { benchmarkEncoder(b, digits, huffman, 1e4) }
func BenchmarkEncodeDigitsHuffman1e5(b *testing.B) { benchmarkEncoder(b, digits, huffman, 1e5) }
func BenchmarkEncodeDigitsHuffman1e6(b *testing.B) { benchmarkEncoder(b, digits, huffman, 1e6) }
func BenchmarkEncodeDigitsSpeed1e4(b *testing.B) { benchmarkEncoder(b, digits, speed, 1e4) }
func BenchmarkEncodeDigitsSpeed1e5(b *testing.B) { benchmarkEncoder(b, digits, speed, 1e5) }
func BenchmarkEncodeDigitsSpeed1e6(b *testing.B) { benchmarkEncoder(b, digits, speed, 1e6) }
func BenchmarkEncodeDigitsDefault1e4(b *testing.B) { benchmarkEncoder(b, digits, default_, 1e4) }
func BenchmarkEncodeDigitsDefault1e5(b *testing.B) { benchmarkEncoder(b, digits, default_, 1e5) }
func BenchmarkEncodeDigitsDefault1e6(b *testing.B) { benchmarkEncoder(b, digits, default_, 1e6) }
func BenchmarkEncodeDigitsCompress1e4(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e4) }
func BenchmarkEncodeDigitsCompress1e5(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e5) }
func BenchmarkEncodeDigitsCompress1e6(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e6) }
func BenchmarkEncodeTwainHuffman1e4(b *testing.B) { benchmarkEncoder(b, twain, huffman, 1e4) }
func BenchmarkEncodeTwainHuffman1e5(b *testing.B) { benchmarkEncoder(b, twain, huffman, 1e5) }
func BenchmarkEncodeTwainHuffman1e6(b *testing.B) { benchmarkEncoder(b, twain, huffman, 1e6) }
func BenchmarkEncodeTwainSpeed1e4(b *testing.B) { benchmarkEncoder(b, twain, speed, 1e4) }
func BenchmarkEncodeTwainSpeed1e5(b *testing.B) { benchmarkEncoder(b, twain, speed, 1e5) }
func BenchmarkEncodeTwainSpeed1e6(b *testing.B) { benchmarkEncoder(b, twain, speed, 1e6) }
func BenchmarkEncodeTwainDefault1e4(b *testing.B) { benchmarkEncoder(b, twain, default_, 1e4) }
func BenchmarkEncodeTwainDefault1e5(b *testing.B) { benchmarkEncoder(b, twain, default_, 1e5) }
func BenchmarkEncodeTwainDefault1e6(b *testing.B) { benchmarkEncoder(b, twain, default_, 1e6) }
func BenchmarkEncodeTwainCompress1e4(b *testing.B) { benchmarkEncoder(b, twain, compress, 1e4) }
func BenchmarkEncodeTwainCompress1e5(b *testing.B) { benchmarkEncoder(b, twain, compress, 1e5) }
func BenchmarkEncodeTwainCompress1e6(b *testing.B) { benchmarkEncoder(b, twain, compress, 1e6) }
// errorWriter is a writer that fails after N writes. // errorWriter is a writer that fails after N writes.
type errorWriter struct { type errorWriter struct {
N int N int
...@@ -141,17 +112,12 @@ func TestWriteError(t *testing.T) { ...@@ -141,17 +112,12 @@ func TestWriteError(t *testing.T) {
// Test if two runs produce identical results // Test if two runs produce identical results
// even when writing different sizes to the Writer. // even when writing different sizes to the Writer.
func TestDeterministicL0(t *testing.T) { testDeterministic(0, t) } func TestDeterministic(t *testing.T) {
func TestDeterministicL1(t *testing.T) { testDeterministic(1, t) } for i := 0; i <= 9; i++ {
func TestDeterministicL2(t *testing.T) { testDeterministic(2, t) } t.Run(fmt.Sprint("L", i), func(t *testing.T) { testDeterministic(i, t) })
func TestDeterministicL3(t *testing.T) { testDeterministic(3, t) } }
func TestDeterministicL4(t *testing.T) { testDeterministic(4, t) } t.Run("LM2", func(t *testing.T) { testDeterministic(-2, t) })
func TestDeterministicL5(t *testing.T) { testDeterministic(5, t) } }
func TestDeterministicL6(t *testing.T) { testDeterministic(6, t) }
func TestDeterministicL7(t *testing.T) { testDeterministic(7, t) }
func TestDeterministicL8(t *testing.T) { testDeterministic(8, t) }
func TestDeterministicL9(t *testing.T) { testDeterministic(9, t) }
func TestDeterministicLM2(t *testing.T) { testDeterministic(-2, t) }
func testDeterministic(i int, t *testing.T) { func testDeterministic(i int, t *testing.T) {
// Test so much we cross a good number of block boundaries. // Test so much we cross a good number of block boundaries.
......
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