diff options
author | W. Felix Handte <w@felixhandte.com> | 2018-02-12 19:44:53 (GMT) |
---|---|---|
committer | W. Felix Handte <w@felixhandte.com> | 2018-03-12 18:58:43 (GMT) |
commit | 7060bcabf041395d6249a701729d02e28529bf82 (patch) | |
tree | 9d18d5ce26cc34aa895bc41dfca101ff29046f15 /lib | |
parent | b3628cb0c51bb93f681707b2d0cdbce5ccdae818 (diff) | |
download | lz4-7060bcabf041395d6249a701729d02e28529bf82.zip lz4-7060bcabf041395d6249a701729d02e28529bf82.tar.gz lz4-7060bcabf041395d6249a701729d02e28529bf82.tar.bz2 |
Only Re-Alloc / Reset When Needed When Switching Between Regular and High Compression Modes
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lz4frame.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/lib/lz4frame.c b/lib/lz4frame.c index bf70b5c..cd61925 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -188,7 +188,15 @@ typedef struct LZ4F_cctx_s U64 totalInSize; XXH32_state_t xxh; void* lz4CtxPtr; - U32 lz4CtxLevel; /* 0: unallocated; 1: LZ4_stream_t; 3: LZ4_streamHC_t */ + /* lz4CtxLevel records both what size of memory has been allocated into the + * ctx pointer field and what it's being used as. + * - The low bit (& 1) value indicates whether the ctx is being used for + * hc (1) or not (0). + * - The next bit (& 2) indicates whether the allocated memory is big + * enough for a non-hc context. + * - The next bit (& 4) indicates whether the allocated memory is big + * enough for an hc context. */ + U32 lz4CtxLevel; } LZ4F_cctx_t; @@ -356,7 +364,7 @@ size_t LZ4F_compressFrame_usingCDict(void* dstBuffer, size_t dstCapacity, if (prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { LZ4_resetStream(&lz4ctx); cctxI.lz4CtxPtr = &lz4ctx; - cctxI.lz4CtxLevel = 1; + cctxI.lz4CtxLevel = 2; } /* fast compression context pre-created on stack */ memset(&options, 0, sizeof(options)); @@ -513,21 +521,27 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, cctxPtr->prefs = *preferencesPtr; /* Ctx Management */ - { U32 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; /* 0:nothing ; 1:LZ4 table ; 2:HC tables */ - if (cctxPtr->lz4CtxLevel < ctxTypeID) { + { U32 const ctxSufficientAllocBits = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 2 : 6; + U32 const ctxTypeBit = cctxPtr->prefs.compressionLevel >= LZ4HC_CLEVEL_MIN; + if ((cctxPtr->lz4CtxLevel & ctxSufficientAllocBits) != ctxSufficientAllocBits) { FREEMEM(cctxPtr->lz4CtxPtr); - if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) + if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { cctxPtr->lz4CtxPtr = (void*)LZ4_createStream(); - else + } else { cctxPtr->lz4CtxPtr = (void*)LZ4_createStreamHC(); + } if (cctxPtr->lz4CtxPtr == NULL) return err0r(LZ4F_ERROR_allocation_failed); - cctxPtr->lz4CtxLevel = ctxTypeID; - } else if (cctxPtr->lz4CtxLevel != ctxTypeID) { - /* otherwise, we must be transitioning from HC -> LZ4. - * In that case, avoid reallocating, since a LZ4 ctx - * fits in an HC ctx. Just reset. */ - LZ4_resetStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr); - cctxPtr->lz4CtxLevel = ctxTypeID; + cctxPtr->lz4CtxLevel = ctxSufficientAllocBits | ctxTypeBit; + } else if ((cctxPtr->lz4CtxLevel & 1) != ctxTypeBit) { + /* otherwise, a sufficient buffer is allocated, but we need to + * reset it to the correct context type */ + if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { + LZ4_resetStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr); + cctxPtr->lz4CtxLevel &= ~1; + } else { + LZ4_resetStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel); + cctxPtr->lz4CtxLevel |= 1; + } } } |