From 5406c2e479f5bb2b594a43e74e28719f4640450f Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 2 May 2018 23:29:07 -0400 Subject: [PATCH] Only Reset the LZ4 Stream when Init'ing a Streaming Block --- lib/lz4.h | 24 +++++++++++++++++++----- lib/lz4frame.c | 19 ++++++++++++++----- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/lz4.h b/lib/lz4.h index db6353c..d8238f5 100644 --- a/lib/lz4.h +++ b/lib/lz4.h @@ -358,6 +358,15 @@ LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int or #ifdef LZ4_STATIC_LINKING_ONLY /*! LZ4_resetStream_fast() : + * Use this, like LZ4_resetStream(), to prepare a context for a new chain of + * calls to a streaming API (e.g., LZ4_compress_fast_continue()). + * + * Note: + * Using this in advance of a non- streaming-compression function is redundant, + * and potentially bad for performance, since they all perform their own custom + * reset internally. + * + * Differences from LZ4_resetStream(): * When an LZ4_stream_t is known to be in a internally coherent state, * it can often be prepared for a new compression with almost no work, only * sometimes falling back to the full, expensive reset that is always required @@ -367,13 +376,17 @@ LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int or * LZ4_streams are guaranteed to be in a valid state when: * - returned from LZ4_createStream() * - reset by LZ4_resetStream() - * - memset(stream, 0, sizeof(LZ4_stream_t)) + * - memset(stream, 0, sizeof(LZ4_stream_t)), though this is discouraged * - the stream was in a valid state and was reset by LZ4_resetStream_fast() * - the stream was in a valid state and was then used in any compression call * that returned success * - the stream was in an indeterminate state and was used in a compression - * call that fully reset the state (LZ4_compress_fast_extState()) and that - * returned success + * call that fully reset the state (e.g., LZ4_compress_fast_extState()) and + * that returned success + * + * When a stream isn't known to be in a valid state, it is not safe to pass to + * any fastReset or streaming function. It must first be cleansed by the full + * LZ4_resetStream(). */ LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); @@ -384,8 +397,9 @@ LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); * to call if the state buffer is known to be correctly initialized already * (see above comment on LZ4_resetStream_fast() for a definition of "correctly * initialized"). From a high level, the difference is that this function - * initializes the provided state with a call to LZ4_resetStream_fast() while - * LZ4_compress_fast_extState() starts with a call to LZ4_resetStream(). + * initializes the provided state with a call to something like + * LZ4_resetStream_fast() while LZ4_compress_fast_extState() starts with a + * call to LZ4_resetStream(). */ LZ4LIB_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); diff --git a/lib/lz4frame.c b/lib/lz4frame.c index 6cf2a06..91e5a43 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -537,9 +537,18 @@ LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_comp */ static void LZ4F_initStream(void* ctx, const LZ4F_CDict* cdict, - int level) { + int level, + LZ4F_blockMode_t blockMode) { if (level < LZ4HC_CLEVEL_MIN) { - LZ4_resetStream_fast((LZ4_stream_t *)ctx); + if (cdict != NULL || blockMode == LZ4F_blockLinked) { + /* In these cases, we will call LZ4_compress_fast_continue(), + * which needs an already reset context. Otherwise, we'll call a + * one-shot API. The non-continued APIs internally perform their own + * resets at the beginning of their calls, where they know what + * tableType they need the context to be in. So in that case this + * would be misguided / wasted work. */ + LZ4_resetStream_fast((LZ4_stream_t*)ctx); + } LZ4_attach_dictionary((LZ4_stream_t *)ctx, cdict ? cdict->fastCtx : NULL); } else { LZ4_resetStreamHC_fast((LZ4_streamHC_t*)ctx, level); @@ -617,7 +626,7 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, cctxPtr->cdict = cdict; if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) { /* frame init only for blockLinked : blockIndependent will be init at each block */ - LZ4F_initStream(cctxPtr->lz4CtxPtr, cdict, cctxPtr->prefs.compressionLevel); + LZ4F_initStream(cctxPtr->lz4CtxPtr, cdict, cctxPtr->prefs.compressionLevel, LZ4F_blockLinked); } if (preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN) { LZ4_favorDecompressionSpeed((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, (int)preferencesPtr->favorDecSpeed); @@ -715,7 +724,7 @@ static size_t LZ4F_makeBlock(void* dst, const void* src, size_t srcSize, static int LZ4F_compressBlock(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict) { int const acceleration = (level < -1) ? -level : 1; - LZ4F_initStream(ctx, cdict, level); + LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent); if (cdict) { return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration); } else { @@ -732,7 +741,7 @@ static int LZ4F_compressBlock_continue(void* ctx, const char* src, char* dst, in static int LZ4F_compressBlockHC(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict) { - LZ4F_initStream(ctx, cdict, level); + LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent); if (cdict) { return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity); }