Add benchmarks for nocompressio.

PiperOrigin-RevId: 672596781
This commit is contained in:
Ayush Ranjan
2024-09-09 10:49:15 -07:00
committed by gVisor bot
parent 3c4b246cf2
commit 688187b7b1
2 changed files with 114 additions and 93 deletions
+86 -92
View File
@@ -22,6 +22,7 @@ import (
"io"
"math/rand"
"runtime"
"strings"
"testing"
"time"
)
@@ -49,30 +50,30 @@ func initTest(t harness, size int) []byte {
}
type testOpts struct {
Name string
Data []byte
NewWriter func(*bytes.Buffer) (io.Writer, error)
NewReader func(*bytes.Buffer) (io.Reader, error)
PreCompress func()
PostCompress func()
PreDecompress func()
PostDecompress func()
CompressIters int
DecompressIters int
CorruptData bool
Name string
Data []byte
NewWriter func(*bytes.Buffer) (io.WriteCloser, error)
NewReader func(*bytes.Buffer) (io.Reader, error)
PreWrite func()
PostWrite func()
PreRead func()
PostRead func()
WriteIters int
ReadIters int
CorruptData bool
}
func doTest(t harness, opts testOpts) {
// Compress.
var compressed bytes.Buffer
compressionStartTime := time.Now()
if opts.PreCompress != nil {
opts.PreCompress()
if opts.PreWrite != nil {
opts.PreWrite()
}
if opts.CompressIters <= 0 {
opts.CompressIters = 1
if opts.WriteIters <= 0 {
opts.WriteIters = 1
}
for i := 0; i < opts.CompressIters; i++ {
for i := 0; i < opts.WriteIters; i++ {
compressed.Reset()
w, err := opts.NewWriter(&compressed)
if err != nil {
@@ -82,16 +83,13 @@ func doTest(t harness, opts testOpts) {
t.Errorf("%s: compress got err %v, expected nil", opts.Name, err)
return
}
closer, ok := w.(io.Closer)
if ok {
if err := closer.Close(); err != nil {
t.Errorf("%s: got err %v, expected nil", opts.Name, err)
return
}
if err := w.Close(); err != nil {
t.Errorf("%s: got err %v, expected nil", opts.Name, err)
return
}
}
if opts.PostCompress != nil {
opts.PostCompress()
if opts.PostWrite != nil {
opts.PostWrite()
}
compressionTime := time.Since(compressionStartTime)
compressionRatio := float32(compressed.Len()) / float32(len(opts.Data))
@@ -104,17 +102,17 @@ func doTest(t harness, opts testOpts) {
// Decompress.
var decompressed bytes.Buffer
decompressionStartTime := time.Now()
if opts.PreDecompress != nil {
opts.PreDecompress()
if opts.PreRead != nil {
opts.PreRead()
}
if opts.DecompressIters <= 0 {
opts.DecompressIters = 1
if opts.ReadIters <= 0 {
opts.ReadIters = 1
}
if opts.CorruptData {
b := compressed.Bytes()
b[rand.Intn(len(b))]++
}
for i := 0; i < opts.DecompressIters; i++ {
for i := 0; i < opts.ReadIters; i++ {
decompressed.Reset()
r, err := opts.NewReader(bytes.NewBuffer(compressed.Bytes()))
if err != nil {
@@ -129,8 +127,8 @@ func doTest(t harness, opts testOpts) {
return
}
}
if opts.PostDecompress != nil {
opts.PostDecompress()
if opts.PostRead != nil {
opts.PostRead()
}
decompressionTime := time.Since(decompressionStartTime)
@@ -185,7 +183,7 @@ func TestCompress(t *testing.T) {
doTest(t, testOpts{
Name: fmt.Sprintf("len(data)=%d, blockSize=%d, key=%s, corruptData=%v", len(data), blockSize, string(key), corruptData),
Data: data,
NewWriter: func(b *bytes.Buffer) (io.Writer, error) {
NewWriter: func(b *bytes.Buffer) (io.WriteCloser, error) {
return NewWriter(b, key, blockSize, flate.BestSpeed)
},
NewReader: func(b *bytes.Buffer) (io.Reader, error) {
@@ -201,7 +199,7 @@ func TestCompress(t *testing.T) {
doTest(t, testOpts{
Name: fmt.Sprintf("len(data)=%d, vanilla flate", len(data)),
Data: data,
NewWriter: func(b *bytes.Buffer) (io.Writer, error) {
NewWriter: func(b *bytes.Buffer) (io.WriteCloser, error) {
return flate.NewWriter(b, flate.BestSpeed)
},
NewReader: func(b *bytes.Buffer) (io.Reader, error) {
@@ -215,7 +213,7 @@ const (
benchDataSize = 600 * 1024 * 1024
)
func benchmark(b *testing.B, compress bool, hash bool, blockSize uint32) {
func benchmark(b *testing.B, compression bool, write bool, hash bool, blockSize uint32) {
b.StopTimer()
b.SetBytes(benchDataSize)
data := initTest(b, benchDataSize)
@@ -224,71 +222,67 @@ func benchmark(b *testing.B, compress bool, hash bool, blockSize uint32) {
key = nil
}
opts := testOpts{
Name: fmt.Sprintf("compress=%t, hash=%t, len(data)=%d, blockSize=%d", compress, hash, len(data), blockSize),
Name: fmt.Sprintf("compression=%t, write=%t, hash=%t, len(data)=%d, blockSize=%d", compression, write, hash, len(data), blockSize),
Data: data,
NewWriter: func(b *bytes.Buffer) (io.Writer, error) {
return NewWriter(b, key, blockSize, flate.BestSpeed)
},
NewReader: func(b *bytes.Buffer) (io.Reader, error) {
return NewReader(b, key)
},
}
if compress {
opts.PreCompress = b.StartTimer
opts.PostCompress = b.StopTimer
opts.CompressIters = b.N
if compression {
opts.NewWriter = func(b *bytes.Buffer) (io.WriteCloser, error) {
return NewWriter(b, key, blockSize, flate.BestSpeed)
}
opts.NewReader = func(b *bytes.Buffer) (io.Reader, error) {
return NewReader(b, key)
}
} else {
opts.PreDecompress = b.StartTimer
opts.PostDecompress = b.StopTimer
opts.DecompressIters = b.N
opts.NewWriter = func(b *bytes.Buffer) (io.WriteCloser, error) {
return NewSimpleWriter(b, key), nil
}
opts.NewReader = func(b *bytes.Buffer) (io.Reader, error) {
return NewSimpleReader(b, key), nil
}
}
if write {
opts.PreWrite = b.StartTimer
opts.PostWrite = b.StopTimer
opts.WriteIters = b.N
} else {
opts.PreRead = b.StartTimer
opts.PostRead = b.StopTimer
opts.ReadIters = b.N
}
doTest(b, opts)
}
func BenchmarkCompressNoHash64K(b *testing.B) {
benchmark(b, true, false, 64*1024)
func benchmarkName(compression bool, write bool, hash bool, blockSize uint32) string {
var sb strings.Builder
if compression {
sb.WriteString("Compress")
} else {
sb.WriteString("NoCompress")
}
if write {
sb.WriteString("Write")
} else {
sb.WriteString("Read")
}
if hash {
sb.WriteString("Hash")
} else {
sb.WriteString("NoHash")
}
sb.WriteString(fmt.Sprintf("%dKbBlock", blockSize/1024))
return sb.String()
}
func BenchmarkCompressHash64K(b *testing.B) {
benchmark(b, true, true, 64*1024)
}
func BenchmarkDecompressNoHash64K(b *testing.B) {
benchmark(b, false, false, 64*1024)
}
func BenchmarkDecompressHash64K(b *testing.B) {
benchmark(b, false, true, 64*1024)
}
func BenchmarkCompressNoHash1M(b *testing.B) {
benchmark(b, true, false, 1024*1024)
}
func BenchmarkCompressHash1M(b *testing.B) {
benchmark(b, true, true, 1024*1024)
}
func BenchmarkDecompressNoHash1M(b *testing.B) {
benchmark(b, false, false, 1024*1024)
}
func BenchmarkDecompressHash1M(b *testing.B) {
benchmark(b, false, true, 1024*1024)
}
func BenchmarkCompressNoHash16M(b *testing.B) {
benchmark(b, true, false, 16*1024*1024)
}
func BenchmarkCompressHash16M(b *testing.B) {
benchmark(b, true, true, 16*1024*1024)
}
func BenchmarkDecompressNoHash16M(b *testing.B) {
benchmark(b, false, false, 16*1024*1024)
}
func BenchmarkDecompressHash16M(b *testing.B) {
benchmark(b, false, true, 16*1024*1024)
func BenchmarkLargeIO(b *testing.B) {
for _, compress := range []bool{false, true} {
for _, blockSize := range []uint32{64 * 1024, 1024 * 1024, 16 * 1024 * 1024} {
for _, hash := range []bool{false, true} {
for _, write := range []bool{false, true} {
b.Run(benchmarkName(compress, write, hash, blockSize), func(b *testing.B) {
benchmark(b, compress, write, hash, blockSize)
})
}
}
}
}
}
+28 -1
View File
@@ -53,7 +53,7 @@ func TestNoCompress(t *testing.T) {
doTest(t, testOpts{
Name: fmt.Sprintf("len(data)=%d, blockSize=%d, key=%s, corruptData=%v", len(data), blockSize, string(key), corruptData),
Data: data,
NewWriter: func(b *bytes.Buffer) (io.Writer, error) {
NewWriter: func(b *bytes.Buffer) (io.WriteCloser, error) {
return NewSimpleWriter(b, key), nil
},
NewReader: func(b *bytes.Buffer) (io.Reader, error) {
@@ -66,3 +66,30 @@ func TestNoCompress(t *testing.T) {
}
}
}
// The following benchmarks aims to be representative of how the wire
// package writes to the image. In practice, wire package only calls Write
// with a single byte at a time. Because all types boil down to wire.Uint
// whose implementation invokes Write with one byte at a time.
func BenchmarkTinyIO(b *testing.B) {
// Use the same chunk size as the statefile package.
const blockSize = 1024 * 1024
for _, key := range [][]byte{nil, hashKey} {
b.Run(benchmarkName(false, true, key != nil, blockSize), func(b *testing.B) {
benchmarkNoCompress1ByteWrite(b, key, blockSize)
})
}
}
func benchmarkNoCompress1ByteWrite(b *testing.B, key []byte, blockSize uint32) {
var (
buf [1]byte
out bytes.Buffer
)
w := NewSimpleWriter(&out, key)
for i := 0; i < b.N; i++ {
w.Write(buf[:])
}
w.Close()
}