fix snappy allocations and improve benchmarks

This commit is contained in:
Nicolás Pazos 2023-11-02 17:51:37 -03:00 committed by Callum Styan
parent 1ef02aad26
commit a727653618
2 changed files with 97 additions and 13 deletions

View file

@ -104,7 +104,7 @@ type snappyCompression struct {
func (s *snappyCompression) Compress(data []byte) ([]byte, error) { func (s *snappyCompression) Compress(data []byte) ([]byte, error) {
s.buf = s.buf[0:cap(s.buf)] s.buf = s.buf[0:cap(s.buf)]
compressed := snappy.Encode(s.buf, data) compressed := snappy.Encode(s.buf, data)
if n := snappy.MaxEncodedLen(len(data)); n > len(s.buf) { if n := snappy.MaxEncodedLen(len(data)); n > cap(s.buf) {
s.buf = make([]byte, n) s.buf = make([]byte, n)
} }
return compressed, nil return compressed, nil
@ -125,7 +125,7 @@ type snappyAltCompression struct {
func (s *snappyAltCompression) Compress(data []byte) ([]byte, error) { func (s *snappyAltCompression) Compress(data []byte) ([]byte, error) {
s.buf = s.buf[:0] s.buf = s.buf[:0]
res := reSnappy.Encode(s.buf, data) res := reSnappy.Encode(s.buf, data)
if n := reSnappy.MaxEncodedLen(len(data)); n > len(s.buf) { if n := reSnappy.MaxEncodedLen(len(data)); n > cap(s.buf) {
s.buf = make([]byte, n) s.buf = make([]byte, n)
} }
return res, nil return res, nil

View file

@ -1,6 +1,9 @@
package remote package remote
import "testing" import (
"testing"
"time"
)
func TestCompressions(t *testing.T) { func TestCompressions(t *testing.T) {
data := makeUncompressedReducedWriteRequestBenchData(t) data := makeUncompressedReducedWriteRequestBenchData(t)
@ -59,7 +62,7 @@ func BenchmarkCompressions(b *testing.B) {
{"FlateFast", FlateFast}, {"FlateFast", FlateFast},
{"FlateComp", FlateComp}, {"FlateComp", FlateComp},
{"BrotliFast", BrotliFast}, {"BrotliFast", BrotliFast},
{"BrotliComp", BrotliComp}, // {"BrotliComp", BrotliComp},
{"BrotliDefault", BrotliDefault}, {"BrotliDefault", BrotliDefault},
} }
comps := make(map[CompAlgorithm]Compression) comps := make(map[CompAlgorithm]Compression)
@ -71,7 +74,7 @@ func BenchmarkCompressions(b *testing.B) {
comps[c.algo] = comp comps[c.algo] = comp
decomps[c.algo] = decomp decomps[c.algo] = decomp
// warmup // warmup
for i := 0; i < 10; i++ { for i := 0; i < 2; i++ {
compressed, err := comp.Compress(data) compressed, err := comp.Compress(data)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
@ -84,30 +87,111 @@ func BenchmarkCompressions(b *testing.B) {
} }
for _, c := range bc { for _, c := range bc {
b.Run("compress-"+c.name, func(b *testing.B) { b.Run(c.name, func(b *testing.B) {
comp := comps[c.algo] comp := comps[c.algo]
b.ResetTimer() decomp := decomps[c.algo]
totalSize := 0
compTime := 0
decompTime := 0
rate := 0.0
var start time.Time
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, err := comp.Compress(data) start = time.Now()
res, err := comp.Compress(data)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
compTime += int(time.Since(start))
totalSize += len(res)
rate += float64(len(data)) / float64(len(res))
start = time.Now()
_, err = decomp.Decompress(res)
if err != nil {
b.Fatal(err)
}
decompTime += int(time.Since(start))
} }
b.ReportMetric(float64(totalSize)/float64(b.N), "compressedSize/op")
b.ReportMetric(float64(compTime)/float64(b.N), "nsCompress/op")
b.ReportMetric(float64(decompTime)/float64(b.N), "nsDecompress/op")
b.ReportMetric(rate/float64(b.N), "compressionX/op")
}) })
b.Run("decompress-"+c.name, func(b *testing.B) { }
comp := comps[c.algo] }
decomp := decomps[c.algo]
func BenchmarkCompressionsV1(b *testing.B) {
data := makeUncompressedWriteRequestBenchData(b)
bc := []struct {
name string
algo CompAlgorithm
}{
{"Snappy", Snappy},
{"SnappyAlt", SnappyAlt},
{"S2", S2},
{"ZstdFast", ZstdFast},
{"ZstdDefault", ZstdDefault},
{"ZstdBestComp", ZstdBestComp},
{"Lzw", Lzw},
{"FlateFast", FlateFast},
{"FlateComp", FlateComp},
{"BrotliFast", BrotliFast},
// {"BrotliComp", BrotliComp},
{"BrotliDefault", BrotliDefault},
}
comps := make(map[CompAlgorithm]Compression)
decomps := make(map[CompAlgorithm]Compression)
for _, c := range bc {
UseAlgorithm = c.algo
comp := createComp()
decomp := createComp()
comps[c.algo] = comp
decomps[c.algo] = decomp
// warmup
for i := 0; i < 2; i++ {
compressed, err := comp.Compress(data) compressed, err := comp.Compress(data)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.ResetTimer() _, err = decomp.Decompress(compressed)
if err != nil {
b.Fatal(err)
}
}
}
for _, c := range bc {
b.Run(c.name, func(b *testing.B) {
comp := comps[c.algo]
decomp := decomps[c.algo]
totalSize := 0
compTime := 0
decompTime := 0
rate := 0.0
var start time.Time
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, err = decomp.Decompress(compressed) start = time.Now()
res, err := comp.Compress(data)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
compTime += int(time.Since(start))
totalSize += len(res)
rate += float64(len(data)) / float64(len(res))
start = time.Now()
_, err = decomp.Decompress(res)
if err != nil {
b.Fatal(err)
}
decompTime += int(time.Since(start))
} }
b.ReportMetric(float64(totalSize)/float64(b.N), "compressedSize/op")
b.ReportMetric(float64(compTime)/float64(b.N), "nsCompress/op")
b.ReportMetric(float64(decompTime)/float64(b.N), "nsDecompress/op")
b.ReportMetric(rate/float64(b.N), "compressionX/op")
}) })
} }
} }