Optimize zstd compression

reuse the same context for zstd compression. One context should be used
per compression thread for optimal performance. Discussion and
reccomendations can be found at go/android-hw-compression-vendor

Results (level 3 compression)
full ota on raven with optimizations:  1191.304 seconds
without optimizations:  1461.854 seconds

compression ratio remains unchanged and merge time difference are
negligible ~1% delta (probably just noise)

Test: ota_from_target_files, update_device.py
Change-Id: I3feede9f1f119874e369c54b29c594475fbf7376
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
index d023f19..466b93c 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
@@ -18,6 +18,7 @@
 #include <unistd.h>
 
 #include <limits>
+#include <memory>
 #include <queue>
 
 #include <android-base/file.h>
@@ -174,12 +175,18 @@
 
 class ZstdCompressor final : public ICompressor {
   public:
-    ZstdCompressor(uint32_t compression_level) : ICompressor(compression_level){};
+    ZstdCompressor(uint32_t compression_level)
+        : ICompressor(compression_level), zstd_context_(ZSTD_createCCtx(), ZSTD_freeCCtx) {
+        ZSTD_CCtx_setParameter(zstd_context_.get(), ZSTD_c_compressionLevel, compression_level);
+        // FIXME: hardcoding a value of 12 here for 4k blocks, should change to be either set by
+        // user, or optimized depending on block size
+        ZSTD_CCtx_setParameter(zstd_context_.get(), ZSTD_c_windowLog, 12);
+    };
 
     std::basic_string<uint8_t> Compress(const void* data, size_t length) const override {
         std::basic_string<uint8_t> buffer(ZSTD_compressBound(length), '\0');
         const auto compressed_size =
-                ZSTD_compress(buffer.data(), buffer.size(), data, length, GetCompressionLevel());
+                ZSTD_compress2(zstd_context_.get(), buffer.data(), buffer.size(), data, length);
         if (compressed_size <= 0) {
             LOG(ERROR) << "ZSTD compression failed " << compressed_size;
             return {};
@@ -193,6 +200,9 @@
         }
         return buffer;
     };
+
+  private:
+    std::unique_ptr<ZSTD_CCtx, decltype(&ZSTD_freeCCtx)> zstd_context_;
 };
 
 bool CompressWorker::CompressBlocks(const void* buffer, size_t num_blocks,