@@ -202,9 +202,8 @@ void CompileCacheHandler::ReadCacheFile(CompileCacheEntry* entry) {
202202 // and zstd-compressed when cache_size < raw_size (see
203203 // CompileCacheHandler::Persist()). Anything else is invalid.
204204 if (cache_size > raw_size) {
205- Debug (" invalid cache size %d > uncompressed size %d\n " ,
206- cache_size,
207- raw_size);
205+ Debug (
206+ " invalid cache size %d > uncompressed size %d\n " , cache_size, raw_size);
208207 return ;
209208 }
210209
@@ -260,13 +259,19 @@ void CompileCacheHandler::ReadCacheFile(CompileCacheEntry* entry) {
260259 content_size);
261260 return ;
262261 }
262+ // Lazily create the decompression context on first use and reuse it
263+ // for subsequent reads - recreating its workspace for every file
264+ // costs more than the decompression itself for small caches.
265+ if (zstd_dctx_ == nullptr && (zstd_dctx_ = ZSTD_createDCtx ()) == nullptr ) {
266+ Debug (" failed to create zstd context\n " );
267+ return ;
268+ }
263269 // Decompress directly into the buffer handed to V8.
264270 std::unique_ptr<uint8_t []> raw_data (new uint8_t [raw_size]);
265- size_t decompressed_size =
266- ZSTD_decompress ( raw_data.get (), raw_size, disk_data.get (), cache_size);
271+ size_t decompressed_size = ZSTD_decompressDCtx (
272+ zstd_dctx_, raw_data.get (), raw_size, disk_data.get (), cache_size);
267273 if (ZSTD_isError (decompressed_size)) {
268- Debug (" decompression failed: %s\n " ,
269- ZSTD_getErrorName (decompressed_size));
274+ Debug (" decompression failed: %s\n " , ZSTD_getErrorName (decompressed_size));
270275 return ;
271276 }
272277 if (decompressed_size != raw_size) {
@@ -276,9 +281,7 @@ void CompileCacheHandler::ReadCacheFile(CompileCacheEntry* entry) {
276281 return ;
277282 }
278283 entry->cache .reset (new ScriptCompiler::CachedData (
279- raw_data.release (),
280- raw_size,
281- ScriptCompiler::CachedData::BufferOwned));
284+ raw_data.release (), raw_size, ScriptCompiler::CachedData::BufferOwned));
282285 }
283286 Debug (" success, size=%d\n " , raw_size);
284287}
@@ -459,6 +462,16 @@ void CompileCacheHandler::Persist() {
459462 // finished. In that case, the off-thread writes should finish long
460463 // before any attempt of flushing is made so the method would then only
461464 // incur a negligible overhead from thread synchronization.
465+
466+ // The compression context is created lazily when there is anything to
467+ // compress and reused for all the entries in this invocation.
468+ ZSTD_CCtx* cctx = nullptr ;
469+ auto cleanup_cctx = OnScopeLeave ([&cctx]() {
470+ if (cctx != nullptr ) {
471+ ZSTD_freeCCtx (cctx);
472+ }
473+ });
474+
462475 for (auto & pair : compiler_cache_store_) {
463476 auto * entry = pair.second .get ();
464477 const char * type_name = entry->type_name ();
@@ -495,15 +508,18 @@ void CompileCacheHandler::Persist() {
495508 // shutdown and should add as little overhead as possible. If the data
496509 // is not compressible, store it uncompressed, which is indicated by
497510 // the cache size being equal to the uncompressed size in the headers.
498- size_t compressed_bound = ZSTD_compressBound (raw_size);
499- std::unique_ptr<uint8_t []> compressed (new uint8_t [compressed_bound]);
500- size_t compressed_size = ZSTD_compress (
501- compressed.get (), compressed_bound, raw_ptr, raw_size, 1 );
502511 char * cache_ptr = raw_ptr;
503512 uint32_t cache_size = raw_size;
504- if (!ZSTD_isError (compressed_size) && compressed_size < raw_size) {
505- cache_ptr = reinterpret_cast <char *>(compressed.get ());
506- cache_size = static_cast <uint32_t >(compressed_size);
513+ std::unique_ptr<uint8_t []> compressed;
514+ if (cctx != nullptr || (cctx = ZSTD_createCCtx ()) != nullptr ) {
515+ size_t compressed_bound = ZSTD_compressBound (raw_size);
516+ compressed.reset (new uint8_t [compressed_bound]);
517+ size_t compressed_size = ZSTD_compressCCtx (
518+ cctx, compressed.get (), compressed_bound, raw_ptr, raw_size, 1 );
519+ if (!ZSTD_isError (compressed_size) && compressed_size < raw_size) {
520+ cache_ptr = reinterpret_cast <char *>(compressed.get ());
521+ cache_size = static_cast <uint32_t >(compressed_size);
522+ }
507523 }
508524 Debug (" [compile cache] compressed cache for %s %s: %d -> %d bytes\n " ,
509525 type_name,
@@ -621,6 +637,12 @@ CompileCacheHandler::CompileCacheHandler(Environment* env)
621637 is_debug_(
622638 env->enabled_debug_list ()->enabled(DebugCategory::COMPILE_CACHE )) {}
623639
640+ CompileCacheHandler::~CompileCacheHandler () {
641+ if (zstd_dctx_ != nullptr ) {
642+ ZSTD_freeDCtx (zstd_dctx_);
643+ }
644+ }
645+
624646// Directory structure:
625647// - Compile cache directory (from NODE_COMPILE_CACHE)
626648// - $NODE_VERSION-$ARCH-$CACHE_DATA_VERSION_TAG-$UID
0 commit comments