From 9dcd9abc14a33b6ac6c91dd727235db1daabe066 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 26 Jan 2018 11:29:00 -0500 Subject: Make LZ4F_compressFrame_usingCDict Take a Compression Context --- lib/lz4frame.c | 75 ++++++++++++++++++++++++++++++++++++--------------- lib/lz4frame_static.h | 2 ++ programs/lz4io.c | 2 +- tests/framebench.c | 2 ++ tests/frametest.c | 19 +++++++------ 5 files changed, 69 insertions(+), 31 deletions(-) diff --git a/lib/lz4frame.c b/lib/lz4frame.c index 9ff7766..e77fd35 100644 --- a/lib/lz4frame.c +++ b/lib/lz4frame.c @@ -47,6 +47,19 @@ You can contact the author at : /*-************************************ +* Tuning parameters +**************************************/ +/* + * LZ4_HEAPMODE : + * Select how default compression functions will allocate memory for their hash table, + * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). + */ +#ifndef LZ4_HEAPMODE +# define LZ4_HEAPMODE 0 +#endif + + +/*-************************************ * Memory routines **************************************/ #include /* malloc, calloc, free */ @@ -332,23 +345,18 @@ size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* prefere * @return : number of bytes written into dstBuffer, * or an error code if it fails (can be tested using LZ4F_isError()) */ -size_t LZ4F_compressFrame_usingCDict(void* dstBuffer, size_t dstCapacity, +size_t LZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx, + void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_CDict* cdict, const LZ4F_preferences_t* preferencesPtr) { - LZ4F_cctx_t cctxI; - LZ4_stream_t lz4ctx; /* pretty large on stack */ LZ4F_preferences_t prefs; LZ4F_compressOptions_t options; BYTE* const dstStart = (BYTE*) dstBuffer; BYTE* dstPtr = dstStart; BYTE* const dstEnd = dstStart + dstCapacity; - memset(&cctxI, 0, sizeof(cctxI)); - cctxI.version = LZ4F_VERSION; - cctxI.maxBufferSize = 5 MB; /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */ - if (preferencesPtr!=NULL) prefs = *preferencesPtr; else @@ -361,33 +369,24 @@ size_t LZ4F_compressFrame_usingCDict(void* dstBuffer, size_t dstCapacity, if (srcSize <= LZ4F_getBlockSize(prefs.frameInfo.blockSizeID)) prefs.frameInfo.blockMode = LZ4F_blockIndependent; /* only one block => no need for inter-block link */ - if (prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { - LZ4_resetStream(&lz4ctx); - cctxI.lz4CtxPtr = &lz4ctx; - cctxI.lz4CtxLevel = 2; - } /* fast compression context pre-created on stack */ - memset(&options, 0, sizeof(options)); options.stableSrc = 1; if (dstCapacity < LZ4F_compressFrameBound(srcSize, &prefs)) /* condition to guarantee success */ return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); - { size_t const headerSize = LZ4F_compressBegin_usingCDict(&cctxI, dstBuffer, dstCapacity, cdict, &prefs); /* write header */ + { size_t const headerSize = LZ4F_compressBegin_usingCDict(cctx, dstBuffer, dstCapacity, cdict, &prefs); /* write header */ if (LZ4F_isError(headerSize)) return headerSize; dstPtr += headerSize; /* header size */ } - { size_t const cSize = LZ4F_compressUpdate(&cctxI, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options); + { size_t const cSize = LZ4F_compressUpdate(cctx, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options); if (LZ4F_isError(cSize)) return cSize; dstPtr += cSize; } - { size_t const tailSize = LZ4F_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options); /* flush last block, and generate suffix */ + { size_t const tailSize = LZ4F_compressEnd(cctx, dstPtr, dstEnd-dstPtr, &options); /* flush last block, and generate suffix */ if (LZ4F_isError(tailSize)) return tailSize; dstPtr += tailSize; } - if (prefs.compressionLevel >= LZ4HC_CLEVEL_MIN) /* Ctx allocation only for lz4hc */ - FREEMEM(cctxI.lz4CtxPtr); - return (dstPtr - dstStart); } @@ -403,9 +402,41 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr) { - return LZ4F_compressFrame_usingCDict(dstBuffer, dstCapacity, - srcBuffer, srcSize, - NULL, preferencesPtr); + size_t result; +#if (LZ4_HEAPMODE) + LZ4F_cctx_t *cctxPtr; + LZ4F_createCompressionContext(&cctxPtr, LZ4F_VERSION); +#else + LZ4F_cctx_t cctx; + LZ4_stream_t lz4ctx; + LZ4F_cctx_t *cctxPtr = &cctx; + + MEM_INIT(&cctx, 0, sizeof(cctx)); + cctx.version = LZ4F_VERSION; + cctx.maxBufferSize = 5 MB; /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */ + if (preferencesPtr == NULL || + preferencesPtr->compressionLevel < LZ4HC_CLEVEL_MIN + ) { + LZ4_resetStream(&lz4ctx); + cctxPtr->lz4CtxPtr = &lz4ctx; + cctxPtr->lz4CtxLevel = 2; + } +#endif + + result = LZ4F_compressFrame_usingCDict(cctxPtr, dstBuffer, dstCapacity, + srcBuffer, srcSize, + NULL, preferencesPtr); + +#if (LZ4_HEAPMODE) + LZ4F_freeCompressionContext(cctxPtr); +#else + if (preferencesPtr != NULL && + preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN + ) { + FREEMEM(cctxPtr->lz4CtxPtr); + } +#endif + return result; } diff --git a/lib/lz4frame_static.h b/lib/lz4frame_static.h index a59b94b..be587e6 100644 --- a/lib/lz4frame_static.h +++ b/lib/lz4frame_static.h @@ -107,6 +107,7 @@ LZ4FLIB_STATIC_API void LZ4F_freeCDict(LZ4F_CDict* CDict); /*! LZ4_compressFrame_usingCDict() : * Compress an entire srcBuffer into a valid LZ4 frame using a digested Dictionary. + * cctx must point to a context created by LZ4F_createCompressionContext(). * If cdict==NULL, compress without a dictionary. * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). * If this condition is not respected, function will fail (@return an errorCode). @@ -115,6 +116,7 @@ LZ4FLIB_STATIC_API void LZ4F_freeCDict(LZ4F_CDict* CDict); * @return : number of bytes written into dstBuffer. * or an error code if it fails (can be tested using LZ4F_isError()) */ LZ4FLIB_STATIC_API size_t LZ4F_compressFrame_usingCDict( + LZ4F_cctx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const LZ4F_CDict* cdict, diff --git a/programs/lz4io.c b/programs/lz4io.c index c712fe1..ca13316 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -560,7 +560,7 @@ static int LZ4IO_compressFilename_extRess(cRess_t ress, const char* srcFileName, /* single-block file */ if (readSize < blockSize) { /* Compress in single pass */ - size_t cSize = LZ4F_compressFrame_usingCDict(dstBuffer, dstBufferSize, srcBuffer, readSize, ress.cdict, &prefs); + size_t cSize = LZ4F_compressFrame_usingCDict(ctx, dstBuffer, dstBufferSize, srcBuffer, readSize, ress.cdict, &prefs); if (LZ4F_isError(cSize)) EXM_THROW(31, "Compression failed : %s", LZ4F_getErrorName(cSize)); compressedfilesize = cSize; DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", diff --git a/tests/framebench.c b/tests/framebench.c index 21c3704..a7a270b 100644 --- a/tests/framebench.c +++ b/tests/framebench.c @@ -30,6 +30,7 @@ typedef struct { size_t compress_frame(bench_params_t *p) { size_t iter = p->iter; + LZ4F_cctx *cctx = p->cctx; char *obuf = p->obuf; size_t osize = p->osize; const char* ibuf = p->ibuf; @@ -43,6 +44,7 @@ size_t compress_frame(bench_params_t *p) { prefs->frameInfo.contentSize = isize; oused = LZ4F_compressFrame_usingCDict( + cctx, obuf, osize, ibuf + ((iter * 2654435761U) % num_ibuf) * isize, diff --git a/tests/frametest.c b/tests/frametest.c index 986a16d..74d9c88 100644 --- a/tests/frametest.c +++ b/tests/frametest.c @@ -164,7 +164,7 @@ static unsigned FUZ_highbit(U32 v32) /*-******************************************************* * Tests *********************************************************/ -#define CHECK_V(v,f) v = f; if (LZ4F_isError(v)) goto _output_error +#define CHECK_V(v,f) v = f; if (LZ4F_isError(v)) { fprintf(stderr, "%s\n", LZ4F_getErrorName(v)); goto _output_error; } #define CHECK(f) { LZ4F_errorCode_t const CHECK_V(err_ , f); } int basicTests(U32 seed, double compressibility) @@ -509,23 +509,25 @@ int basicTests(U32 seed, double compressibility) CHECK( LZ4F_freeCompressionContext(cctx) ); cctx = NULL; } - /* Dictionary compression test */ { size_t const dictSize = 63 KB; size_t const dstCapacity = LZ4F_compressFrameBound(dictSize, NULL); size_t cSizeNoDict, cSizeWithDict; LZ4F_CDict* const cdict = LZ4F_createCDict(CNBuffer, dictSize); if (cdict == NULL) goto _output_error; + CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) ); DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with NULL dict : "); CHECK_V(cSizeNoDict, - LZ4F_compressFrame_usingCDict(compressedBuffer, dstCapacity, + LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity, CNBuffer, dictSize, NULL, NULL) ); DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeNoDict); + CHECK( LZ4F_freeCompressionContext(cctx) ); + CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) ); DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict : "); CHECK_V(cSizeWithDict, - LZ4F_compressFrame_usingCDict(compressedBuffer, dstCapacity, + LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity, CNBuffer, dictSize, cdict, NULL) ); DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n", @@ -557,7 +559,7 @@ int basicTests(U32 seed, double compressibility) memset(&cParams, 0, sizeof(cParams)); cParams.compressionLevel = -3; CHECK_V(cSizeLevelMax, - LZ4F_compressFrame_usingCDict(compressedBuffer, dstCapacity, + LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity, CNBuffer, dictSize, cdict, &cParams) ); DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeLevelMax); @@ -569,7 +571,7 @@ int basicTests(U32 seed, double compressibility) memset(&cParams, 0, sizeof(cParams)); cParams.compressionLevel = LZ4F_compressionLevel_max(); CHECK_V(cSizeLevelMax, - LZ4F_compressFrame_usingCDict(compressedBuffer, dstCapacity, + LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity, CNBuffer, dictSize, cdict, &cParams) ); DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeLevelMax); @@ -584,7 +586,7 @@ int basicTests(U32 seed, double compressibility) cParams.frameInfo.blockMode = LZ4F_blockLinked; cParams.frameInfo.blockSizeID = LZ4F_max64KB; CHECK_V(cSizeContiguous, - LZ4F_compressFrame_usingCDict(compressedBuffer, outCapacity, + LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, outCapacity, CNBuffer, inSize, cdict, &cParams) ); DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n", @@ -620,7 +622,7 @@ int basicTests(U32 seed, double compressibility) cParams.frameInfo.blockMode = LZ4F_blockIndependent; cParams.frameInfo.blockSizeID = LZ4F_max64KB; CHECK_V(cSizeIndep, - LZ4F_compressFrame_usingCDict(compressedBuffer, outCapacity, + LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, outCapacity, CNBuffer, inSize, cdict, &cParams) ); DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n", @@ -647,6 +649,7 @@ int basicTests(U32 seed, double compressibility) } LZ4F_freeCDict(cdict); + CHECK( LZ4F_freeCompressionContext(cctx) ); cctx = NULL; } -- cgit v0.12