Browse Source

lz4.Writer: allocate only if buffer too small. Fixes #52.

Pierre Curto 6 years ago
parent
commit
21241797f8
3 changed files with 31 additions and 11 deletions
  1. 24 6
      bench_test.go
  2. 1 1
      decode_other.go
  3. 6 4
      writer.go

+ 24 - 6
bench_test.go

@@ -17,7 +17,7 @@ func BenchmarkCompress(b *testing.B) {
 	b.ResetTimer()
 
 	for i := 0; i < b.N; i++ {
-		lz4.CompressBlock(pg1661, buf, hashTable[:])
+		_, _ = lz4.CompressBlock(pg1661, buf, hashTable[:])
 	}
 }
 
@@ -30,7 +30,7 @@ func BenchmarkCompressRandom(b *testing.B) {
 	b.ResetTimer()
 
 	for i := 0; i < b.N; i++ {
-		lz4.CompressBlock(random, buf, hashTable[:])
+		_, _ = lz4.CompressBlock(random, buf, hashTable[:])
 	}
 }
 
@@ -41,7 +41,7 @@ func BenchmarkCompressHC(b *testing.B) {
 	b.ResetTimer()
 
 	for i := 0; i < b.N; i++ {
-		lz4.CompressBlockHC(pg1661, buf, 16)
+		_, _ = lz4.CompressBlockHC(pg1661, buf, 16)
 	}
 }
 
@@ -52,7 +52,7 @@ func BenchmarkUncompress(b *testing.B) {
 	b.ResetTimer()
 
 	for i := 0; i < b.N; i++ {
-		lz4.UncompressBlock(pg1661LZ4, buf)
+		_, _ = lz4.UncompressBlock(pg1661LZ4, buf)
 	}
 }
 
@@ -92,7 +92,7 @@ func benchmarkUncompress(b *testing.B, compressed []byte) {
 	for i := 0; i < b.N; i++ {
 		r.Reset(compressed)
 		zr.Reset(r)
-		io.Copy(ioutil.Discard, zr)
+		_, _ = io.Copy(ioutil.Discard, zr)
 	}
 }
 
@@ -122,7 +122,7 @@ func benchmarkCompress(b *testing.B, uncompressed []byte) {
 	for i := 0; i < b.N; i++ {
 		r.Reset(uncompressed)
 		zw.Reset(w)
-		io.Copy(zw, r)
+		_, _ = io.Copy(zw, r)
 	}
 }
 
@@ -130,3 +130,21 @@ func BenchmarkCompressPg1661(b *testing.B) { benchmarkCompress(b, pg1661) }
 func BenchmarkCompressDigits(b *testing.B) { benchmarkCompress(b, digits) }
 func BenchmarkCompressTwain(b *testing.B)  { benchmarkCompress(b, twain) }
 func BenchmarkCompressRand(b *testing.B)   { benchmarkCompress(b, random) }
+
+// Benchmark to check reallocations upon Reset().
+// See issue https://github.com/pierrec/lz4/issues/52.
+func BenchmarkWriterReset(b *testing.B) {
+	b.ReportAllocs()
+
+	zw := lz4.NewWriter(nil)
+	src := mustLoadFile("testdata/gettysburg.txt")
+	var buf bytes.Buffer
+
+	for n := 0; n < b.N; n++ {
+		buf.Reset()
+		zw.Reset(&buf)
+
+		_, _ = zw.Write(src)
+		_ = zw.Close()
+	}
+}

+ 1 - 1
decode_other.go

@@ -35,7 +35,7 @@ func decodeBlock(dst, src []byte) (ret int) {
 					if offset := int(src[si]) | int(src[si+1])<<8; mLen <= offset {
 						i := di - offset
 						end := i + 18
-						if end >= len(dst) {
+						if end > len(dst) {
 							// The remaining buffer may not hold 18 bytes.
 							// See https://github.com/pierrec/lz4/issues/51.
 							end = len(dst)

+ 6 - 4
writer.go

@@ -46,11 +46,13 @@ func (z *Writer) writeHeader() error {
 	}
 	// Allocate the compressed/uncompressed buffers.
 	// The compressed buffer cannot exceed the uncompressed one.
-	if n := 2 * bSize; cap(z.zdata) < n {
-		z.zdata = make([]byte, n, n)
+	if cap(z.zdata) < bSize {
+		// Only allocate if there is not enough capacity.
+		// Allocate both buffers at once.
+		z.zdata = make([]byte, 2*bSize)
 	}
-	z.data = z.zdata[:bSize]
-	z.zdata = z.zdata[:cap(z.zdata)][bSize:]
+	z.data = z.zdata[:bSize]                 // Uncompressed buffer is the first half.
+	z.zdata = z.zdata[:cap(z.zdata)][bSize:] // Compressed buffer is the second half.
 	z.idx = 0
 
 	// Size is optional.