From 97b5dc712255fad125f2f305f9fa58d9ff109fe5 Mon Sep 17 00:00:00 2001
From: Aliaksandr Valialkin <valyala@gmail.com>
Date: Wed, 24 Jul 2019 19:15:33 +0300
Subject: [PATCH] lib/encoding/zstd: disable CRC checks in `pure Go` build

This should give slightly better compression and decompressions performance.
Additionally this shaves off 4 bytes per each compressed block.
---
 lib/encoding/zstd/zstd_pure.go | 23 ++++++++++++++++-------
 lib/encoding/zstd/zstd_test.go |  4 +++-
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/lib/encoding/zstd/zstd_pure.go b/lib/encoding/zstd/zstd_pure.go
index c6359a6908..2ae2d66ced 100644
--- a/lib/encoding/zstd/zstd_pure.go
+++ b/lib/encoding/zstd/zstd_pure.go
@@ -45,17 +45,15 @@ func CompressLevel(dst, src []byte, compressionLevel int) []byte {
 
 func getEncoder(compressionLevel int) *zstd.Encoder {
 	r := av.Load().(registry)
-	if e, ok := r[compressionLevel]; ok {
+	e := r[compressionLevel]
+	if e != nil {
 		return e
 	}
 
-	level := zstd.EncoderLevelFromZstd(compressionLevel)
-	e, err := zstd.NewWriter(nil, zstd.WithEncoderLevel(level))
-	if err != nil {
-		logger.Panicf("BUG: failed to create ZSTD writer: %s", err)
-	}
-
 	mu.Lock()
+	// Create the encoder under lock in order to prevent from wasted work
+	// when concurrent goroutines create encoder for the same compressionLevel.
+	e = newEncoder(compressionLevel)
 	r1 := av.Load().(registry)
 	r2 := make(registry)
 	for k, v := range r1 {
@@ -67,3 +65,14 @@ func getEncoder(compressionLevel int) *zstd.Encoder {
 
 	return e
 }
+
+func newEncoder(compressionLevel int) *zstd.Encoder {
+	level := zstd.EncoderLevelFromZstd(compressionLevel)
+	e, err := zstd.NewWriter(nil,
+		zstd.WithEncoderCRC(false), // Disable CRC for performance reasons.
+		zstd.WithEncoderLevel(level))
+	if err != nil {
+		logger.Panicf("BUG: failed to create ZSTD writer: %s", err)
+	}
+	return e
+}
diff --git a/lib/encoding/zstd/zstd_test.go b/lib/encoding/zstd/zstd_test.go
index cc4c50ebba..d557ce451e 100644
--- a/lib/encoding/zstd/zstd_test.go
+++ b/lib/encoding/zstd/zstd_test.go
@@ -68,7 +68,9 @@ func testCompressDecompress(t *testing.T, compress compressFn, decompress decomp
 type compressFn func(dst, src []byte, compressionLevel int) ([]byte, error)
 
 func pureCompress(dst, src []byte, _ int) ([]byte, error) {
-	w, err := pure.NewWriter(nil, pure.WithEncoderLevel(pure.SpeedBestCompression))
+	w, err := pure.NewWriter(nil,
+		pure.WithEncoderCRC(false),  // Disable CRC for performance reasons.
+		pure.WithEncoderLevel(pure.SpeedBestCompression))
 	if err != nil {
 		return nil, err
 	}