From 450feb0f95636a7622e3c4b1e14ba33253a8c5c9 Mon Sep 17 00:00:00 2001
From: Nick Terrell Streaming compression functions
typedef enum {
size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */
-This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and
ZSTD_compressStream2(). It is redundent, but is still fully supported.
+
This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and
ZSTD_compressStream2(). It is redundant, but is still fully supported.
Advanced parameters and dictionary compression can only be used through the
new API.
@@ -647,9 +647,7 @@ Streaming compression functions
typedef enum {
ZSTD_DStream management functions
ZSTD_DStream* ZSTD_createDStream(void);
size_t ZSTD_freeDStream(ZSTD_DStream* zds);
-Streaming decompression functions
size_t ZSTD_initDStream(ZSTD_DStream* zds);
-size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
-
+Streaming decompression functions
size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
@@ -1407,9 +1405,32 @@
Advanced Streaming compression functions
/**! ZST
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);/**< note: no dictionary will be used if dict == NULL or dictSize < 8 */ -size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict is referenced, it must outlive decompression session */ -size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */ +
This is an advanced API, giving full control over buffer management, for users which need direct control over memory. From 61025d5b7d283e62304e177dd21db65225c4a5b2 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte"Date: Fri, 24 May 2019 16:55:59 -0400 Subject: [PATCH 027/108] zstdgrep: Handle -f Flag --- programs/zstdgrep | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/programs/zstdgrep b/programs/zstdgrep index cb804b8bead..4879fb0dae4 100755 --- a/programs/zstdgrep +++ b/programs/zstdgrep @@ -58,6 +58,9 @@ while [ "$#" -gt 0 ] && [ "${endofopts}" -eq 0 ]; do shift 2 break ;; + -f) + pattern_found=2 + ;; *) ;; esac @@ -117,7 +120,11 @@ else set -f while [ "$#" -gt 0 ]; do # shellcheck disable=SC2086 - "${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - + if [ $pattern_found -eq 2 ]; then + "${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- - + else + "${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - + fi [ "$?" -ne 0 ] && EXIT_CODE=1 shift done From 6a0638048a33ef87971dcd2141e45e7e5bd90307 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 24 May 2019 17:21:44 -0400 Subject: [PATCH 028/108] Add Test --- tests/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Makefile b/tests/Makefile index f11b731835e..4ee684e0870 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -359,6 +359,9 @@ test-zstdgrep: gzstd -echo 'hello world' > test.txt && $(PRGDIR)/zstd test.txt env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep hello test.txt.zst env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep weird test.txt.zst && return 1 || return 0 + -echo 'hello' > pattern.txt + env ZCAT=/tmp/zstdcat $(PRGDIR)/zstdgrep -f pattern.txt test.txt.zst + $(RM) test.txt test.txt.zst pattern.txt test-fullbench: fullbench datagen $(QEMU_SYS) ./fullbench -i1 From 3f5737afd7d9520868dd70ca8f959fa6eb962ce9 Mon Sep 17 00:00:00 2001 From: Jonathan Scott Date: Sat, 25 May 2019 17:29:04 -0700 Subject: [PATCH 029/108] CMake: Check for existing custom target 'uninstall' --- build/cmake/lib/CMakeLists.txt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 508bee37819..e415c159006 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -194,10 +194,12 @@ if (ZSTD_BUILD_STATIC) endif () # uninstall target -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY) - -add_custom_target(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +if (NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +endif () From 1bc77ee174f3d75485794e457f1564801c75daec Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sun, 26 May 2019 03:18:39 -0700 Subject: [PATCH 030/108] Skip --adapt and --rsyncable tests when built without thread support These options require ZSTD_MULTITHREAD. --- tests/playTests.sh | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/playTests.sh b/tests/playTests.sh index df13a71f9e0..c4d68998e56 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -895,18 +895,21 @@ roundTripTest -g1M -P50 "1 --single-thread --long=29" " --long=28 --memory=512MB roundTripTest -g1M -P50 "1 --single-thread --long=29" " --zstd=wlog=28 --memory=512MB" -println "\n===> adaptive mode " -roundTripTest -g270000000 " --adapt" -roundTripTest -g27000000 " --adapt=min=1,max=4" -println "===> test: --adapt must fail on incoherent bounds " -./datagen > tmp -$ZSTD -f -vv --adapt=min=10,max=9 tmp && die "--adapt must fail on incoherent bounds" +if [ -n "$hasMT" ] +then + println "\n===> adaptive mode " + roundTripTest -g270000000 " --adapt" + roundTripTest -g27000000 " --adapt=min=1,max=4" + println "===> test: --adapt must fail on incoherent bounds " + ./datagen > tmp + $ZSTD -f -vv --adapt=min=10,max=9 tmp && die "--adapt must fail on incoherent bounds" -println "\n===> rsyncable mode " -roundTripTest -g10M " --rsyncable" -roundTripTest -g10M " --rsyncable -B100K" -println "===> test: --rsyncable must fail with --single-thread" -$ZSTD -f -vv --rsyncable --single-thread tmp && die "--rsyncable must fail with --single-thread" + println "\n===> rsyncable mode " + roundTripTest -g10M " --rsyncable" + roundTripTest -g10M " --rsyncable -B100K" + println "===> test: --rsyncable must fail with --single-thread" + $ZSTD -f -vv --rsyncable --single-thread tmp && die "--rsyncable must fail with --single-thread" +fi if [ "$1" != "--test-large-data" ]; then From 4baecdf72ad83fd8a6425af4bd60cc4c31a7f8b7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 May 2019 13:15:48 -0700 Subject: [PATCH 031/108] added comments to better understand enforceMaxDist() --- lib/compress/zstd_compress.c | 31 ++++++------ lib/compress/zstd_compress_internal.h | 71 +++++++++++++++++---------- tests/fuzzer.c | 35 +++++++------ 3 files changed, 79 insertions(+), 58 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 2e163c8bf3d..bd13eebb07f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1282,8 +1282,8 @@ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs) } /*! ZSTD_invalidateMatchState() - * Invalidate all the matches in the match finder tables. - * Requires nextSrc and base to be set (can be NULL). + * Invalidate all the matches in the match finder tables. + * Requires nextSrc and base to be set (can be NULL). */ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) { @@ -1587,15 +1587,14 @@ static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict, * handled in _enforceMaxDist */ } -static size_t ZSTD_resetCCtx_byAttachingCDict( - ZSTD_CCtx* cctx, - const ZSTD_CDict* cdict, - ZSTD_CCtx_params params, - U64 pledgedSrcSize, - ZSTD_buffered_policy_e zbuff) +static size_t +ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, + const ZSTD_CDict* cdict, + ZSTD_CCtx_params params, + U64 pledgedSrcSize, + ZSTD_buffered_policy_e zbuff) { - { - const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams; + { const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams; unsigned const windowLog = params.cParams.windowLog; assert(windowLog != 0); /* Resize working context table params for input only, since the dict @@ -1607,8 +1606,7 @@ static size_t ZSTD_resetCCtx_byAttachingCDict( assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); } - { - const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc + { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc - cdict->matchState.window.base); const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit; if (cdictLen == 0) { @@ -1625,9 +1623,9 @@ static size_t ZSTD_resetCCtx_byAttachingCDict( cctx->blockState.matchState.window.base + cdictEnd; ZSTD_window_clear(&cctx->blockState.matchState.window); } + /* loadedDictEnd is expressed within the referential of the active context */ cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit; - } - } + } } cctx->dictID = cdict->dictID; @@ -2844,7 +2842,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; - assert(cctx->appliedParams.cParams.windowLog <= 31); + assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); if (cctx->appliedParams.fParams.checksumFlag && srcSize) @@ -2899,7 +2897,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, } } if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending; - return op-ostart; + return (size_t)(op-ostart); } @@ -2991,6 +2989,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, cctx->pledgedSrcSizePlusOne-1, cctx->dictID); FORWARD_IF_ERROR(fhSize); + assert(fhSize <= dstCapacity); dstCapacity -= fhSize; dst = (char*)dst + fhSize; cctx->stage = ZSTDcs_ongoing; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index cc3cbb9da9f..cbf15136e9b 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -33,13 +33,13 @@ extern "C" { ***************************************/ #define kSearchStrength 8 #define HASH_READ_SIZE 8 -#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted". +#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index ZSTD_DUBT_UNSORTED_MARK==1 means "unsorted". It could be confused for a real successor at index "1", if sorted as larger than its predecessor. It's not a big deal though : candidate will just be sorted again. Additionally, candidate position 1 will be lost. But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss. - The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy - Constant required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */ + The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy. + This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */ /*-************************************* @@ -128,13 +128,13 @@ typedef struct { BYTE const* base; /* All regular indexes relative to this position */ BYTE const* dictBase; /* extDict indexes relative to this position */ U32 dictLimit; /* below that point, need extDict */ - U32 lowLimit; /* below that point, no more data */ + U32 lowLimit; /* below that point, no more valid data */ } ZSTD_window_t; typedef struct ZSTD_matchState_t ZSTD_matchState_t; struct ZSTD_matchState_t { ZSTD_window_t window; /* State for window round buffer management */ - U32 loadedDictEnd; /* index of end of dictionary */ + U32 loadedDictEnd; /* index of end of dictionary, within dictionary's referential. Only used for attached dictionaries. Effectively same value as dictSize, since dictionary indexes start a zero */ U32 nextToUpdate; /* index from which to continue table update */ U32 nextToUpdate3; /* index from which to continue table update */ U32 hashLog3; /* dispatch table : larger == faster, more memory */ @@ -675,31 +675,49 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, * Updates lowLimit so that: * (srcEnd - base) - lowLimit == maxDist + loadedDictEnd * - * This allows a simple check that index >= lowLimit to see if index is valid. - * This must be called before a block compression call, with srcEnd as the block - * source end. + * It ensures index is valid as long as index >= lowLimit. + * This must be called before a block compression call. * - * If loadedDictEndPtr is not NULL, we set it to zero once we update lowLimit. - * This is because dictionaries are allowed to be referenced as long as the last - * byte of the dictionary is in the window, but once they are out of range, - * they cannot be referenced. If loadedDictEndPtr is NULL, we use - * loadedDictEnd == 0. + * loadedDictEnd is only defined if a dictionary is in use for current compression. + * As the name implies, loadedDictEnd represents the index at end of dictionary. + * The value lies within context's referential, it can be directly compared to blockEndIdx. * - * In normal dict mode, the dict is between lowLimit and dictLimit. In - * dictMatchState mode, lowLimit and dictLimit are the same, and the dictionary - * is below them. forceWindow and dictMatchState are therefore incompatible. + * If loadedDictEndPtr is NULL, no dictionary is in use, and we use loadedDictEnd == 0. + * If loadedDictEndPtr is not NULL, we set it to zero after updating lowLimit. + * This is because dictionaries are allowed to be referenced fully + * as long as the last byte of the dictionary is in the window. + * Once input has progressed beyond window size, dictionary cannot be referenced anymore. + * + * In normal dict mode, the dictionary lies between lowLimit and dictLimit. + * In dictMatchState mode, lowLimit and dictLimit are the same, + * and the dictionary is below them. + * forceWindow and dictMatchState are therefore incompatible. */ MEM_STATIC void ZSTD_window_enforceMaxDist(ZSTD_window_t* window, - void const* srcEnd, - U32 maxDist, - U32* loadedDictEndPtr, + const void* blockEnd, + U32 maxDist, + U32* loadedDictEndPtr, const ZSTD_matchState_t** dictMatchStatePtr) { - U32 const blockEndIdx = (U32)((BYTE const*)srcEnd - window->base); - U32 loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0; - DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u", - (unsigned)blockEndIdx, (unsigned)maxDist); + U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base); + U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0; + DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u", + (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd); + + /* - When there is no dictionary : loadedDictEnd == 0. + In which case, the test (blockEndIdx > maxDist) is merely to avoid + overflowing next operation `newLowLimit = blockEndIdx - maxDist`. + - When there is a standard dictionary : + Index referential is copied from the dictionary, + which means it starts from 0. + In which case, loadedDictEnd == dictSize, + and it makes sense to compare `blockEndIdx > maxDist + dictSize` + since `blockEndIdx` also starts from zero. + - When there is an attached dictionary : + loadedDictEnd is expressed within the referential of the context, + so it can be directly compared against blockEndIdx. + */ if (blockEndIdx > maxDist + loadedDictEnd) { U32 const newLowLimit = blockEndIdx - maxDist; if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit; @@ -708,10 +726,9 @@ ZSTD_window_enforceMaxDist(ZSTD_window_t* window, (unsigned)window->dictLimit, (unsigned)window->lowLimit); window->dictLimit = window->lowLimit; } - if (loadedDictEndPtr) - *loadedDictEndPtr = 0; - if (dictMatchStatePtr) - *dictMatchStatePtr = NULL; + /* On reaching window size, dictionaries are invalidated */ + if (loadedDictEndPtr) *loadedDictEndPtr = 0; + if (dictMatchStatePtr) *dictMatchStatePtr = NULL; } } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 1a31c78e292..1fe488a2590 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -62,10 +62,12 @@ static U32 g_displayLevel = 2; static const U64 g_refreshRate = SEC_TO_MICRO / 6; static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; -#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ - if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \ - { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ - if (g_displayLevel>=4) fflush(stderr); } } +#define DISPLAYUPDATE(l, ...) \ + if (g_displayLevel>=l) { \ + if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \ + { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ + if (g_displayLevel>=4) fflush(stderr); } \ + } /*-******************************************************* @@ -73,7 +75,7 @@ static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; *********************************************************/ #undef MIN #undef MAX -/* Declaring the function is it isn't unused */ +/* Declaring the function, to avoid -Wmissing-prototype */ void FUZ_bug976(void); void FUZ_bug976(void) { /* these constants shall not depend on MIN() macro */ @@ -247,7 +249,7 @@ static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsig /* advanced MT streaming API test */ if (part <= 4) - { unsigned nbThreads; + { int nbThreads; for (nbThreads=1; nbThreads<=4; nbThreads++) { int compressionLevel; for (compressionLevel=1; compressionLevel<=6; compressionLevel++) { @@ -261,7 +263,7 @@ static int FUZ_mallocTests_internal(unsigned seed, double compressibility, unsig CHECK_Z( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue) ); while ( ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end) ) {} ZSTD_freeCCtx(cctx); - DISPLAYLEVEL(3, "compress_generic,-T%u,continue level %i : ", + DISPLAYLEVEL(3, "compress_generic,-T%i,continue level %i : ", nbThreads, compressionLevel); FUZ_displayMallocStats(malcount); } } } @@ -768,13 +770,11 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : init CCtx for small level %u (should work again) : ", testNb++, 1); - { size_t const r = ZSTD_compressBegin(staticCCtx, 1); - if (ZSTD_isError(r)) goto _output_error; } + CHECK( ZSTD_compressBegin(staticCCtx, 1) ); DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : init CStream for small level %u : ", testNb++, 1); - { size_t const r = ZSTD_initCStream(staticCCtx, 1); - if (ZSTD_isError(r)) goto _output_error; } + CHECK( ZSTD_initCStream(staticCCtx, 1) ); DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : init CStream with dictionary (should fail) : ", testNb++); @@ -1059,7 +1059,7 @@ static int basicUnitTests(U32 seed, double compressibility) /* Dictionary and dictBuilder tests */ { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); size_t const dictBufferCapacity = 16 KB; - void* dictBuffer = malloc(dictBufferCapacity); + void* const dictBuffer = malloc(dictBufferCapacity); size_t const totalSampleSize = 1 MB; size_t const sampleUnitSize = 8 KB; U32 const nbSamples = (U32)(totalSampleSize / sampleUnitSize); @@ -1164,6 +1164,7 @@ static int basicUnitTests(U32 seed, double compressibility) ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); + assert(cdict != NULL); DISPLAYLEVEL(3, "(size : %u) : ", (unsigned)ZSTD_sizeof_CDict(cdict)); cSize = ZSTD_compress_usingCDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, cdict); @@ -1221,8 +1222,11 @@ static int basicUnitTests(U32 seed, double compressibility) { ZSTD_frameParameters const fParams = { 0 /* frameSize */, 1 /* checksum */, 1 /* noDictID*/ }; ZSTD_compressionParameters const cParams = ZSTD_getCParams(1, CNBuffSize, dictSize); ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); - cSize = ZSTD_compress_usingCDict_advanced(cctx, compressedBuffer, compressedBufferSize, - CNBuffer, CNBuffSize, cdict, fParams); + assert(cdict != NULL); + cSize = ZSTD_compress_usingCDict_advanced(cctx, + compressedBuffer, compressedBufferSize, + CNBuffer, CNBuffSize, + cdict, fParams); ZSTD_freeCDict(cdict); if (ZSTD_isError(cSize)) goto _output_error; } @@ -1235,7 +1239,8 @@ static int basicUnitTests(U32 seed, double compressibility) DISPLAYLEVEL(3, "OK (unknown)\n"); DISPLAYLEVEL(3, "test%3i : frame built without dictID should be decompressible : ", testNb++); - { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); + { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); + assert(dctx != NULL); CHECKPLUS(r, ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, From 6453f8158f2a10846490266d5fa07e9d40c8307a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 May 2019 14:12:16 -0700 Subject: [PATCH 032/108] complementary code comments on variables used / impacted during maxDist check --- lib/compress/zstd_compress.c | 3 +++ lib/compress/zstd_compress_internal.h | 4 ++-- lib/compress/zstd_opt.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index bd13eebb07f..0e522a71131 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2866,10 +2866,13 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, ZSTD_reduceIndex(cctx, correction); if (ms->nextToUpdate < correction) ms->nextToUpdate = 0; else ms->nextToUpdate -= correction; + /* invalidate dictionaries on overflow correction */ ms->loadedDictEnd = 0; ms->dictMatchState = NULL; } + ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); + /* Ensure hash/chain table insertion resumes no sooner than lowlimit */ if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; { size_t cSize = ZSTD_compressBlock_internal(cctx, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index cbf15136e9b..bccaacac7a4 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -134,9 +134,9 @@ typedef struct { typedef struct ZSTD_matchState_t ZSTD_matchState_t; struct ZSTD_matchState_t { ZSTD_window_t window; /* State for window round buffer management */ - U32 loadedDictEnd; /* index of end of dictionary, within dictionary's referential. Only used for attached dictionaries. Effectively same value as dictSize, since dictionary indexes start a zero */ + U32 loadedDictEnd; /* index of end of dictionary, within context's referential. When dict referential is copied into active context (i.e. not attached), effectively same value as dictSize, since referential starts at zero */ U32 nextToUpdate; /* index from which to continue table update */ - U32 nextToUpdate3; /* index from which to continue table update */ + U32 nextToUpdate3; /* index from which to continue table update of hashTable3 */ U32 hashLog3; /* dispatch table : larger == faster, more memory */ U32* hashTable; U32* hashTable3; diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index efb69d3267d..3f2f2b7ba43 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -862,7 +862,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u", (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate); assert(optLevel <= 2); - ms->nextToUpdate3 = ms->nextToUpdate; + ms->nextToUpdate3 = ms->nextToUpdate; /* note : why a separate nextToUpdate3 stored into cctx->ms if it's synchtonized from nextToUpdate anyway ? */ ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel); ip += (ip==prefixStart); From 327cf6fac115fab8ff32adaad2a2727286abf2a4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 May 2019 15:26:52 -0700 Subject: [PATCH 033/108] nextToUpdate3 does not need to be maintained outside of zstd_opt.c It's re-synchronized with nextToUpdate at beginning of each block. It only needs to be tracked from within zstd_opt block parser. Made the logic clear, so that no code tried to maintain this variable. An even better solution would be to make nextToUpdate3 an internal variable of ZSTD_compressBlock_opt_generic(). That would make it possible to remove it from ZSTD_matchState_t, thus restricting its visibility to only where it's actually useful. This would require deeper changes though, since the matchState is the natural structure to transport parameters into and inside the parser. --- lib/compress/zstd_compress.c | 3 --- lib/compress/zstd_compress_internal.h | 4 ++-- lib/compress/zstd_lazy.c | 2 -- lib/compress/zstd_opt.c | 20 +++++++++----------- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 0e522a71131..43185eea1e9 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1290,7 +1290,6 @@ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) ZSTD_window_clear(&ms->window); ms->nextToUpdate = ms->window.dictLimit; - ms->nextToUpdate3 = ms->window.dictLimit; ms->loadedDictEnd = 0; ms->opt.litLengthSum = 0; /* force reset of btopt stats */ ms->dictMatchState = NULL; @@ -1679,7 +1678,6 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState; dstMatchState->window = srcMatchState->window; dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; - dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3; dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; } @@ -1759,7 +1757,6 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState; dstMatchState->window = srcMatchState->window; dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; - dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3; dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; } dstCCtx->dictID = srcCCtx->dictID; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index bccaacac7a4..559ff7029bf 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -134,9 +134,9 @@ typedef struct { typedef struct ZSTD_matchState_t ZSTD_matchState_t; struct ZSTD_matchState_t { ZSTD_window_t window; /* State for window round buffer management */ - U32 loadedDictEnd; /* index of end of dictionary, within context's referential. When dict referential is copied into active context (i.e. not attached), effectively same value as dictSize, since referential starts at zero */ + U32 loadedDictEnd; /* index of end of dictionary, within context's referential. When dict referential is copied into active context (i.e. not attached), effectively same value as dictSize, since referential starts from zero */ U32 nextToUpdate; /* index from which to continue table update */ - U32 nextToUpdate3; /* index from which to continue table update of hashTable3 */ + U32 nextToUpdate3; /* index from which to continue table update of hashTable3. synchronized with nextToUpdate at block's start, so no need to maintain outside of parser. Used by opt parser only */ U32 hashLog3; /* dispatch table : larger == faster, more memory */ U32* hashTable; U32* hashTable3; diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 53f998a4374..aa932b511de 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -653,7 +653,6 @@ size_t ZSTD_compressBlock_lazy_generic( /* init */ ip += (dictAndPrefixLength == 0); - ms->nextToUpdate3 = ms->nextToUpdate; if (dictMode == ZSTD_noDict) { U32 const maxRep = (U32)(ip - prefixLowest); if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0; @@ -933,7 +932,6 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( U32 offset_1 = rep[0], offset_2 = rep[1]; /* init */ - ms->nextToUpdate3 = ms->nextToUpdate; ip += (ip == prefixStart); /* Match Loop */ diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 3f2f2b7ba43..faacc75a430 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -255,13 +255,13 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP * to provide a cost which is directly comparable to a match ending at same position */ static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel) { - if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel); + if (optPtr->priceType >= zop_predef) return (int)WEIGHT(litLength, optLevel); /* dynamic statistics */ { U32 const llCode = ZSTD_LLcode(litLength); - int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER) - + WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */ - - WEIGHT(optPtr->litLengthFreq[llCode], optLevel); + int const contribution = (int)(LL_bits[llCode] * BITCOST_MULTIPLIER) + + (int)WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */ + - (int)WEIGHT(optPtr->litLengthFreq[llCode], optLevel); #if 1 return contribution; #else @@ -278,7 +278,7 @@ static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLe const optState_t* const optPtr, int optLevel) { - int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel) + int const contribution = (int)ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel) + ZSTD_litLengthContribution(litLength, optPtr, optLevel); return contribution; } @@ -378,7 +378,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* U32 const hashLog3 = ms->hashLog3; const BYTE* const base = ms->window.base; U32 idx = ms->nextToUpdate3; - U32 const target = ms->nextToUpdate3 = (U32)(ip - base); + U32 const target = (U32)(ip - base); size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3); assert(hashLog3 > 0); @@ -387,6 +387,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* idx++; } + ms->nextToUpdate3 = target; return hashTable3[hash3]; } @@ -653,9 +654,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( (ip+mlen == iLimit) ) { /* best possible length */ ms->nextToUpdate = current+1; /* skip insertion */ return 1; - } - } - } + } } } /* no dictMatchState lookup: dicts don't have a populated HC3 table */ } @@ -862,7 +861,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u", (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate); assert(optLevel <= 2); - ms->nextToUpdate3 = ms->nextToUpdate; /* note : why a separate nextToUpdate3 stored into cctx->ms if it's synchtonized from nextToUpdate anyway ? */ + ms->nextToUpdate3 = ms->nextToUpdate; /* note : nextToUpdate3 always synchronized with nextToUpdate at beginning of block */ ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel); ip += (ip==prefixStart); @@ -1158,7 +1157,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms, ms->window.dictLimit += (U32)srcSize; ms->window.lowLimit = ms->window.dictLimit; ms->nextToUpdate = ms->window.dictLimit; - ms->nextToUpdate3 = ms->window.dictLimit; /* re-inforce weight of collected statistics */ ZSTD_upscaleStats(&ms->opt); From 33dabc8c80d637dfed25ce5037d6373e47356ca6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 May 2019 16:11:32 -0700 Subject: [PATCH 034/108] get bt matches : made it a bit clearer which parameters are input and output --- lib/compress/zstd_opt.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index faacc75a430..aaacf55aec0 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -532,11 +532,11 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) { FORCE_INLINE_TEMPLATE U32 ZSTD_insertBtAndGetAllMatches ( + ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */ ZSTD_matchState_t* ms, const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode, - U32 rep[ZSTD_REP_NUM], + const U32 rep[ZSTD_REP_NUM], U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */ - ZSTD_match_t* matches, const U32 lengthToBeat, U32 const mls /* template */) { @@ -759,10 +759,12 @@ U32 ZSTD_insertBtAndGetAllMatches ( FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches ( + ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */ ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode, - U32 rep[ZSTD_REP_NUM], U32 const ll0, - ZSTD_match_t* matches, U32 const lengthToBeat) + const U32 rep[ZSTD_REP_NUM], + U32 const ll0, + U32 const lengthToBeat) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32 const matchLengthSearch = cParams->minMatch; @@ -771,12 +773,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches ( ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode); switch(matchLengthSearch) { - case 3 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 3); + case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3); default : - case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4); - case 5 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 5); + case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4); + case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5); case 7 : - case 6 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 6); + case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6); } } @@ -872,7 +874,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, /* find first match */ { U32 const litlen = (U32)(ip - anchor); U32 const ll0 = !litlen; - U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0, matches, minMatch); + U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, ip, iend, dictMode, rep, ll0, minMatch); if (!nbMatches) { ip++; continue; } /* initialize opt[0] */ @@ -969,7 +971,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0; U32 const previousPrice = opt[cur].price; U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel); - U32 const nbMatches = ZSTD_BtGetAllMatches(ms, inr, iend, dictMode, opt[cur].rep, ll0, matches, minMatch); + U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, inr, iend, dictMode, opt[cur].rep, ll0, minMatch); U32 matchNb; if (!nbMatches) { DEBUGLOG(7, "rPos:%u : no match found", cur); @@ -1093,7 +1095,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } /* while (ip < ilimit) */ /* Return the last literals size */ - return iend - anchor; + return (size_t)(iend - anchor); } From 9719fd616cb96d7a5120190b1a751d2ca421db36 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 May 2019 16:18:12 -0700 Subject: [PATCH 035/108] removed nextToUpdate3 from ZSTD_window it's now a local variable of ZSTD_compressBlock_opt() --- lib/compress/zstd_compress_internal.h | 1 - lib/compress/zstd_opt.c | 26 +++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 559ff7029bf..ee9d9e31a23 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -136,7 +136,6 @@ struct ZSTD_matchState_t { ZSTD_window_t window; /* State for window round buffer management */ U32 loadedDictEnd; /* index of end of dictionary, within context's referential. When dict referential is copied into active context (i.e. not attached), effectively same value as dictSize, since referential starts from zero */ U32 nextToUpdate; /* index from which to continue table update */ - U32 nextToUpdate3; /* index from which to continue table update of hashTable3. synchronized with nextToUpdate at block's start, so no need to maintain outside of parser. Used by opt parser only */ U32 hashLog3; /* dispatch table : larger == faster, more memory */ U32* hashTable; U32* hashTable3; diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index aaacf55aec0..12b56c70def 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -372,12 +372,14 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length) /* Update hashTable3 up to ip (excluded) Assumption : always within prefix (i.e. not within extDict) */ -static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* const ip) +static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, + U32* nextToUpdate3, + const BYTE* const ip) { U32* const hashTable3 = ms->hashTable3; U32 const hashLog3 = ms->hashLog3; const BYTE* const base = ms->window.base; - U32 idx = ms->nextToUpdate3; + U32 idx = *nextToUpdate3; U32 const target = (U32)(ip - base); size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3); assert(hashLog3 > 0); @@ -387,7 +389,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* idx++; } - ms->nextToUpdate3 = target; + *nextToUpdate3 = target; return hashTable3[hash3]; } @@ -534,6 +536,7 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_insertBtAndGetAllMatches ( ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */ ZSTD_matchState_t* ms, + U32* nextToUpdate3, const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode, const U32 rep[ZSTD_REP_NUM], U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */ @@ -628,7 +631,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( /* HC3 match finder */ if ((mls == 3) /*static*/ && (bestLength < mls)) { - U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip); + U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip); if ((matchIndex3 >= matchLow) & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) { size_t mlen; @@ -761,6 +764,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches ( ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */ ZSTD_matchState_t* ms, + U32* nextToUpdate3, const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode, const U32 rep[ZSTD_REP_NUM], U32 const ll0, @@ -773,12 +777,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches ( ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode); switch(matchLengthSearch) { - case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3); + case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3); default : - case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4); - case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5); + case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4); + case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5); case 7 : - case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6); + case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6); } } @@ -854,6 +858,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4; + U32 nextToUpdate3 = ms->nextToUpdate; ZSTD_optimal_t* const opt = optStatePtr->priceTable; ZSTD_match_t* const matches = optStatePtr->matchTable; @@ -863,7 +868,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u", (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate); assert(optLevel <= 2); - ms->nextToUpdate3 = ms->nextToUpdate; /* note : nextToUpdate3 always synchronized with nextToUpdate at beginning of block */ ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel); ip += (ip==prefixStart); @@ -874,7 +878,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, /* find first match */ { U32 const litlen = (U32)(ip - anchor); U32 const ll0 = !litlen; - U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, ip, iend, dictMode, rep, ll0, minMatch); + U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch); if (!nbMatches) { ip++; continue; } /* initialize opt[0] */ @@ -971,7 +975,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0; U32 const previousPrice = opt[cur].price; U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel); - U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, inr, iend, dictMode, opt[cur].rep, ll0, minMatch); + U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch); U32 matchNb; if (!nbMatches) { DEBUGLOG(7, "rPos:%u : no match found", cur); From 4c4149452c8ace4afb6c87d14cd4bac491bc9de3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 May 2019 16:37:03 -0700 Subject: [PATCH 036/108] fullbench can now select sample size with command `-B#` --- tests/fullbench.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index b06e2edc53a..b996fc5cd1e 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -51,7 +51,7 @@ #define DEFAULT_CLEVEL 1 #define COMPRESSIBILITY_DEFAULT 0.50 -static const size_t g_sampleSize = 10000000; +static const size_t k_sampleSize_default = 10000000; #define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */ @@ -66,7 +66,6 @@ static const size_t g_sampleSize = 10000000; * Benchmark Parameters **************************************/ static unsigned g_nbIterations = NBLOOPS; -static double g_compressibility = COMPRESSIBILITY_DEFAULT; /*_******************************************************* @@ -549,21 +548,19 @@ static int benchMem(unsigned benchNb, static int benchSample(U32 benchNb, + size_t benchedSize, double compressibility, int cLevel, ZSTD_compressionParameters cparams) { - size_t const benchedSize = g_sampleSize; - const char* const name = "Sample 10MiB"; - /* Allocation */ void* const origBuff = malloc(benchedSize); if (!origBuff) { DISPLAY("\nError: not enough memory!\n"); return 12; } /* Fill buffer */ - RDG_genBuffer(origBuff, benchedSize, g_compressibility, 0.0, 0); + RDG_genBuffer(origBuff, benchedSize, compressibility, 0.0, 0); /* bench */ DISPLAY("\r%70s\r", ""); - DISPLAY(" %s : \n", name); + DISPLAY(" Sample %u bytes : \n", (unsigned)benchedSize); if (benchNb) { benchMem(benchNb, origBuff, benchedSize, cLevel, cparams); } else { /* 0 == run all tests */ @@ -696,10 +693,11 @@ static int usage_advanced(const char* exename) usage(exename); DISPLAY( "\nAdvanced options :\n"); DISPLAY( " -b# : test only function # \n"); - DISPLAY( " -i# : iteration loops [1-9](default : %i)\n", NBLOOPS); - DISPLAY( " -P# : sample compressibility (default : %.1f%%)\n", COMPRESSIBILITY_DEFAULT * 100); DISPLAY( " -l# : benchmark functions at that compression level (default : %i)\n", DEFAULT_CLEVEL); DISPLAY( " --zstd : custom parameter selection. Format same as zstdcli \n"); + DISPLAY( " -P# : sample compressibility (default : %.1f%%)\n", COMPRESSIBILITY_DEFAULT * 100); + DISPLAY( " -B# : sample size (default : %u)\n", (unsigned)k_sampleSize_default); + DISPLAY( " -i# : iteration loops [1-9](default : %i)\n", NBLOOPS); return 0; } @@ -718,6 +716,8 @@ int main(int argc, const char** argv) U32 benchNb = 0, main_pause = 0; int cLevel = DEFAULT_CLEVEL; ZSTD_compressionParameters cparams = ZSTD_getCParams(cLevel, 0, 0); + size_t sampleSize = k_sampleSize_default; + double compressibility = COMPRESSIBILITY_DEFAULT; DISPLAY(WELCOME_MESSAGE); if (argc<1) return badusage(exename); @@ -767,21 +767,29 @@ int main(int argc, const char** argv) benchNb = readU32FromChar(&argument); break; - /* Modify Nb Iterations */ - case 'i': + /* Select compression level to use */ + case 'l': argument++; - g_nbIterations = readU32FromChar(&argument); + cLevel = (int)readU32FromChar(&argument); + cparams = ZSTD_getCParams(cLevel, 0, 0); break; /* Select compressibility of synthetic sample */ case 'P': argument++; - g_compressibility = (double)readU32FromChar(&argument) / 100.; + compressibility = (double)readU32FromChar(&argument) / 100.; break; - case 'l': + + /* Select size of synthetic sample */ + case 'B': argument++; - cLevel = (int)readU32FromChar(&argument); - cparams = ZSTD_getCParams(cLevel, 0, 0); + sampleSize = (size_t)readU32FromChar(&argument); + break; + + /* Modify Nb Iterations */ + case 'i': + argument++; + g_nbIterations = readU32FromChar(&argument); break; /* Unknown command */ @@ -798,7 +806,7 @@ int main(int argc, const char** argv) if (filenamesStart==0) /* no input file */ - result = benchSample(benchNb, cLevel, cparams); + result = benchSample(benchNb, sampleSize, compressibility, cLevel, cparams); else result = benchFiles(benchNb, argv+filenamesStart, argc-filenamesStart, cLevel, cparams); From eb6b1990384364f6a3aa50bd695f87da035e202e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 May 2019 16:50:49 -0700 Subject: [PATCH 037/108] fullbench: added streaming with fresh CCtx scenario worst case situation, where context must be recreated every time but without knowledge of the input size thus sizing the context for some large input. --- tests/fullbench.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/fullbench.c b/tests/fullbench.c index b996fc5cd1e..3340e9b534e 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -160,6 +160,19 @@ local_ZSTD_compressStream(const void* src, size_t srcSize, return buffOut.pos; } +static size_t +local_ZSTD_compressStream_freshCCtx(const void* src, size_t srcSize, + void* dst, size_t dstCapacity, + void* buff2) +{ + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + assert(cctx != NULL); + + return local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, buff2); + + ZSTD_freeCCtx(cctx); +} + static size_t local_ZSTD_compress_generic_end(const void* src, size_t srcSize, void* dst, size_t dstCapacity, @@ -354,6 +367,9 @@ static int benchMem(unsigned benchNb, case 42: benchFunction = local_ZSTD_decompressStream; benchName = "decompressStream"; break; + case 43: + benchFunction = local_ZSTD_compressStream_freshCCtx; benchName = "compressStream_freshCCtx"; + break; case 51: benchFunction = local_ZSTD_compress_generic_continue; benchName = "compress_generic, continue"; break; From c63081623f76c909e7bd2f1bd523c9a1fe9495f3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 May 2019 17:27:52 -0700 Subject: [PATCH 038/108] fullbench 43: ensure context is freed after each usage --- tests/fullbench.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 3340e9b534e..cd6e7454620 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -166,11 +166,14 @@ local_ZSTD_compressStream_freshCCtx(const void* src, size_t srcSize, void* buff2) { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + size_t r; assert(cctx != NULL); - return local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, buff2); + r = local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, buff2); ZSTD_freeCCtx(cctx); + + return r; } static size_t From ed38b645db5f28dac223376beb8c3b728c208ee6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 29 May 2019 15:26:06 -0700 Subject: [PATCH 039/108] fullbench: pass proper parameters in scenario 43 --- lib/compress/zstd_compress.c | 14 +++++++------- lib/compress/zstd_opt.c | 2 +- tests/fullbench.c | 3 +++ tests/fuzzer.c | 8 ++++---- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 0e522a71131..45f33679669 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -930,12 +930,12 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) @return : 0, or an error code if one value is beyond authorized range */ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) { - BOUNDCHECK(ZSTD_c_windowLog, cParams.windowLog); - BOUNDCHECK(ZSTD_c_chainLog, cParams.chainLog); - BOUNDCHECK(ZSTD_c_hashLog, cParams.hashLog); - BOUNDCHECK(ZSTD_c_searchLog, cParams.searchLog); - BOUNDCHECK(ZSTD_c_minMatch, cParams.minMatch); - BOUNDCHECK(ZSTD_c_targetLength,cParams.targetLength); + BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); + BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); + BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); + BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); + BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch); + BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength); BOUNDCHECK(ZSTD_c_strategy, cParams.strategy); return 0; } @@ -951,7 +951,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams) if ((int)val bounds.upperBound) val=(type)bounds.upperBound; \ } -# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, int) +# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned) CLAMP(ZSTD_c_windowLog, cParams.windowLog); CLAMP(ZSTD_c_chainLog, cParams.chainLog); CLAMP(ZSTD_c_hashLog, cParams.hashLog); diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 3f2f2b7ba43..534bae432d1 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -1094,7 +1094,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } /* while (ip < ilimit) */ /* Return the last literals size */ - return iend - anchor; + return (size_t)(iend - anchor); } diff --git a/tests/fullbench.c b/tests/fullbench.c index cd6e7454620..9e0770b86e1 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -499,6 +499,9 @@ static int benchMem(unsigned benchNb, case 42 : g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel); break; + case 43 : + buff2 = &cparams; + break; /* test functions */ /* convention: test functions have ID > 100 */ diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 1fe488a2590..2b6bfff6a4c 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -2464,7 +2464,7 @@ static unsigned readU32FromChar(const char** stringPtr) * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand. * @return 0 and doesn't modify *stringPtr otherwise. */ -static unsigned longCommandWArg(const char** stringPtr, const char* longCommand) +static int longCommandWArg(const char** stringPtr, const char* longCommand) { size_t const comSize = strlen(longCommand); int const result = !strncmp(*stringPtr, longCommand, comSize); @@ -2524,7 +2524,7 @@ int main(int argc, const char** argv) case 'i': argument++; maxDuration = 0; - nbTests = readU32FromChar(&argument); + nbTests = (int)readU32FromChar(&argument); break; case 'T': @@ -2544,12 +2544,12 @@ int main(int argc, const char** argv) case 't': argument++; - testNb = readU32FromChar(&argument); + testNb = (int)readU32FromChar(&argument); break; case 'P': /* compressibility % */ argument++; - proba = readU32FromChar(&argument); + proba = (int)readU32FromChar(&argument); if (proba>100) proba = 100; break; From 904d4da239d54d0cc81721c9eedd1bc98d9a69a1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 29 May 2019 16:08:49 -0700 Subject: [PATCH 040/108] fullbench : minor refactoring, for readability --- tests/fullbench.c | 123 ++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 59 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 9e0770b86e1..3c470315efd 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -99,12 +99,12 @@ static ZSTD_CCtx* g_zcc = NULL; static size_t local_ZSTD_compress(const void* src, size_t srcSize, void* dst, size_t dstSize, - void* buff2) + void* payload) { ZSTD_parameters p; ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 }; p.fParams = f; - p.cParams = *(ZSTD_compressionParameters*)buff2; + p.cParams = *(ZSTD_compressionParameters*)payload; return ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p); //return ZSTD_compress(dst, dstSize, src, srcSize, cLevel); } @@ -125,7 +125,7 @@ extern size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* ctx, const void* src, size_t s static size_t local_ZSTD_decodeLiteralsBlock(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2) { (void)src; (void)srcSize; (void)dst; (void)dstSize; - return ZSTD_decodeLiteralsBlock((ZSTD_DCtx*)g_zdc, buff2, g_cSize); + return ZSTD_decodeLiteralsBlock(g_zdc, buff2, g_cSize); } static size_t local_ZSTD_decodeSeqHeaders(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2) @@ -140,14 +140,14 @@ static ZSTD_CStream* g_cstream= NULL; static size_t local_ZSTD_compressStream(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* payload) { ZSTD_outBuffer buffOut; ZSTD_inBuffer buffIn; ZSTD_parameters p; ZSTD_frameParameters f = {1 /* contentSizeHeader*/, 0, 0}; p.fParams = f; - p.cParams = *(ZSTD_compressionParameters*)buff2; + p.cParams = *(ZSTD_compressionParameters*)payload; ZSTD_initCStream_advanced(g_cstream, NULL, 0, p, ZSTD_CONTENTSIZE_UNKNOWN); buffOut.dst = dst; buffOut.size = dstCapacity; @@ -163,13 +163,13 @@ local_ZSTD_compressStream(const void* src, size_t srcSize, static size_t local_ZSTD_compressStream_freshCCtx(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* payload) { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); size_t r; assert(cctx != NULL); - r = local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, buff2); + r = local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, payload); ZSTD_freeCCtx(cctx); @@ -179,20 +179,20 @@ local_ZSTD_compressStream_freshCCtx(const void* src, size_t srcSize, static size_t local_ZSTD_compress_generic_end(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* payload) { - (void)buff2; + (void)payload; return ZSTD_compress2(g_cstream, dst, dstCapacity, src, srcSize); } static size_t local_ZSTD_compress_generic_continue(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* payload) { ZSTD_outBuffer buffOut; ZSTD_inBuffer buffIn; - (void)buff2; + (void)payload; buffOut.dst = dst; buffOut.size = dstCapacity; buffOut.pos = 0; @@ -207,9 +207,9 @@ local_ZSTD_compress_generic_continue(const void* src, size_t srcSize, static size_t local_ZSTD_compress_generic_T2_end(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* payload) { - (void)buff2; + (void)payload; ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_nbWorkers, 2); return ZSTD_compress2(g_cstream, dst, dstCapacity, src, srcSize); } @@ -217,11 +217,11 @@ local_ZSTD_compress_generic_T2_end(const void* src, size_t srcSize, static size_t local_ZSTD_compress_generic_T2_continue(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* payload) { ZSTD_outBuffer buffOut; ZSTD_inBuffer buffIn; - (void)buff2; + (void)payload; ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_nbWorkers, 2); buffOut.dst = dst; buffOut.size = dstCapacity; @@ -257,27 +257,28 @@ local_ZSTD_decompressStream(const void* src, size_t srcSize, #ifndef ZSTD_DLL_IMPORT static size_t local_ZSTD_compressContinue(const void* src, size_t srcSize, void* dst, size_t dstCapacity, - void* buff2) + void* payload) { ZSTD_parameters p; ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 }; p.fParams = f; - p.cParams = *(ZSTD_compressionParameters*)buff2; + p.cParams = *(ZSTD_compressionParameters*)payload; ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize); return ZSTD_compressEnd(g_zcc, dst, dstCapacity, src, srcSize); } #define FIRST_BLOCK_SIZE 8 -static size_t local_ZSTD_compressContinue_extDict(const void* src, size_t srcSize, - void* dst, size_t dstCapacity, - void* buff2) +static size_t +local_ZSTD_compressContinue_extDict(const void* src, size_t srcSize, + void* dst, size_t dstCapacity, + void* payload) { BYTE firstBlockBuf[FIRST_BLOCK_SIZE]; ZSTD_parameters p; - ZSTD_frameParameters f = { 1, 0, 0 }; + ZSTD_frameParameters const f = { 1, 0, 0 }; p.fParams = f; - p.cParams = *(ZSTD_compressionParameters*)buff2; + p.cParams = *(ZSTD_compressionParameters*)payload; ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize); memcpy(firstBlockBuf, src, FIRST_BLOCK_SIZE); @@ -333,7 +334,7 @@ static int benchMem(unsigned benchNb, size_t dstBuffSize = ZSTD_compressBound(srcSize); BYTE* dstBuff; void* dstBuff2; - void* buff2; + void* payload; const char* benchName; BMK_benchFn_t benchFunction; int errorcode = 0; @@ -397,7 +398,7 @@ static int benchMem(unsigned benchNb, free(dstBuff); free(dstBuff2); return 12; } - buff2 = dstBuff2; + payload = dstBuff2; if (g_zcc==NULL) g_zcc = ZSTD_createCCtx(); if (g_zdc==NULL) g_zdc = ZSTD_createDCtx(); if (g_cstream==NULL) g_cstream = ZSTD_createCStream(); @@ -430,62 +431,66 @@ static int benchMem(unsigned benchNb, switch(benchNb) { case 1: - buff2 = &cparams; + payload = &cparams; break; case 2: - g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel); + g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel); break; #ifndef ZSTD_DLL_IMPORT case 11: - buff2 = &cparams; + payload = &cparams; break; case 12: - buff2 = &cparams; + payload = &cparams; break; case 13 : - g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel); + g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel); break; - case 31: /* ZSTD_decodeLiteralsBlock */ - { blockProperties_t bp; - ZSTD_frameHeader zfp; - size_t frameHeaderSize, skippedSize; + case 31: /* ZSTD_decodeLiteralsBlock : starts literals block in dstBuff2 */ + { size_t frameHeaderSize; g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); - frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_FRAMEHEADERSIZE_MIN); - if (frameHeaderSize==0) frameHeaderSize = ZSTD_FRAMEHEADERSIZE_MIN; - ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */ - if (bp.blockType != bt_compressed) { - DISPLAY("ZSTD_decodeLiteralsBlock : impossible to test on this sample (not compressible)\n"); - goto _cleanOut; + frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX); + assert(!ZSTD_isError(frameHeaderSize)); + /* check block is compressible, hence contains a literals section */ + { blockProperties_t bp; + ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */ + if (bp.blockType != bt_compressed) { + DISPLAY("ZSTD_decodeLiteralsBlock : impossible to test on this sample (not compressible)\n"); + goto _cleanOut; + } } + { size_t const skippedSize = frameHeaderSize + ZSTD_blockHeaderSize; + memcpy(dstBuff2, dstBuff+skippedSize, g_cSize-skippedSize); } - skippedSize = frameHeaderSize + ZSTD_blockHeaderSize; - memcpy(buff2, dstBuff+skippedSize, g_cSize-skippedSize); srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ ZSTD_decompressBegin(g_zdc); break; } case 32: /* ZSTD_decodeSeqHeaders */ { blockProperties_t bp; - ZSTD_frameHeader zfp; const BYTE* ip = dstBuff; const BYTE* iend; - size_t frameHeaderSize, cBlockSize; - ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); /* it would be better to use direct block compression here */ - g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); - frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_FRAMEHEADERSIZE_MIN); - if (frameHeaderSize==0) frameHeaderSize = ZSTD_FRAMEHEADERSIZE_MIN; - ip += frameHeaderSize; /* Skip frame Header */ - cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */ - if (bp.blockType != bt_compressed) { - DISPLAY("ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible)\n"); - goto _cleanOut; + { size_t const cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); + assert(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX); + } + /* Skip frame Header */ + { size_t const frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX); + assert(!ZSTD_isError(frameHeaderSize)); + ip += frameHeaderSize; + } + /* Find end of block */ + { size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */ + if (bp.blockType != bt_compressed) { + DISPLAY("ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible)\n"); + goto _cleanOut; + } + iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */ } - iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */ - ip += ZSTD_blockHeaderSize; /* skip block header */ + ip += ZSTD_blockHeaderSize; /* skip block header */ ZSTD_decompressBegin(g_zdc); assert(iend > ip); ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, (size_t)(iend-ip)); /* skip literal segment */ g_cSize = (size_t)(iend-ip); - memcpy(buff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */ + memcpy(dstBuff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */ srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ break; } @@ -494,13 +499,13 @@ static int benchMem(unsigned benchNb, goto _cleanOut; #endif case 41 : - buff2 = &cparams; + payload = &cparams; break; case 42 : - g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel); + g_cSize = ZSTD_compress(payload, dstBuffSize, src, srcSize, cLevel); break; case 43 : - buff2 = &cparams; + payload = &cparams; break; /* test functions */ @@ -522,7 +527,7 @@ static int benchMem(unsigned benchNb, assert(tfs != NULL); bp.benchFn = benchFunction; - bp.benchPayload = buff2; + bp.benchPayload = payload; bp.initFn = NULL; bp.initPayload = NULL; bp.errorFn = ZSTD_isError; From ab3625cffda9be5773472d42db0f8977927ce74f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 29 May 2019 16:18:22 -0700 Subject: [PATCH 041/108] define CONTROL, to ensure check cannot be disabled assert() can be disabled with NDEBUG --- tests/fullbench.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index 3c470315efd..fcae1f16a73 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -15,7 +15,6 @@ #include "util.h" /* Compiler options, UTIL_GetFileSize */ #include /* malloc */ #include /* fprintf, fopen, ftello64 */ -#include /* assert */ #include "timefn.h" /* UTIL_clockSpanNano, UTIL_getTime */ #include "mem.h" /* U32 */ @@ -61,6 +60,7 @@ static const size_t k_sampleSize_default = 10000000; **************************************/ #define DISPLAY(...) fprintf(stderr, __VA_ARGS__) +#define CONTROL(c) { if (!(c)) { abort(); } } /* like assert(), but cannot be disabled */ /*_************************************ * Benchmark Parameters @@ -450,7 +450,7 @@ static int benchMem(unsigned benchNb, { size_t frameHeaderSize; g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX); - assert(!ZSTD_isError(frameHeaderSize)); + CONTROL(!ZSTD_isError(frameHeaderSize)); /* check block is compressible, hence contains a literals section */ { blockProperties_t bp; ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */ @@ -470,11 +470,11 @@ static int benchMem(unsigned benchNb, const BYTE* ip = dstBuff; const BYTE* iend; { size_t const cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); - assert(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX); + CONTROL(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX); } /* Skip frame Header */ { size_t const frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX); - assert(!ZSTD_isError(frameHeaderSize)); + CONTROL(!ZSTD_isError(frameHeaderSize)); ip += frameHeaderSize; } /* Find end of block */ @@ -487,7 +487,7 @@ static int benchMem(unsigned benchNb, } ip += ZSTD_blockHeaderSize; /* skip block header */ ZSTD_decompressBegin(g_zdc); - assert(iend > ip); + CONTROL(iend > ip); ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, (size_t)(iend-ip)); /* skip literal segment */ g_cSize = (size_t)(iend-ip); memcpy(dstBuff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */ @@ -524,7 +524,7 @@ static int benchMem(unsigned benchNb, BMK_runTime_t bestResult; bestResult.sumOfReturn = 0; bestResult.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000; /* hopefully large enough : must be larger than any potential measurement */ - assert(tfs != NULL); + CONTROL(tfs != NULL); bp.benchFn = benchFunction; bp.benchPayload = payload; @@ -751,7 +751,7 @@ int main(int argc, const char** argv) for (argNb=1; argNb Date: Thu, 30 May 2019 10:13:56 -0700 Subject: [PATCH 042/108] consistency : changed constant name to kSampleSizeDefault as suggested by @terrelln. added include --- tests/fullbench.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/fullbench.c b/tests/fullbench.c index fcae1f16a73..f750ee0d78f 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -15,6 +15,7 @@ #include "util.h" /* Compiler options, UTIL_GetFileSize */ #include /* malloc */ #include /* fprintf, fopen, ftello64 */ +#include #include "timefn.h" /* UTIL_clockSpanNano, UTIL_getTime */ #include "mem.h" /* U32 */ @@ -30,8 +31,8 @@ #include "zstd.h" /* ZSTD_versionString */ #include "util.h" /* time functions */ #include "datagen.h" -#include "benchfn.h" /* CustomBench*/ -#include "benchzstd.h" /* MB_UNIT */ +#include "benchfn.h" /* CustomBench */ +#include "benchzstd.h" /* MB_UNIT */ /*_************************************ @@ -50,7 +51,7 @@ #define DEFAULT_CLEVEL 1 #define COMPRESSIBILITY_DEFAULT 0.50 -static const size_t k_sampleSize_default = 10000000; +static const size_t kSampleSizeDefault = 10000000; #define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */ @@ -723,7 +724,7 @@ static int usage_advanced(const char* exename) DISPLAY( " -l# : benchmark functions at that compression level (default : %i)\n", DEFAULT_CLEVEL); DISPLAY( " --zstd : custom parameter selection. Format same as zstdcli \n"); DISPLAY( " -P# : sample compressibility (default : %.1f%%)\n", COMPRESSIBILITY_DEFAULT * 100); - DISPLAY( " -B# : sample size (default : %u)\n", (unsigned)k_sampleSize_default); + DISPLAY( " -B# : sample size (default : %u)\n", (unsigned)kSampleSizeDefault); DISPLAY( " -i# : iteration loops [1-9](default : %i)\n", NBLOOPS); return 0; } @@ -743,7 +744,7 @@ int main(int argc, const char** argv) U32 benchNb = 0, main_pause = 0; int cLevel = DEFAULT_CLEVEL; ZSTD_compressionParameters cparams = ZSTD_getCParams(cLevel, 0, 0); - size_t sampleSize = k_sampleSize_default; + size_t sampleSize = kSampleSizeDefault; double compressibility = COMPRESSIBILITY_DEFAULT; DISPLAY(WELCOME_MESSAGE); From bc601bdc6d8a290da9916709dee1178ad5d01b3c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 May 2019 15:55:12 -0700 Subject: [PATCH 043/108] first implementation of small window size for btopt noticeably improves compression ratio when window size is small (< 18). enwik7 level 19 windowLog `dev` `smallwlog` improvement 23 3.577 3.577 0.02% 22 3.536 3.538 0.06% 21 3.462 3.467 0.14% 20 3.364 3.377 0.39% 19 3.244 3.272 0.86% 18 3.110 3.166 1.80% 17 2.843 3.057 7.53% 16 2.724 2.943 8.04% 15 2.594 2.822 8.79% 14 2.456 2.686 9.36% 13 2.312 2.523 9.13% 12 2.162 2.361 9.20% 11 2.003 2.182 8.94% --- lib/compress/zstd_compress.c | 10 ++++---- lib/compress/zstd_compress_internal.h | 34 ++++++++++++++++++++++++++- lib/compress/zstd_opt.c | 6 +++-- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b4feaef83f7..46400f78a45 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1387,7 +1387,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, note : `params` are assumed fully validated at this stage */ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, ZSTD_CCtx_params params, - U64 pledgedSrcSize, + U64 const pledgedSrcSize, ZSTD_compResetPolicy_e const crp, ZSTD_buffered_policy_e const zbuff) { @@ -2868,7 +2868,8 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, ms->dictMatchState = NULL; } - ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); + //ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); + ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); /* Ensure hash/chain table insertion resumes no sooner than lowlimit */ if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; @@ -3296,12 +3297,11 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, ZSTDcrp_continue, zbuff) ); - { - size_t const dictID = ZSTD_compress_insertDictionary( + { size_t const dictID = ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, ¶ms, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace); FORWARD_IF_ERROR(dictID); - assert(dictID <= (size_t)(U32)-1); + assert(dictID <= UINT32_MAX); cctx->dictID = (U32)dictID; } return 0; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ee9d9e31a23..6e3021080b3 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -141,7 +141,7 @@ struct ZSTD_matchState_t { U32* hashTable3; U32* chainTable; optState_t opt; /* optimal parser state */ - const ZSTD_matchState_t * dictMatchState; + const ZSTD_matchState_t* dictMatchState; ZSTD_compressionParameters cParams; }; @@ -731,6 +731,38 @@ ZSTD_window_enforceMaxDist(ZSTD_window_t* window, } } +MEM_STATIC void +ZSTD_checkDictValidity(ZSTD_window_t* window, + const void* blockEnd, + U32 maxDist, + U32* loadedDictEndPtr, + const ZSTD_matchState_t** dictMatchStatePtr) +{ + U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base); + U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0; + DEBUGLOG(5, "ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u", + (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd); + + /* - When there is no dictionary : loadedDictEnd == 0. + In which case, the test (blockEndIdx > maxDist) is merely to avoid + overflowing next operation `newLowLimit = blockEndIdx - maxDist`. + - When there is a standard dictionary : + Index referential is copied from the dictionary, + which means it starts from 0. + In which case, loadedDictEnd == dictSize, + and it makes sense to compare `blockEndIdx > maxDist + dictSize` + since `blockEndIdx` also starts from zero. + - When there is an attached dictionary : + loadedDictEnd is expressed within the referential of the context, + so it can be directly compared against blockEndIdx. + */ + if (loadedDictEnd && (blockEndIdx > maxDist + loadedDictEnd)) { + /* On reaching window size, dictionaries are invalidated */ + if (loadedDictEndPtr) *loadedDictEndPtr = 0; + if (dictMatchStatePtr) *dictMatchStatePtr = NULL; + } +} + /** * ZSTD_window_update(): * Updates the window by appending [src, src + srcSize) to the window. diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 12b56c70def..4c72d243daa 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -545,6 +545,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); + U32 const maxDistance = 1U << cParams->windowLog; const BYTE* const base = ms->window.base; U32 const current = (U32)(ip-base); U32 const hashLog = cParams->hashLog; @@ -560,8 +561,9 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 const dictLimit = ms->window.dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; - U32 const btLow = btMask >= current ? 0 : current - btMask; - U32 const windowLow = ms->window.lowLimit; + U32 const btLow = (btMask >= current) ? 0 : current - btMask; + U32 const windowValid = ms->window.lowLimit; + U32 const windowLow = ((current - windowValid) > maxDistance) ? current - maxDistance : windowValid; U32 const matchLow = windowLow ? windowLow : 1; U32* smallerPtr = bt + 2*(current&btMask); U32* largerPtr = bt + 2*(current&btMask) + 1; From 58adb1059fbdd75e14e78f85fe078365eaa51ce6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 May 2019 16:08:48 -0700 Subject: [PATCH 044/108] extended exact window size to greedy/lazy modes --- lib/compress/zstd_lazy.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index aa932b511de..94d906c01f1 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -83,7 +83,10 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms, U32* largerPtr = smallerPtr + 1; U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */ U32 dummy32; /* to be nullified at the end */ - U32 const windowLow = ms->window.lowLimit; + U32 const windowValid = ms->window.lowLimit; + U32 const maxDistance = 1U << cParams->windowLog; + U32 const windowLow = (current - windowValid > maxDistance) ? current - maxDistance : windowValid; + DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)", current, dictLimit, windowLow); @@ -239,7 +242,9 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, const BYTE* const base = ms->window.base; U32 const current = (U32)(ip-base); - U32 const windowLow = ms->window.lowLimit; + U32 const maxDistance = 1U << cParams->windowLog; + U32 const windowValid = ms->window.lowLimit; + U32 const windowLow = (current - windowValid > maxDistance) ? current - maxDistance : windowValid; U32* const bt = ms->chainTable; U32 const btLog = cParams->chainLog - 1; @@ -490,8 +495,10 @@ size_t ZSTD_HcFindBestMatch_generic ( const U32 dictLimit = ms->window.dictLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; - const U32 lowLimit = ms->window.lowLimit; const U32 current = (U32)(ip-base); + const U32 maxDistance = 1U << cParams->windowLog; + const U32 lowValid = ms->window.lowLimit; + const U32 lowLimit = (current - lowValid > maxDistance) ? current - maxDistance : lowValid; const U32 minChain = current > chainSize ? current - chainSize : 0; U32 nbAttempts = 1U << cParams->searchLog; size_t ml=4-1; From a30febaeeb8dd56a786d44ebab020d0cf3113330 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 May 2019 16:34:55 -0700 Subject: [PATCH 045/108] Made fast strategy compatible with new offset validation strategy fast mode does the same thing as before : it pre-emptively invalidates any index that could lead to offset > maxDistance. It's supposed to help speed. But this logic is performed inside zstd_fast, so that other strategies can select a different behavior. --- lib/compress/zstd_fast.c | 49 ++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index ed997b441c1..a05b8a47f14 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -13,7 +13,8 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, - void const* end, ZSTD_dictTableLoadMethod_e dtlm) + const void* const end, + ZSTD_dictTableLoadMethod_e dtlm) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32* const hashTable = ms->hashTable; @@ -41,6 +42,7 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, } } } } } + FORCE_INLINE_TEMPLATE size_t ZSTD_compressBlock_fast_generic( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], @@ -58,7 +60,10 @@ size_t ZSTD_compressBlock_fast_generic( const BYTE* ip0 = istart; const BYTE* ip1; const BYTE* anchor = istart; - const U32 prefixStartIndex = ms->window.dictLimit; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + const U32 maxDistance = 1U << cParams->windowLog; + const U32 validStartIndex = ms->window.dictLimit; + const U32 prefixStartIndex = (endIndex - validStartIndex > maxDistance) ? endIndex - maxDistance : validStartIndex; const BYTE* const prefixStart = base + prefixStartIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; @@ -165,7 +170,7 @@ size_t ZSTD_compressBlock_fast_generic( rep[1] = offset_2 ? offset_2 : offsetSaved; /* Return the last literals size */ - return iend - anchor; + return (size_t)(iend - anchor); } @@ -222,8 +227,15 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart); const U32 dictHLog = dictCParams->hashLog; - /* otherwise, we would get index underflow when translating a dict index - * into a local index */ + /* if a dictionary is still attached, it necessarily means that + * it is within window size. So we just check it. */ + const U32 maxDistance = 1U << cParams->windowLog; + const U32 endIndex = (U32)((size_t)(ip - base) + srcSize); + assert(endIndex - prefixStartIndex <= maxDistance); + (void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */ + + /* ensure there will be no no underflow + * when translating a dict index into a local index */ assert(prefixStartIndex >= (U32)(dictEnd - dictBase)); /* init */ @@ -251,7 +263,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4; ip++; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH); } else if ( (matchIndex <= prefixStartIndex) ) { size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls); U32 const dictMatchIndex = dictHashTable[dictHash]; @@ -271,7 +283,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( } /* catch up */ offset_2 = offset_1; offset_1 = offset; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); } } else if (MEM_read32(match) != MEM_read32(ip)) { /* it's not a match, and we're not going to check the dictionary */ @@ -286,7 +298,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ offset_2 = offset_1; offset_1 = offset; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); } /* match found */ @@ -327,7 +339,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( rep[1] = offset_2 ? offset_2 : offsetSaved; /* Return the last literals size */ - return iend - anchor; + return (size_t)(iend - anchor); } size_t ZSTD_compressBlock_fast_dictMatchState( @@ -366,15 +378,24 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( const BYTE* const istart = (const BYTE*)src; const BYTE* ip = istart; const BYTE* anchor = istart; - const U32 dictStartIndex = ms->window.lowLimit; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + const U32 maxDistance = 1U << cParams->windowLog; + const U32 validLow = ms->window.lowLimit; + const U32 lowLimit = (endIndex - validLow > maxDistance) ? endIndex - maxDistance : validLow; + const U32 dictStartIndex = lowLimit; const BYTE* const dictStart = dictBase + dictStartIndex; - const U32 prefixStartIndex = ms->window.dictLimit; + const U32 dictLimit = ms->window.dictLimit; + const U32 prefixStartIndex = dictLimit < lowLimit ? lowLimit : dictLimit; const BYTE* const prefixStart = base + prefixStartIndex; const BYTE* const dictEnd = dictBase + prefixStartIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; U32 offset_1=rep[0], offset_2=rep[1]; + /* switch to "regular" variant if extDict is invalidated due to maxDistance */ + if (prefixStartIndex == dictStartIndex) + return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, mls); + /* Search Loop */ while (ip < ilimit) { /* < instead of <=, because (ip+1) */ const size_t h = ZSTD_hashPtr(ip, hlog, mls); @@ -394,7 +415,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4; ip++; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH); } else { if ( (matchIndex < dictStartIndex) || (MEM_read32(match) != MEM_read32(ip)) ) { @@ -410,7 +431,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( offset = current - matchIndex; offset_2 = offset_1; offset_1 = offset; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); } } /* found a match : store it */ @@ -445,7 +466,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( rep[1] = offset_2; /* Return the last literals size */ - return iend - anchor; + return (size_t)(iend - anchor); } From d605f482c7df515edf94a71ba762154c00735373 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 May 2019 16:50:04 -0700 Subject: [PATCH 046/108] make double_fast compatible with new index invalidation strategy --- lib/compress/zstd_double_fast.c | 41 ++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 47faf6d641d..7bc2e3fa0db 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -43,8 +43,7 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, /* Only load extra positions for ZSTD_dtlm_full */ if (dtlm == ZSTD_dtlm_fast) break; - } - } + } } } @@ -63,7 +62,10 @@ size_t ZSTD_compressBlock_doubleFast_generic( const BYTE* const istart = (const BYTE*)src; const BYTE* ip = istart; const BYTE* anchor = istart; - const U32 prefixLowestIndex = ms->window.dictLimit; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + const U32 lowestValid = ms->window.dictLimit; + const U32 maxDistance = 1U << cParams->windowLog; + const U32 prefixLowestIndex = (endIndex - lowestValid > maxDistance) ? endIndex - maxDistance : lowestValid; const BYTE* const prefixLowest = base + prefixLowestIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; @@ -97,6 +99,10 @@ size_t ZSTD_compressBlock_doubleFast_generic( assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState); + /* if a dictionary is attached, it must be within window range */ + if (dictMode == ZSTD_dictMatchState) + assert(lowestValid + maxDistance <= endIndex); + /* init */ ip += (dictAndPrefixLength == 0); if (dictMode == ZSTD_noDict) { @@ -138,7 +144,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; ip++; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH); goto _match_stored; } @@ -147,7 +153,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) { mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4; ip++; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH); goto _match_stored; } @@ -242,7 +248,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( offset_2 = offset_1; offset_1 = offset; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); _match_stored: /* match found */ @@ -301,7 +307,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( rep[1] = offset_2 ? offset_2 : offsetSaved; /* Return the last literals size */ - return iend - anchor; + return (size_t)(iend - anchor); } @@ -360,10 +366,15 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; - const U32 prefixStartIndex = ms->window.dictLimit; const BYTE* const base = ms->window.base; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + const U32 maxDistance = 1U << cParams->windowLog; + const U32 lowestValid = ms->window.lowLimit; + const U32 lowLimit = (endIndex - lowestValid > maxDistance) ? endIndex - maxDistance : lowestValid; + const U32 dictStartIndex = lowLimit; + const U32 dictLimit = ms->window.dictLimit; + const U32 prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit; const BYTE* const prefixStart = base + prefixStartIndex; - const U32 dictStartIndex = ms->window.lowLimit; const BYTE* const dictBase = ms->window.dictBase; const BYTE* const dictStart = dictBase + dictStartIndex; const BYTE* const dictEnd = dictBase + prefixStartIndex; @@ -371,6 +382,10 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)", srcSize); + /* if extDict is invalidated due to maxDistance, switch to "regular" variant */ + if (prefixStartIndex == dictStartIndex) + return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, mls, ZSTD_noDict); + /* Search Loop */ while (ip < ilimit) { /* < instead of <=, because (ip+1) */ const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls); @@ -396,7 +411,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4; ip++; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, 0, mLength-MINMATCH); } else { if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) { const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend; @@ -407,7 +422,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ offset_2 = offset_1; offset_1 = offset; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); } else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) { size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8); @@ -432,7 +447,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( } offset_2 = offset_1; offset_1 = offset; - ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH); } else { ip += ((ip-anchor) >> kSearchStrength) + 1; @@ -475,7 +490,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( rep[1] = offset_2; /* Return the last literals size */ - return iend - anchor; + return (size_t)(iend - anchor); } From a968099038e0ee3b939c5aa1084074c0f14f43c4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 May 2019 16:52:37 -0700 Subject: [PATCH 047/108] minor code cleaning for new index invalidation strategy --- lib/compress/zstd_compress.c | 2 +- lib/compress/zstd_compress_internal.h | 16 +++------------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 46400f78a45..7d31db72c6d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2868,8 +2868,8 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, ms->dictMatchState = NULL; } - //ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); + /* Ensure hash/chain table insertion resumes no sooner than lowlimit */ if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 6e3021080b3..55304fa317f 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -731,6 +731,9 @@ ZSTD_window_enforceMaxDist(ZSTD_window_t* window, } } +/* Similar to ZSTD_window_enforceMaxDist(), + * but only invalidates dictionary + * when input progresses beyond window size. */ MEM_STATIC void ZSTD_checkDictValidity(ZSTD_window_t* window, const void* blockEnd, @@ -743,19 +746,6 @@ ZSTD_checkDictValidity(ZSTD_window_t* window, DEBUGLOG(5, "ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u", (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd); - /* - When there is no dictionary : loadedDictEnd == 0. - In which case, the test (blockEndIdx > maxDist) is merely to avoid - overflowing next operation `newLowLimit = blockEndIdx - maxDist`. - - When there is a standard dictionary : - Index referential is copied from the dictionary, - which means it starts from 0. - In which case, loadedDictEnd == dictSize, - and it makes sense to compare `blockEndIdx > maxDist + dictSize` - since `blockEndIdx` also starts from zero. - - When there is an attached dictionary : - loadedDictEnd is expressed within the referential of the context, - so it can be directly compared against blockEndIdx. - */ if (loadedDictEnd && (blockEndIdx > maxDist + loadedDictEnd)) { /* On reaching window size, dictionaries are invalidated */ if (loadedDictEndPtr) *loadedDictEndPtr = 0; From fce4df3ab7be85a8c3bd3ef8e604c329b6864b18 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 May 2019 17:06:28 -0700 Subject: [PATCH 048/108] fixed wrong assert in double_fast --- lib/compress/zstd_double_fast.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 7bc2e3fa0db..3c8e22ba598 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -97,11 +97,14 @@ size_t ZSTD_compressBlock_doubleFast_generic( dictCParams->chainLog : hBitsS; const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictStart); + DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_generic"); + assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState); /* if a dictionary is attached, it must be within window range */ - if (dictMode == ZSTD_dictMatchState) - assert(lowestValid + maxDistance <= endIndex); + if (dictMode == ZSTD_dictMatchState) { + assert(lowestValid + maxDistance >= endIndex); + } /* init */ ip += (dictAndPrefixLength == 0); From 80d6ccea7930d1c904eb898cf49c3f1e154474af Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 31 May 2019 17:27:07 -0700 Subject: [PATCH 049/108] removed UINT32_MAX apparently not guaranteed on all platforms, replaced by UINT_MAX. --- lib/compress/zstd_compress.c | 2 +- lib/compress/zstd_double_fast.c | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 7d31db72c6d..77b8b9b70cf 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3301,7 +3301,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, cctx->blockState.prevCBlock, &cctx->blockState.matchState, ¶ms, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace); FORWARD_IF_ERROR(dictID); - assert(dictID <= UINT32_MAX); + assert(dictID <= UINT_MAX); cctx->dictID = (U32)dictID; } return 0; diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 3c8e22ba598..f156da9dfaf 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -179,8 +179,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( offset = (U32)(current - dictMatchIndexL - dictIndexDelta); while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */ goto _match_found; - } - } + } } if (matchIndexS > prefixLowestIndex) { /* check prefix short match */ @@ -195,16 +194,14 @@ size_t ZSTD_compressBlock_doubleFast_generic( if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) { goto _search_next_long; - } - } + } } ip += ((ip-anchor) >> kSearchStrength) + 1; continue; _search_next_long: - { - size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8); + { size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8); size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8); U32 const matchIndexL3 = hashLong[hl3]; const BYTE* matchL3 = base + matchIndexL3; @@ -230,9 +227,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta); while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */ goto _match_found; - } - } - } + } } } /* if no long +1 match, explore the short match we found */ if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) { @@ -287,8 +282,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( continue; } break; - } - } + } } if (dictMode == ZSTD_noDict) { while ( (ip <= ilimit) @@ -303,7 +297,8 @@ size_t ZSTD_compressBlock_doubleFast_generic( ip += rLength; anchor = ip; continue; /* faster when present ... (?) */ - } } } } + } } } + } /* while (ip < ilimit) */ /* save reps for next block */ rep[0] = offset_1 ? offset_1 : offsetSaved; From b31df043a05853c827b14960b017542cdfad3465 Mon Sep 17 00:00:00 2001 From: l00292966 Date: Mon, 3 Jun 2019 18:19:59 +0800 Subject: [PATCH 050/108] add cmake lz4 support add some instructions for build/cmake/README.md --- build/cmake/CMakeModules/FindLibLZ4.cmake | 49 +++++++++++++++++++++++ build/cmake/README.md | 39 ++++++++++++++++++ build/cmake/programs/CMakeLists.txt | 16 ++++++++ 3 files changed, 104 insertions(+) create mode 100644 build/cmake/CMakeModules/FindLibLZ4.cmake diff --git a/build/cmake/CMakeModules/FindLibLZ4.cmake b/build/cmake/CMakeModules/FindLibLZ4.cmake new file mode 100644 index 00000000000..d0fac06da1b --- /dev/null +++ b/build/cmake/CMakeModules/FindLibLZ4.cmake @@ -0,0 +1,49 @@ +# Find LibLZ4 +# +# Find LibLZ4 headers and library +# +# Result Variables +# +# LIBLZ4_FOUND - True if lz4 is found +# LIBLZ4_INCLUDE_DIRS - lz4 headers directories +# LIBLZ4_LIBRARIES - lz4 libraries +# LIBLZ4_VERSION_MAJOR - The major version of lz4 +# LIBLZ4_VERSION_MINOR - The minor version of lz4 +# LIBLZ4_VERSION_RELEASE - The release version of lz4 +# LIBLZ4_VERSION_STRING - version number string (e.g. 1.8.3) +# +# Hints +# +# Set ``LZ4_ROOT_DIR`` to the directory of lz4.h and lz4 library + +set(_LIBLZ4_ROOT_HINTS + ENV LZ4_ROOT_DIR) + +find_path( LIBLZ4_INCLUDE_DIR lz4.h + HINTS ${_LIBLZ4_ROOT_HINTS}) +find_library( LIBLZ4_LIBRARY NAMES lz4 liblz4 liblz4_static + HINTS ${_LIBLZ4_ROOT_HINTS}) + +if(LIBLZ4_INCLUDE_DIR) + file(STRINGS "${LIBLZ4_INCLUDE_DIR}/lz4.h" LIBLZ4_HEADER_CONTENT REGEX "#define LZ4_VERSION_[A-Z]+ +[0-9]+") + + string(REGEX REPLACE ".*#define LZ4_VERSION_MAJOR +([0-9]+).*" "\\1" LIBLZ4_VERSION_MAJOR "${LIBLZ4_HEADER_CONTENT}") + string(REGEX REPLACE ".*#define LZ4_VERSION_MINOR +([0-9]+).*" "\\1" LIBLZ4_VERSION_MINOR "${LIBLZ4_HEADER_CONTENT}") + string(REGEX REPLACE ".*#define LZ4_VERSION_RELEASE +([0-9]+).*" "\\1" LIBLZ4_VERSION_RELEASE "${LIBLZ4_HEADER_CONTENT}") + + set(LIBLZ4_VERSION_STRING "${LIBLZ4_VERSION_MAJOR}.${LIBLZ4_VERSION_MINOR}.${LIBLZ4_VERSION_RELEASE}") + unset(LIBLZ4_HEADER_CONTENT) +endif() + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibLZ4 REQUIRED_VARS LIBLZ4_INCLUDE_DIR + LIBLZ4_LIBRARY + VERSION_VAR LIBLZ4_VERSION_STRING + FAIL_MESSAGE "Could NOT find LZ4, try to set the paths to lz4.h and lz4 library in environment variable LZ4_ROOT_DIR") + +if (LIBLZ4_FOUND) + set(LIBLZ4_LIBRARIES ${LIBLZ4_LIBRARY}) + set(LIBLZ4_INCLUDE_DIRS ${LIBLZ4_INCLUDE_DIR}) +endif () + +mark_as_advanced( LIBLZ4_INCLUDE_DIR LIBLZ4_LIBRARY ) diff --git a/build/cmake/README.md b/build/cmake/README.md index 681b14cef39..854389ad834 100644 --- a/build/cmake/README.md +++ b/build/cmake/README.md @@ -5,6 +5,45 @@ use case sensitivity that matches modern (ie. cmake version 2.6 and above) conventions of using lower-case for commands, and upper-case for variables. +# How to build + +As cmake doesn't support command like `cmake clean`, it's recommanded to perform a "out of source build". +To do this, you can create a new directory and build in it: +```sh +cd build/cmake +mkdir builddir +cd builddir +cmake .. +make +``` +Then you can clean all cmake caches by simpily delete the new directory: +```sh +rm -rf build/cmake/builddir +``` + +And of course, you can directly build in build/cmake: +```sh +cd build/cmake +cmake +make +``` + +To show cmake build options, you can: +```sh +cd build/cmake/builddir +cmake -LH .. +``` + +Bool options can be set to ON/OFF with -D\[option\]=\[ON/OFF\]. You can configure cmake options like this: +```sh +cd build/cmake/builddir +cmake -DZSTD_BUILD_TESTS=ON -DZSTD_LEGACY_SUPPORT=ON .. +make +``` + +## referring +[Looking for a 'cmake clean' command to clear up CMake output](https://stackoverflow.com/questions/9680420/looking-for-a-cmake-clean-command-to-clear-up-cmake-output) + # CMake Style Recommendations ## Indent all code correctly, i.e. the body of diff --git a/build/cmake/programs/CMakeLists.txt b/build/cmake/programs/CMakeLists.txt index f6f7a3616f4..6ef68f8a7d3 100644 --- a/build/cmake/programs/CMakeLists.txt +++ b/build/cmake/programs/CMakeLists.txt @@ -83,7 +83,9 @@ endif () option(ZSTD_ZLIB_SUPPORT "ZLIB SUPPORT" OFF) option(ZSTD_LZMA_SUPPORT "LZMA SUPPORT" OFF) +option(ZSTD_LZ4_SUPPORT "LZ4 SUPPORT" OFF) +# Add gzip support if (ZSTD_ZLIB_SUPPORT) find_package(ZLIB REQUIRED) @@ -96,6 +98,7 @@ if (ZSTD_ZLIB_SUPPORT) endif () endif () +# Add lzma support if (ZSTD_LZMA_SUPPORT) find_package(LibLZMA REQUIRED) @@ -107,3 +110,16 @@ if (ZSTD_LZMA_SUPPORT) message(SEND_ERROR "lzma library is missing") endif () endif () + +# Add lz4 support +if (ZSTD_LZ4_SUPPORT) + find_package(LibLZ4 REQUIRED) + + if (LIBLZ4_FOUND) + include_directories(${LIBLZ4_INCLUDE_DIRS}) + target_link_libraries(zstd ${LIBLZ4_LIBRARIES}) + set_property(TARGET zstd APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_LZ4COMPRESS;ZSTD_LZ4DECOMPRESS") + else () + message(SEND_ERROR "lz4 library is missing") + endif () +endif () From 5029ebce2f6dbf55071e4e99579839a89b0f0a85 Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Mon, 3 Jun 2019 14:38:40 -0700 Subject: [PATCH 051/108] zstdcli : exposing cpu load indicator for each file on -vv mode --- programs/fileio.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index dc8479ab061..390a3bbe735 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1236,6 +1236,9 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, const char* srcFileName, int compressionLevel) { + UTIL_time_t const timeStart = UTIL_getTime(); + clock_t const cpuStart = clock(); + int closeDstFile = 0; int result; stat_t statbuf; @@ -1282,7 +1285,14 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, UTIL_setFileStat(dstFileName, &statbuf); } } - + { clock_t const cpuEnd = clock(); + double const cpuLoad_s = (double)(cpuEnd - cpuStart) / CLOCKS_PER_SEC; + U64 const timeLength_ns = UTIL_clockSpanNano(timeStart); + double const timeLength_s = (double)timeLength_ns / 1000000000; + double const cpuLoad_pct = (cpuLoad_s / timeLength_s) * 100; + DISPLAYLEVEL(4, "%s: Completed in %.2f sec (cpu load : %.0f%%)\n", + srcFileName, timeLength_s, cpuLoad_pct); + } return result; } @@ -1339,15 +1349,12 @@ int FIO_compressFilename(FIO_prefs_t* const prefs, const char* dictFileName, int compressionLevel, ZSTD_compressionParameters comprParams) { - clock_t const start = clock(); U64 const fileSize = UTIL_getFileSize(srcFileName); U64 const srcSize = (fileSize == UTIL_FILESIZE_UNKNOWN) ? ZSTD_CONTENTSIZE_UNKNOWN : fileSize; cRess_t const ress = FIO_createCResources(prefs, dictFileName, compressionLevel, srcSize, comprParams); int const result = FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel); - double const seconds = (double)(clock() - start) / CLOCKS_PER_SEC; - DISPLAYLEVEL(4, "Completed in %.2f sec \n", seconds); FIO_freeCResources(ress); return result; From 43d463eccb329c486a73447805536561d8680d27 Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Mon, 3 Jun 2019 17:31:14 -0700 Subject: [PATCH 052/108] zstdcli : moving start time and cpu initialization after potential prompt --- programs/fileio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 390a3bbe735..0ac0f70f955 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1236,9 +1236,6 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, const char* srcFileName, int compressionLevel) { - UTIL_time_t const timeStart = UTIL_getTime(); - clock_t const cpuStart = clock(); - int closeDstFile = 0; int result; stat_t statbuf; @@ -1262,6 +1259,9 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, transfer_permissions = 1; } + UTIL_time_t const timeStart = UTIL_getTime(); + clock_t const cpuStart = clock(); + result = FIO_compressFilename_internal(prefs, ress, dstFileName, srcFileName, compressionLevel); if (closeDstFile) { From 2841c79e87022a784aca447d95e0968fd62007fd Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Mon, 3 Jun 2019 17:36:09 -0700 Subject: [PATCH 053/108] zstdcli : fixing mixed declarations and code error --- programs/fileio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 0ac0f70f955..d1b155c2d93 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1236,6 +1236,9 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, const char* srcFileName, int compressionLevel) { + UTIL_time_t timeStart; + clock_t cpuStart; + int closeDstFile = 0; int result; stat_t statbuf; @@ -1259,8 +1262,8 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, transfer_permissions = 1; } - UTIL_time_t const timeStart = UTIL_getTime(); - clock_t const cpuStart = clock(); + timeStart = UTIL_getTime(); + cpuStart = clock(); result = FIO_compressFilename_internal(prefs, ress, dstFileName, srcFileName, compressionLevel); From 5fe974261bc240693ee3a2b8a80409ab525d761c Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Tue, 4 Jun 2019 09:04:35 -0700 Subject: [PATCH 054/108] zstdcli : moving cpu load calculation from FIO_compressFilename_dstFile to FIO_compressFilename_internal --- programs/fileio.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index d1b155c2d93..39d02a6537f 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1165,6 +1165,9 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, const char* dstFileName, const char* srcFileName, int compressionLevel) { + UTIL_time_t const timeStart = UTIL_getTime();; + clock_t const cpuStart = clock(); + U64 readsize = 0; U64 compressedfilesize = 0; U64 const fileSize = UTIL_getFileSize(srcFileName); @@ -1217,6 +1220,15 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, (unsigned long long)readsize, (unsigned long long) compressedfilesize, dstFileName); + /* Elapsed Time and CPU Load */ + { clock_t const cpuEnd = clock(); + double const cpuLoad_s = (double)(cpuEnd - cpuStart) / CLOCKS_PER_SEC; + U64 const timeLength_ns = UTIL_clockSpanNano(timeStart); + double const timeLength_s = (double)timeLength_ns / 1000000000; + double const cpuLoad_pct = (cpuLoad_s / timeLength_s) * 100; + DISPLAYLEVEL(4, "%s: Completed in %.2f sec (cpu load : %.0f%%)\n", + srcFileName, timeLength_s, cpuLoad_pct); + } return 0; } @@ -1236,9 +1248,6 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, const char* srcFileName, int compressionLevel) { - UTIL_time_t timeStart; - clock_t cpuStart; - int closeDstFile = 0; int result; stat_t statbuf; @@ -1262,9 +1271,6 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, transfer_permissions = 1; } - timeStart = UTIL_getTime(); - cpuStart = clock(); - result = FIO_compressFilename_internal(prefs, ress, dstFileName, srcFileName, compressionLevel); if (closeDstFile) { @@ -1288,14 +1294,7 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, UTIL_setFileStat(dstFileName, &statbuf); } } - { clock_t const cpuEnd = clock(); - double const cpuLoad_s = (double)(cpuEnd - cpuStart) / CLOCKS_PER_SEC; - U64 const timeLength_ns = UTIL_clockSpanNano(timeStart); - double const timeLength_s = (double)timeLength_ns / 1000000000; - double const cpuLoad_pct = (cpuLoad_s / timeLength_s) * 100; - DISPLAYLEVEL(4, "%s: Completed in %.2f sec (cpu load : %.0f%%)\n", - srcFileName, timeLength_s, cpuLoad_pct); - } + return result; } From ef2c83695540f2ba1f8133432f47ee8ed6024cd8 Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Tue, 4 Jun 2019 09:23:49 -0700 Subject: [PATCH 055/108] zstdcli : trying to fix declaration after statement --- programs/fileio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/programs/fileio.c b/programs/fileio.c index 39d02a6537f..b26e9fcf114 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1167,7 +1167,6 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, { UTIL_time_t const timeStart = UTIL_getTime();; clock_t const cpuStart = clock(); - U64 readsize = 0; U64 compressedfilesize = 0; U64 const fileSize = UTIL_getFileSize(srcFileName); From a38601f05ad72063bc1c854fcda3c953e053b54e Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Tue, 4 Jun 2019 09:25:16 -0700 Subject: [PATCH 056/108] zstdcli : remove extra semicolon --- programs/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/fileio.c b/programs/fileio.c index b26e9fcf114..3fcaf1ac247 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1165,7 +1165,7 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, const char* dstFileName, const char* srcFileName, int compressionLevel) { - UTIL_time_t const timeStart = UTIL_getTime();; + UTIL_time_t const timeStart = UTIL_getTime(); clock_t const cpuStart = clock(); U64 readsize = 0; U64 compressedfilesize = 0; From e498bb64b6d614288bb01af09964b97183593218 Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Tue, 4 Jun 2019 09:42:18 -0700 Subject: [PATCH 057/108] zstdcli : align output message with previous message --- programs/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/fileio.c b/programs/fileio.c index 3fcaf1ac247..3c45a986434 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1225,7 +1225,7 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, U64 const timeLength_ns = UTIL_clockSpanNano(timeStart); double const timeLength_s = (double)timeLength_ns / 1000000000; double const cpuLoad_pct = (cpuLoad_s / timeLength_s) * 100; - DISPLAYLEVEL(4, "%s: Completed in %.2f sec (cpu load : %.0f%%)\n", + DISPLAYLEVEL(4, "%-20s : Completed in %.2f sec (cpu load : %.0f%%)\n", srcFileName, timeLength_s, cpuLoad_pct); } return 0; From b5c98fbfd000f21f55ba7c6f60fcd2c0d6ee7852 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 4 Jun 2019 10:26:16 -0700 Subject: [PATCH 058/108] Added comments on I/O buffer sizes for streaming It seems this is still a confusing topic, as in https://github.com/klauspost/compress/issues/109 . --- doc/zstd_manual.html | 9 +++++---- lib/zstd.h | 24 ++++++++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 1e05f0cb31f..bad5f7b9703 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -18,7 +18,7 @@ zstd 1.4.0 Manual
Advanced decompression API Streaming Streaming compression - HowTo -This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and +This following is a legacy streaming API. Equivalent to: Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). @@ -592,9 +592,10 @@Streaming compression functions
typedef enum {size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */
-size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */ +size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */
-This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and
ZSTD_compressStream2(). It is redundant, but is still fully supported. +This following is a legacy streaming API.
It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). + It is redundant, but remains fully supported. Advanced parameters and dictionary compression can only be used through the new API.@@ -608,7 +609,7 @@Streaming compression functions
typedef enum {Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
NOTE: The return value is different. ZSTD_compressStream() returns a hint for the next read size (if non-zero and not an error). ZSTD_compressStream2() - returns the number of bytes left to flush (if non-zero and not an error). + returns the minimum nb of bytes left to flush (if non-zero and not an error).diff --git a/lib/zstd.h b/lib/zstd.h index 53470c18f36..3ede0441a22 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -657,12 +657,28 @@ ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, ZSTD_inBuffer* input, ZSTD_EndDirective endOp); + +/* These buffer sizes are softly recommended. + * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output. + * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(), + * reducing the amount of memory shuffling and buffering, resulting in minor performance savings. + * + * However, note that these recommendations are from the perspective of a C caller program. + * If the streaming interface is invoked from some other language, + * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo, + * a major performance rule is to reduce crossing such interface to an absolute minimum. + * It's not rare that performance ends being spent more into the interface, rather than compression itself. + * In which cases, prefer using large buffers, as large as practical, + * for both input and output, to reduce the nb of roundtrips. + */ ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */ -ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */ +ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */ + /******************************************************************************* - * This is a legacy streaming API, and can be replaced by ZSTD_CCtx_reset() and - * ZSTD_compressStream2(). It is redundant, but is still fully supported. + * This following is a legacy streaming API. + * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). + * It is redundant, but remains fully supported. * Advanced parameters and dictionary compression can only be used through the * new API. ******************************************************************************/ @@ -679,7 +695,7 @@ ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). * NOTE: The return value is different. ZSTD_compressStream() returns a hint for * the next read size (if non-zero and not an error). ZSTD_compressStream2() - * returns the number of bytes left to flush (if non-zero and not an error). + * returns the minimum nb of bytes left to flush (if non-zero and not an error). */ ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); /** Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ From b3af1873a0b50c1d3545da53786b15f998dd54f7 Mon Sep 17 00:00:00 2001 From: Yann ColletDate: Tue, 4 Jun 2019 10:35:40 -0700 Subject: [PATCH 059/108] better title formatting for html documentation must pay attention to /** and /*! patterns. --- doc/zstd_manual.html | 159 ++++++++++++++++++------------------------- lib/zstd.h | 28 ++++---- 2 files changed, 80 insertions(+), 107 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index bad5f7b9703..024c10e630f 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -10,37 +10,27 @@ zstd 1.4.0 Manual
- Introduction
- Version
-- Default constant
-- Constants
-- Simple API
-- Explicit context
-- Advanced compression API
-- Advanced decompression API
-- Streaming
-- Streaming compression - HowTo
-- This following is a legacy streaming API.
-- Equivalent to:
-- Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
-- Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush).
-- Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end).
-- Streaming decompression - HowTo
-- Simple dictionary API
-- Bulk processing dictionary API
-- Dictionary helper functions
-- Advanced dictionary and prefix API
-- ADVANCED AND EXPERIMENTAL FUNCTIONS
-- experimental API (static linking only)
-- Frame size functions
-- ZSTD_decompressBound() :
-- Memory management
-- Advanced compression functions
-- Advanced decompression functions
-- Advanced streaming functions
-- Buffer-less and synchronous inner streaming functions
-- Buffer-less streaming compression (synchronous mode)
-- Buffer-less streaming decompression (synchronous mode)
-- ZSTD_getFrameHeader() :
-- Block level API
+- Simple API
+- Explicit context
+- Advanced compression API
+- Advanced decompression API
+- Streaming
+- Streaming compression - HowTo
+- Streaming decompression - HowTo
+- Simple dictionary API
+- Bulk processing dictionary API
+- Dictionary helper functions
+- Advanced dictionary and prefix API
+- experimental API (static linking only)
+- Frame size functions
+- Memory management
+- Advanced compression functions
+- Advanced decompression functions
+- Advanced streaming functions
+- Buffer-less and synchronous inner streaming functions
+- Buffer-less streaming compression (synchronous mode)
+- Buffer-less streaming decompression (synchronous mode)
+- Block level API
Introduction
@@ -78,11 +68,7 @@zstd 1.4.0 Manual
unsigned ZSTD_versionNumber(void); /**< to check runtime library version */
-Default constant
- -Constants
- -Simple API
+Simple API
size_t ZSTD_compress( void* dst, size_t dstCapacity, const void* src, size_t srcSize, @@ -152,7 +138,7 @@Helper functions
#define ZSTD_COMPRESSBOUND(srcSize) int ZSTD_minCLevel(void);/*!< minimum negative compression level allowed */ int ZSTD_maxCLevel(void); /*!< maximum compression level available */
-Explicit context
+Explicit context
Compression context
When compressing many times, it is recommended to allocate a context just once, and re-use it for each successive compression operation. @@ -189,7 +175,7 @@Decompression context
When decompressing many times,
-Advanced compression API
+Advanced compression API
typedef enum { ZSTD_fast=1, ZSTD_dfast=2, @@ -424,7 +410,7 @@Decompression context
When decompressing many times,
-Advanced decompression API
+Advanced decompression API
typedef enum { @@ -472,7 +458,7 @@Decompression context
When decompressing many times,
-Streaming
+Streaming
typedef struct ZSTD_inBuffer_s { const void* src; /**< start of input buffer */ @@ -486,7 +472,7 @@Decompression context
When decompressing many times, size_t pos;/**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ } ZSTD_outBuffer;
-Streaming compression - HowTo
+Streaming compression - HowTo
A ZSTD_CStream object is required to track streaming operation. Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources. ZSTD_CStream objects can be reused multiple times on consecutive compression operations. @@ -594,30 +580,26 @@Streaming compression functions
typedef enum {
size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */
-This following is a legacy streaming API.
It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). - It is redundant, but remains fully supported. - Advanced parameters and dictionary compression can only be used through the - new API. -- -Equivalent to:
+size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); +/*! + * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). + * NOTE: The return value is different. ZSTD_compressStream() returns a hint for + * the next read size (if non-zero and not an error). ZSTD_compressStream2() + * returns the minimum nb of bytes left to flush (if non-zero and not an error). + */ +size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ +size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */ +size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); +- -ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); -
Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
NOTE: The return value is different. ZSTD_compressStream() returns a hint for - the next read size (if non-zero and not an error). ZSTD_compressStream2() - returns the minimum nb of bytes left to flush (if non-zero and not an error). - -- -Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush).
- -Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end).
+
-Streaming decompression - HowTo
+Streaming decompression - HowTo
A ZSTD_DStream object is required to track streaming operations. Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. ZSTD_DStream objects can be re-used multiple times. @@ -653,7 +635,7 @@Streaming decompression functions
size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
-Simple dictionary API
+Simple dictionary API
size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, @@ -679,7 +661,7 @@Streaming decompression functions
Note : When `dict == NULL || dictSize < 8` no dictionary is used.
-Bulk processing dictionary API
+Bulk processing dictionary API
ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, int compressionLevel); @@ -722,7 +704,7 @@Streaming decompression functions
Recommended when same dictionary is used multiple times.
-Dictionary helper functions
+Dictionary helper functions
unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);Provides the dictID stored within dictionary. @@ -748,7 +730,7 @@
Streaming decompression functions
When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code.
-Advanced dictionary and prefix API
+/**< Always emit uncompressed literals. */ } ZSTD_literalCompressionMode_e;Advanced dictionary and prefix API
This API allows dictionaries to be used with ZSTD_compress2(), ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and only reset with the context is reset with ZSTD_reset_parameters or @@ -866,15 +848,7 @@Streaming decompression functions
Note that object memory usage can evolve (increase or decrease) over time.
-ADVANCED AND EXPERIMENTAL FUNCTIONS
- The definitions in the following section are considered experimental. - They are provided for advanced scenarios. - They should never be used with a dynamic library, as prototypes may change in the future. - Use them only in association with static linking. - -- -experimental API (static linking only)
+experimental API (static linking only)
The following symbols and constants are not planned to join "stable API" status in the near future. They can still change in future versions. @@ -972,7 +946,7 @@Streaming decompression functions
ZSTD_lcm_uncompressed = 2,
-Frame size functions
+Frame size functions
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);`src` should point to the start of a series of ZSTD encoded and/or skippable frames @@ -997,7 +971,8 @@
Streaming decompression functions
however it does mean that all frame data must be present and valid.
-ZSTD_decompressBound() :
`src` should point to the start of a series of ZSTD encoded and/or skippable frames +unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize); ++`src` should point to the start of a series of ZSTD encoded and/or skippable frames `srcSize` must be the _exact_ size of this series (i.e. there should be a frame boundary at `src + srcSize`) @return : - upper-bound for the decompressed size of all data in all successive frames @@ -1009,7 +984,7 @@
Streaming decompression functions
note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by: upper-bound = # blocks * min(128 KB, Window_Size) -
size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. @@ -1017,7 +992,7 @@
Streaming decompression functions
or an error code (if srcSize is too small)
-Memory management
+Memory management
size_t ZSTD_estimateCCtxSize(int compressionLevel); size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); @@ -1097,7 +1072,7 @@Streaming decompression functions
-Advanced compression functions
+Advanced compression functions
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);Create a digested dictionary for compression @@ -1242,7 +1217,7 @@
Streaming decompression functions
-Advanced decompression functions
+Advanced decompression functions
unsigned ZSTD_isFrame(const void* buffer, size_t size);Tells if the content of `buffer` starts with a valid Frame Identifier. @@ -1304,7 +1279,7 @@
Streaming decompression functions
-Advanced streaming functions
Warning : most of these functions are now redundant with the Advanced API. +Advanced streaming functions
Warning : most of these functions are now redundant with the Advanced API. Once Advanced API reaches "stable" status, redundant functions will be deprecated, and then at some point removed.@@ -1433,14 +1408,14 @@Advanced Streaming decompression functions
/** */ size_t ZSTD_resetDStream(ZSTD_DStream* zds);
-Buffer-less and synchronous inner streaming functions
+Buffer-less and synchronous inner streaming functions
This is an advanced API, giving full control over buffer management, for users which need direct control over memory. But it's also a complex one, with several restrictions, documented below. Prefer normal streaming API for an easier experience.-Buffer-less streaming compression (synchronous mode)
+Buffer-less streaming compression (synchronous mode)
A ZSTD_CCtx object is required to track streaming operations. Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. ZSTD_CCtx object can be re-used multiple times within successive compression operations. @@ -1476,7 +1451,7 @@Buffer-less streaming compression functions
size_t ZS size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize);/* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
-Buffer-less streaming decompression (synchronous mode)
+Buffer-less streaming decompression (synchronous mode)
A ZSTD_DCtx object is required to track streaming operations. Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. A ZSTD_DCtx object can be re-used multiple times. @@ -1558,23 +1533,21 @@Buffer-less streaming decompression functions
typedef unsigned checksumFlag; } ZSTD_frameHeader;
-ZSTD_getFrameHeader() :
decode Frame Header, or requires larger `srcSize`. +size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +/*! ZSTD_getFrameHeader_advanced() : + * same as ZSTD_getFrameHeader(), + * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ +size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); +size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */ +- -decode Frame Header, or requires larger `srcSize`. @return : 0, `zfhPtr` is correctly filled, >0, `srcSize` is too small, value is wanted `srcSize` amount, or an error code, which can be tested using ZSTD_isError() -
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ -
-size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); -size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */ -same as ZSTD_getFrameHeader(), - with added capability to select a format (like ZSTD_f_zstd1_magicless)
typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
-Block level API
+Block level API
Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes). User will have to take in charge required information to regenerate data, such as compressed and content sizes. diff --git a/lib/zstd.h b/lib/zstd.h index 3ede0441a22..0cc72b4e4c1 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -82,16 +82,16 @@ ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library v #define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */ -/*************************************** -* Default constant -***************************************/ +/* ************************************* + * Default constant + ***************************************/ #ifndef ZSTD_CLEVEL_DEFAULT # define ZSTD_CLEVEL_DEFAULT 3 #endif -/*************************************** -* Constants -***************************************/ +/* ************************************* + * Constants + ***************************************/ /* All magic numbers are supposed read/written to/from files/memory using little-endian convention */ #define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */ @@ -675,7 +675,7 @@ ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */ -/******************************************************************************* +/* ***************************************************************************** * This following is a legacy streaming API. * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). * It is redundant, but remains fully supported. @@ -683,7 +683,7 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output * new API. ******************************************************************************/ -/** +/*! * Equivalent to: * * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); @@ -691,16 +691,16 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); */ ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); -/** +/*! * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). * NOTE: The return value is different. ZSTD_compressStream() returns a hint for * the next read size (if non-zero and not an error). ZSTD_compressStream2() * returns the minimum nb of bytes left to flush (if non-zero and not an error). */ ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); -/** Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); -/** Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */ +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */ ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); @@ -985,7 +985,7 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); #endif /* ZSTD_H_235446 */ -/**************************************************************************************** +/* ************************************************************************************** * ADVANCED AND EXPERIMENTAL FUNCTIONS **************************************************************************************** * The definitions in the following section are considered experimental. @@ -1178,7 +1178,7 @@ typedef enum { * however it does mean that all frame data must be present and valid. */ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); -/** ZSTD_decompressBound() : +/*! ZSTD_decompressBound() : * `src` should point to the start of a series of ZSTD encoded and/or skippable frames * `srcSize` must be the _exact_ size of this series * (i.e. there should be a frame boundary at `src + srcSize`) @@ -1859,7 +1859,7 @@ typedef struct { unsigned checksumFlag; } ZSTD_frameHeader; -/** ZSTD_getFrameHeader() : +/*! ZSTD_getFrameHeader() : * decode Frame Header, or requires larger `srcSize`. * @return : 0, `zfhPtr` is correctly filled, * >0, `srcSize` is too small, value is wanted `srcSize` amount, From a371df534d72454917f0d73bf94e699d8face83d Mon Sep 17 00:00:00 2001 From: Ephraim Park
Date: Tue, 4 Jun 2019 11:04:51 -0700 Subject: [PATCH 060/108] circleci : use custom docker image with installations --- .circleci/config.yml | 12 ++++-------- .circleci/images/primary/Dockerfile | 9 +++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .circleci/images/primary/Dockerfile diff --git a/.circleci/config.yml b/.circleci/config.yml index 42e4042db62..f4e479915b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,10 +24,9 @@ jobs: # TODO: Create a small custom docker image with all the dependencies we need # preinstalled to reduce installation time. docker: - - image: circleci/buildpack-deps:bionic + - image: fbopensource/zstd-circleci-primary:0.0.1 steps: - checkout - - *install-dependencies - run: name: Test command: | @@ -41,10 +40,9 @@ jobs: # the second half of the jobs are in this test short-tests-1: docker: - - image: circleci/buildpack-deps:bionic + - image: fbopensource/zstd-circleci-primary:0.0.1 steps: - checkout - - *install-dependencies - run: name: Test command: | @@ -61,12 +59,11 @@ jobs: # tagged release. publish-github-release: docker: - - image: circleci/buildpack-deps:bionic + - image: fbopensource/zstd-circleci-primary:0.0.1 environment: CIRCLE_ARTIFACTS: /tmp/circleci-artifacts steps: - checkout - - *install-dependencies - run: name: Publish command: | @@ -86,12 +83,11 @@ jobs: # This step should only be run in a cron job regression-test: docker: - - image: circleci/buildpack-deps:bionic + - image: fbopensource/zstd-circleci-primary:0.0.1 environment: CIRCLE_ARTIFACTS: /tmp/circleci-artifacts steps: - checkout - - *install-dependencies # Restore the cached resources. - restore_cache: # We try our best to bust the cache when the data changes by hashing diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile new file mode 100644 index 00000000000..dd800415252 --- /dev/null +++ b/.circleci/images/primary/Dockerfile @@ -0,0 +1,9 @@ +FROM circleci/buildpack-deps:bionic + +RUN sudo dpkg --add-architecture i386 +RUN sudo apt-get -y -qq update +RUN sudo apt-get -y install \ + gcc-multilib-powerpc-linux-gnu gcc-arm-linux-gnueabi \ + libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ + libc6-dev-ppc64-powerpc-cross zstd gzip coreutils \ + libcurl4-openssl-dev From a6a7f08eaf65eb3a03313d7b9e425298c515a87c Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Tue, 4 Jun 2019 12:18:33 -0700 Subject: [PATCH 061/108] circleci : remove install dependencies command from config.yml --- .circleci/config.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f4e479915b1..ca153d8356a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,23 +1,5 @@ version: 2 -references: - # Install the dependencies required for tests. - # Add the step "- *install-dependencies" to the beginning of your job to run - # this command. - install-dependencies: &install-dependencies - run: - name: Install dependencies - # TODO: We can split these dependencies up by job to reduce installation - # time. - command: | - sudo dpkg --add-architecture i386 - sudo apt-get -y -qq update - sudo apt-get -y install \ - gcc-multilib-powerpc-linux-gnu gcc-arm-linux-gnueabi \ - libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ - libc6-dev-ppc64-powerpc-cross zstd gzip coreutils \ - libcurl4-openssl-dev - jobs: # the first half of the jobs are in this test short-tests-0: From 3e9572bfa9c9d7db6820a0410b19a9637b2942f8 Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Tue, 4 Jun 2019 11:04:51 -0700 Subject: [PATCH 062/108] circleci : use custom docker image with installations --- .circleci/config.yml | 12 ++++-------- .circleci/images/primary/Dockerfile | 9 +++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .circleci/images/primary/Dockerfile diff --git a/.circleci/config.yml b/.circleci/config.yml index 42e4042db62..f4e479915b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,10 +24,9 @@ jobs: # TODO: Create a small custom docker image with all the dependencies we need # preinstalled to reduce installation time. docker: - - image: circleci/buildpack-deps:bionic + - image: fbopensource/zstd-circleci-primary:0.0.1 steps: - checkout - - *install-dependencies - run: name: Test command: | @@ -41,10 +40,9 @@ jobs: # the second half of the jobs are in this test short-tests-1: docker: - - image: circleci/buildpack-deps:bionic + - image: fbopensource/zstd-circleci-primary:0.0.1 steps: - checkout - - *install-dependencies - run: name: Test command: | @@ -61,12 +59,11 @@ jobs: # tagged release. publish-github-release: docker: - - image: circleci/buildpack-deps:bionic + - image: fbopensource/zstd-circleci-primary:0.0.1 environment: CIRCLE_ARTIFACTS: /tmp/circleci-artifacts steps: - checkout - - *install-dependencies - run: name: Publish command: | @@ -86,12 +83,11 @@ jobs: # This step should only be run in a cron job regression-test: docker: - - image: circleci/buildpack-deps:bionic + - image: fbopensource/zstd-circleci-primary:0.0.1 environment: CIRCLE_ARTIFACTS: /tmp/circleci-artifacts steps: - checkout - - *install-dependencies # Restore the cached resources. - restore_cache: # We try our best to bust the cache when the data changes by hashing diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile new file mode 100644 index 00000000000..dd800415252 --- /dev/null +++ b/.circleci/images/primary/Dockerfile @@ -0,0 +1,9 @@ +FROM circleci/buildpack-deps:bionic + +RUN sudo dpkg --add-architecture i386 +RUN sudo apt-get -y -qq update +RUN sudo apt-get -y install \ + gcc-multilib-powerpc-linux-gnu gcc-arm-linux-gnueabi \ + libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ + libc6-dev-ppc64-powerpc-cross zstd gzip coreutils \ + libcurl4-openssl-dev From c96535f67eda8ad34bd230335e5e013ca2a36ca6 Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Tue, 4 Jun 2019 12:18:33 -0700 Subject: [PATCH 063/108] circleci : remove install dependencies command from config.yml --- .circleci/config.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f4e479915b1..ca153d8356a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,23 +1,5 @@ version: 2 -references: - # Install the dependencies required for tests. - # Add the step "- *install-dependencies" to the beginning of your job to run - # this command. - install-dependencies: &install-dependencies - run: - name: Install dependencies - # TODO: We can split these dependencies up by job to reduce installation - # time. - command: | - sudo dpkg --add-architecture i386 - sudo apt-get -y -qq update - sudo apt-get -y install \ - gcc-multilib-powerpc-linux-gnu gcc-arm-linux-gnueabi \ - libc6-dev-armel-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ - libc6-dev-ppc64-powerpc-cross zstd gzip coreutils \ - libcurl4-openssl-dev - jobs: # the first half of the jobs are in this test short-tests-0: From f46a3603c93314fb68edd737a00f062e51207c5e Mon Sep 17 00:00:00 2001 From: Yosuke Tanigawa Date: Wed, 5 Jun 2019 09:11:21 -0700 Subject: [PATCH 064/108] Update README.md Fix minor typo in the documentation. --- programs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/README.md b/programs/README.md index afbebaa16fd..d9ef5dd2a62 100644 --- a/programs/README.md +++ b/programs/README.md @@ -37,7 +37,7 @@ There are however other Makefile targets that create different variations of CLI `.gz` support is automatically enabled when `zlib` library is detected at build time. It's possible to disable `.gz` support, by setting `HAVE_ZLIB=0`. Example : `make zstd HAVE_ZLIB=0` - It's also possible to force compilation with zlib support, `using HAVE_ZLIB=1`. + It's also possible to force compilation with zlib support, using `HAVE_ZLIB=1`. In which case, linking stage will fail if `zlib` library cannot be found. This is useful to prevent silent feature disabling. @@ -45,7 +45,7 @@ There are however other Makefile targets that create different variations of CLI This is ordered through commands `--format=xz` and `--format=lzma` respectively. Alternatively, symlinks named `xz`, `unxz`, `lzma`, or `unlzma` will mimic intended behavior. `.xz` and `.lzma` support is automatically enabled when `lzma` library is detected at build time. - It's possible to disable `.xz` and `.lzma` support, by setting `HAVE_LZMA=0` . + It's possible to disable `.xz` and `.lzma` support, by setting `HAVE_LZMA=0`. Example : `make zstd HAVE_LZMA=0` It's also possible to force compilation with lzma support, using `HAVE_LZMA=1`. In which case, linking stage will fail if `lzma` library cannot be found. From cdb9481e388139a3ca534c46f58959971f4755d4 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 5 Jun 2019 20:20:55 -0700 Subject: [PATCH 065/108] [libzstd] Optimize ZSTD_insertBt1() for repetitive data We would only skip at most 192 bytes at a time before this diff. This was added to optimize long matches and skip the middle of the match. However, it doesn't handle the case of repetitive data. This patch keeps the optimization, but also handles repetitive data by taking the max of the two return values. ``` > for n in $(seq 9); do echo strategy=$n; dd status=none if=/dev/zero bs=1024k count=1000 | command time -f %U ./zstd --zstd=strategy=$n >/dev/null; done strategy=1 0.27 strategy=2 0.23 strategy=3 0.27 strategy=4 0.43 strategy=5 0.56 strategy=6 0.43 strategy=7 0.34 strategy=8 0.34 strategy=9 0.35 ``` At level 19 with multithreading the compressed size of `silesia.tar` regresses 300 bytes, and `enwik8` regresses 100 bytes. In single threaded mode `enwik8` is also within 100 bytes, and I didn't test `silesia.tar`. Fixes Issue #1634. --- lib/compress/zstd_opt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 12b56c70def..cf46e7501b2 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -506,9 +506,11 @@ static U32 ZSTD_insertBt1( } } *smallerPtr = *largerPtr = 0; - if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */ - assert(matchEndIdx > current + 8); - return matchEndIdx - (current + 8); + { U32 positions = 0; + if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */ + assert(matchEndIdx > current + 8); + return MAX(positions, matchEndIdx - (current + 8)); + } } FORCE_INLINE_TEMPLATE From f3800ba0737709f96c349c846b754acabefd8857 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 5 Jun 2019 20:40:52 -0700 Subject: [PATCH 066/108] [regression] Update results.csv --- tests/regression/results.csv | 80 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 7ac94f207a6..a7c97d882a9 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -11,10 +11,10 @@ silesia.tar, level 6, compress silesia.tar, level 7, compress simple, 4606658 silesia.tar, level 9, compress simple, 4554098 silesia.tar, level 13, compress simple, 4491702 -silesia.tar, level 16, compress simple, 4381277 -silesia.tar, level 19, compress simple, 4281514 +silesia.tar, level 16, compress simple, 4381284 +silesia.tar, level 19, compress simple, 4281512 silesia.tar, uncompressed literals, compress simple, 4875008 -silesia.tar, uncompressed literals optimal, compress simple, 4281514 +silesia.tar, uncompressed literals optimal, compress simple, 4281512 silesia.tar, huffman literals, compress simple, 6186038 silesia, level -5, compress cctx, 6737567 silesia, level -3, compress cctx, 6444663 @@ -28,7 +28,7 @@ silesia, level 6, compress silesia, level 7, compress cctx, 4596234 silesia, level 9, compress cctx, 4543862 silesia, level 13, compress cctx, 4482073 -silesia, level 16, compress cctx, 4377391 +silesia, level 16, compress cctx, 4377389 silesia, level 19, compress cctx, 4293262 silesia, long distance mode, compress cctx, 4862377 silesia, multithreaded, compress cctx, 4862377 @@ -92,7 +92,7 @@ silesia, level 6, zstdcli, silesia, level 7, zstdcli, 4596282 silesia, level 9, zstdcli, 4543910 silesia, level 13, zstdcli, 4482121 -silesia, level 16, zstdcli, 4377439 +silesia, level 16, zstdcli, 4377437 silesia, level 19, zstdcli, 4293310 silesia, long distance mode, zstdcli, 4853437 silesia, multithreaded, zstdcli, 4862425 @@ -102,7 +102,7 @@ silesia, small hash log, zstdcli, silesia, small chain log, zstdcli, 4931141 silesia, explicit params, zstdcli, 4815380 silesia, uncompressed literals, zstdcli, 5155472 -silesia, uncompressed literals optimal, zstdcli, 4325475 +silesia, uncompressed literals optimal, zstdcli, 4325482 silesia, huffman literals, zstdcli, 5331158 silesia, multithreaded with advanced params, zstdcli, 5155472 silesia.tar, level -5, zstdcli, 6738906 @@ -117,8 +117,8 @@ silesia.tar, level 6, zstdcli, silesia.tar, level 7, zstdcli, 4608342 silesia.tar, level 9, zstdcli, 4554700 silesia.tar, level 13, zstdcli, 4491706 -silesia.tar, level 16, zstdcli, 4381281 -silesia.tar, level 19, zstdcli, 4281518 +silesia.tar, level 16, zstdcli, 4381288 +silesia.tar, level 19, zstdcli, 4281516 silesia.tar, no source size, zstdcli, 4875132 silesia.tar, long distance mode, zstdcli, 4866975 silesia.tar, multithreaded, zstdcli, 4875136 @@ -128,7 +128,7 @@ silesia.tar, small hash log, zstdcli, silesia.tar, small chain log, zstdcli, 4943259 silesia.tar, explicit params, zstdcli, 4839202 silesia.tar, uncompressed literals, zstdcli, 5158134 -silesia.tar, uncompressed literals optimal, zstdcli, 4321098 +silesia.tar, uncompressed literals optimal, zstdcli, 4321099 silesia.tar, huffman literals, zstdcli, 5347560 silesia.tar, multithreaded with advanced params, zstdcli, 5158134 github, level -5, zstdcli, 207285 @@ -182,7 +182,7 @@ silesia, level 6, advanced silesia, level 7, advanced one pass, 4596234 silesia, level 9, advanced one pass, 4543862 silesia, level 13, advanced one pass, 4482073 -silesia, level 16, advanced one pass, 4377391 +silesia, level 16, advanced one pass, 4377389 silesia, level 19, advanced one pass, 4293262 silesia, no source size, advanced one pass, 4862377 silesia, long distance mode, advanced one pass, 4853389 @@ -193,7 +193,7 @@ silesia, small hash log, advanced silesia, small chain log, advanced one pass, 4931093 silesia, explicit params, advanced one pass, 4815369 silesia, uncompressed literals, advanced one pass, 5155424 -silesia, uncompressed literals optimal, advanced one pass, 4325427 +silesia, uncompressed literals optimal, advanced one pass, 4325434 silesia, huffman literals, advanced one pass, 5326210 silesia, multithreaded with advanced params, advanced one pass, 5155424 silesia.tar, level -5, advanced one pass, 6738558 @@ -208,8 +208,8 @@ silesia.tar, level 6, advanced silesia.tar, level 7, advanced one pass, 4606658 silesia.tar, level 9, advanced one pass, 4554098 silesia.tar, level 13, advanced one pass, 4491702 -silesia.tar, level 16, advanced one pass, 4381277 -silesia.tar, level 19, advanced one pass, 4281514 +silesia.tar, level 16, advanced one pass, 4381284 +silesia.tar, level 19, advanced one pass, 4281512 silesia.tar, no source size, advanced one pass, 4875008 silesia.tar, long distance mode, advanced one pass, 4861218 silesia.tar, multithreaded, advanced one pass, 4874631 @@ -219,7 +219,7 @@ silesia.tar, small hash log, advanced silesia.tar, small chain log, advanced one pass, 4943255 silesia.tar, explicit params, advanced one pass, 4829974 silesia.tar, uncompressed literals, advanced one pass, 5157992 -silesia.tar, uncompressed literals optimal, advanced one pass, 4321094 +silesia.tar, uncompressed literals optimal, advanced one pass, 4321095 silesia.tar, huffman literals, advanced one pass, 5347283 silesia.tar, multithreaded with advanced params, advanced one pass, 5158545 github, level -5, advanced one pass, 205285 @@ -274,7 +274,7 @@ silesia, level 6, advanced silesia, level 7, advanced one pass small out, 4596234 silesia, level 9, advanced one pass small out, 4543862 silesia, level 13, advanced one pass small out, 4482073 -silesia, level 16, advanced one pass small out, 4377391 +silesia, level 16, advanced one pass small out, 4377389 silesia, level 19, advanced one pass small out, 4293262 silesia, no source size, advanced one pass small out, 4862377 silesia, long distance mode, advanced one pass small out, 4853389 @@ -285,7 +285,7 @@ silesia, small hash log, advanced silesia, small chain log, advanced one pass small out, 4931093 silesia, explicit params, advanced one pass small out, 4815369 silesia, uncompressed literals, advanced one pass small out, 5155424 -silesia, uncompressed literals optimal, advanced one pass small out, 4325427 +silesia, uncompressed literals optimal, advanced one pass small out, 4325434 silesia, huffman literals, advanced one pass small out, 5326210 silesia, multithreaded with advanced params, advanced one pass small out, 5155424 silesia.tar, level -5, advanced one pass small out, 6738558 @@ -300,8 +300,8 @@ silesia.tar, level 6, advanced silesia.tar, level 7, advanced one pass small out, 4606658 silesia.tar, level 9, advanced one pass small out, 4554098 silesia.tar, level 13, advanced one pass small out, 4491702 -silesia.tar, level 16, advanced one pass small out, 4381277 -silesia.tar, level 19, advanced one pass small out, 4281514 +silesia.tar, level 16, advanced one pass small out, 4381284 +silesia.tar, level 19, advanced one pass small out, 4281512 silesia.tar, no source size, advanced one pass small out, 4875008 silesia.tar, long distance mode, advanced one pass small out, 4861218 silesia.tar, multithreaded, advanced one pass small out, 4874631 @@ -311,7 +311,7 @@ silesia.tar, small hash log, advanced silesia.tar, small chain log, advanced one pass small out, 4943255 silesia.tar, explicit params, advanced one pass small out, 4829974 silesia.tar, uncompressed literals, advanced one pass small out, 5157992 -silesia.tar, uncompressed literals optimal, advanced one pass small out, 4321094 +silesia.tar, uncompressed literals optimal, advanced one pass small out, 4321095 silesia.tar, huffman literals, advanced one pass small out, 5347283 silesia.tar, multithreaded with advanced params, advanced one pass small out, 5158545 github, level -5, advanced one pass small out, 205285 @@ -366,7 +366,7 @@ silesia, level 6, advanced silesia, level 7, advanced streaming, 4596234 silesia, level 9, advanced streaming, 4543862 silesia, level 13, advanced streaming, 4482073 -silesia, level 16, advanced streaming, 4377391 +silesia, level 16, advanced streaming, 4377389 silesia, level 19, advanced streaming, 4293262 silesia, no source size, advanced streaming, 4862341 silesia, long distance mode, advanced streaming, 4853389 @@ -377,7 +377,7 @@ silesia, small hash log, advanced silesia, small chain log, advanced streaming, 4931093 silesia, explicit params, advanced streaming, 4815380 silesia, uncompressed literals, advanced streaming, 5155424 -silesia, uncompressed literals optimal, advanced streaming, 4325427 +silesia, uncompressed literals optimal, advanced streaming, 4325434 silesia, huffman literals, advanced streaming, 5331110 silesia, multithreaded with advanced params, advanced streaming, 5155424 silesia.tar, level -5, advanced streaming, 6982738 @@ -392,8 +392,8 @@ silesia.tar, level 6, advanced silesia.tar, level 7, advanced streaming, 4606658 silesia.tar, level 9, advanced streaming, 4554105 silesia.tar, level 13, advanced streaming, 4491703 -silesia.tar, level 16, advanced streaming, 4381277 -silesia.tar, level 19, advanced streaming, 4281514 +silesia.tar, level 16, advanced streaming, 4381284 +silesia.tar, level 19, advanced streaming, 4281512 silesia.tar, no source size, advanced streaming, 4875006 silesia.tar, long distance mode, advanced streaming, 4861218 silesia.tar, multithreaded, advanced streaming, 4875132 @@ -403,7 +403,7 @@ silesia.tar, small hash log, advanced silesia.tar, small chain log, advanced streaming, 4943260 silesia.tar, explicit params, advanced streaming, 4830002 silesia.tar, uncompressed literals, advanced streaming, 5157995 -silesia.tar, uncompressed literals optimal, advanced streaming, 4321094 +silesia.tar, uncompressed literals optimal, advanced streaming, 4321095 silesia.tar, huffman literals, advanced streaming, 5352306 silesia.tar, multithreaded with advanced params, advanced streaming, 5158130 github, level -5, advanced streaming, 205285 @@ -458,7 +458,7 @@ silesia, level 6, old stre silesia, level 7, old streaming, 4596234 silesia, level 9, old streaming, 4543862 silesia, level 13, old streaming, 4482073 -silesia, level 16, old streaming, 4377391 +silesia, level 16, old streaming, 4377389 silesia, level 19, old streaming, 4293262 silesia, no source size, old streaming, 4862341 silesia, long distance mode, old streaming, 12000408 @@ -484,8 +484,8 @@ silesia.tar, level 6, old stre silesia.tar, level 7, old streaming, 4606658 silesia.tar, level 9, old streaming, 4554105 silesia.tar, level 13, old streaming, 4491703 -silesia.tar, level 16, old streaming, 4381277 -silesia.tar, level 19, old streaming, 4281514 +silesia.tar, level 16, old streaming, 4381284 +silesia.tar, level 19, old streaming, 4281512 silesia.tar, no source size, old streaming, 4875006 silesia.tar, long distance mode, old streaming, 12022046 silesia.tar, multithreaded, old streaming, 12022046 @@ -495,7 +495,7 @@ silesia.tar, small hash log, old stre silesia.tar, small chain log, old streaming, 12022046 silesia.tar, explicit params, old streaming, 12022046 silesia.tar, uncompressed literals, old streaming, 4875010 -silesia.tar, uncompressed literals optimal, old streaming, 4281514 +silesia.tar, uncompressed literals optimal, old streaming, 4281512 silesia.tar, huffman literals, old streaming, 6190789 silesia.tar, multithreaded with advanced params, old streaming, 12022046 github, level -5, old streaming, 205285 @@ -550,7 +550,7 @@ silesia, level 6, old stre silesia, level 7, old streaming advanced, 4596234 silesia, level 9, old streaming advanced, 4543862 silesia, level 13, old streaming advanced, 4482073 -silesia, level 16, old streaming advanced, 4377391 +silesia, level 16, old streaming advanced, 4377389 silesia, level 19, old streaming advanced, 4293262 silesia, no source size, old streaming advanced, 4862341 silesia, long distance mode, old streaming advanced, 12000408 @@ -576,8 +576,8 @@ silesia.tar, level 6, old stre silesia.tar, level 7, old streaming advanced, 4606658 silesia.tar, level 9, old streaming advanced, 4554105 silesia.tar, level 13, old streaming advanced, 4491703 -silesia.tar, level 16, old streaming advanced, 4381277 -silesia.tar, level 19, old streaming advanced, 4281514 +silesia.tar, level 16, old streaming advanced, 4381284 +silesia.tar, level 19, old streaming advanced, 4281512 silesia.tar, no source size, old streaming advanced, 4875006 silesia.tar, long distance mode, old streaming advanced, 12022046 silesia.tar, multithreaded, old streaming advanced, 12022046 @@ -587,7 +587,7 @@ silesia.tar, small hash log, old stre silesia.tar, small chain log, old streaming advanced, 12022046 silesia.tar, explicit params, old streaming advanced, 12022046 silesia.tar, uncompressed literals, old streaming advanced, 4875010 -silesia.tar, uncompressed literals optimal, old streaming advanced, 4281514 +silesia.tar, uncompressed literals optimal, old streaming advanced, 4281512 silesia.tar, huffman literals, old streaming advanced, 6190789 silesia.tar, multithreaded with advanced params, old streaming advanced, 12022046 github, level -5, old streaming advanced, 205285 @@ -642,7 +642,7 @@ silesia, level 6, old stre silesia, level 7, old streaming cdcit, 4596234 silesia, level 9, old streaming cdcit, 4543862 silesia, level 13, old streaming cdcit, 4482073 -silesia, level 16, old streaming cdcit, 4377391 +silesia, level 16, old streaming cdcit, 4377389 silesia, level 19, old streaming cdcit, 4293262 silesia, no source size, old streaming cdcit, 4862341 silesia, long distance mode, old streaming cdcit, 12000408 @@ -668,8 +668,8 @@ silesia.tar, level 6, old stre silesia.tar, level 7, old streaming cdcit, 4606658 silesia.tar, level 9, old streaming cdcit, 4554105 silesia.tar, level 13, old streaming cdcit, 4491703 -silesia.tar, level 16, old streaming cdcit, 4381277 -silesia.tar, level 19, old streaming cdcit, 4281514 +silesia.tar, level 16, old streaming cdcit, 4381284 +silesia.tar, level 19, old streaming cdcit, 4281512 silesia.tar, no source size, old streaming cdcit, 4875006 silesia.tar, long distance mode, old streaming cdcit, 12022046 silesia.tar, multithreaded, old streaming cdcit, 12022046 @@ -679,7 +679,7 @@ silesia.tar, small hash log, old stre silesia.tar, small chain log, old streaming cdcit, 12022046 silesia.tar, explicit params, old streaming cdcit, 12022046 silesia.tar, uncompressed literals, old streaming cdcit, 4875010 -silesia.tar, uncompressed literals optimal, old streaming cdcit, 4281514 +silesia.tar, uncompressed literals optimal, old streaming cdcit, 4281512 silesia.tar, huffman literals, old streaming cdcit, 6190789 silesia.tar, multithreaded with advanced params, old streaming cdcit, 12022046 github, level -5, old streaming cdcit, 205285 @@ -734,7 +734,7 @@ silesia, level 6, old stre silesia, level 7, old streaming advanced cdict, 4596234 silesia, level 9, old streaming advanced cdict, 4543862 silesia, level 13, old streaming advanced cdict, 4482073 -silesia, level 16, old streaming advanced cdict, 4377391 +silesia, level 16, old streaming advanced cdict, 4377389 silesia, level 19, old streaming advanced cdict, 4293262 silesia, no source size, old streaming advanced cdict, 4862341 silesia, long distance mode, old streaming advanced cdict, 12000408 @@ -760,8 +760,8 @@ silesia.tar, level 6, old stre silesia.tar, level 7, old streaming advanced cdict, 4606658 silesia.tar, level 9, old streaming advanced cdict, 4554105 silesia.tar, level 13, old streaming advanced cdict, 4491703 -silesia.tar, level 16, old streaming advanced cdict, 4381277 -silesia.tar, level 19, old streaming advanced cdict, 4281514 +silesia.tar, level 16, old streaming advanced cdict, 4381284 +silesia.tar, level 19, old streaming advanced cdict, 4281512 silesia.tar, no source size, old streaming advanced cdict, 4875006 silesia.tar, long distance mode, old streaming advanced cdict, 12022046 silesia.tar, multithreaded, old streaming advanced cdict, 12022046 @@ -771,7 +771,7 @@ silesia.tar, small hash log, old stre silesia.tar, small chain log, old streaming advanced cdict, 12022046 silesia.tar, explicit params, old streaming advanced cdict, 12022046 silesia.tar, uncompressed literals, old streaming advanced cdict, 4875010 -silesia.tar, uncompressed literals optimal, old streaming advanced cdict, 4281514 +silesia.tar, uncompressed literals optimal, old streaming advanced cdict, 4281512 silesia.tar, huffman literals, old streaming advanced cdict, 6190789 silesia.tar, multithreaded with advanced params, old streaming advanced cdict, 12022046 github, level -5, old streaming advanced cdict, 205285 From b878bd08ddf576a58374b8347fd0b3af1f3c921d Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 7 Jun 2019 15:30:30 -0400 Subject: [PATCH 067/108] Clean Up Temp Files Produced By playTests.sh --- tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index 4ee684e0870..684d6a1df13 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -247,7 +247,7 @@ clean: $(MAKE) -C $(ZSTDDIR) clean $(MAKE) -C $(PRGDIR) clean @$(RM) -fR $(TESTARTEFACT) - @$(RM) -f core *.o tmp* result* *.gcda dictionary *.zst \ + @$(RM) -f core *.o tmp* *.tmp result* *.gcda dictionary *.zst \ $(PRGDIR)/zstd$(EXT) $(PRGDIR)/zstd32$(EXT) \ fullbench$(EXT) fullbench32$(EXT) \ fullbench-lib$(EXT) fullbench-dll$(EXT) \ From d2c48042e6d44070ae5559cb2dfacec5ea791fc0 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 7 Jun 2019 15:31:33 -0400 Subject: [PATCH 068/108] Switch Macro Guarding lstat() --- programs/util.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/programs/util.c b/programs/util.c index 7b827d4536a..6190bca5027 100644 --- a/programs/util.c +++ b/programs/util.c @@ -107,19 +107,11 @@ int UTIL_isSameFile(const char* file1, const char* file2) U32 UTIL_isLink(const char* infilename) { /* macro guards, as defined in : https://linux.die.net/man/2/lstat */ -#ifndef __STRICT_ANSI__ -#if defined(_BSD_SOURCE) \ - || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \ - || (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) \ - || (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \ - || (defined(__APPLE__) && defined(__MACH__)) \ - || defined(__OpenBSD__) \ - || defined(__FreeBSD__) +#if PLATFORM_POSIX_VERSION >= 200112L int r; stat_t statbuf; r = lstat(infilename, &statbuf); if (!r && S_ISLNK(statbuf.st_mode)) return 1; -#endif #endif (void)infilename; return 0; From 176a543dde73f82f15a9620a8a5500770c57b269 Mon Sep 17 00:00:00 2001 From: Jen Pollock Date: Fri, 7 Jun 2019 17:21:51 -0600 Subject: [PATCH 069/108] In VS2010+, turn off assembler output for libzstd & libzstd-dll, and don't export functions from libzstd --- build/VS2010/libzstd-dll/libzstd-dll.vcxproj | 2 -- build/VS2010/libzstd/libzstd.vcxproj | 10 ++++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj index 2c4f126e96a..bcde584bed8 100644 --- a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj +++ b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj @@ -209,7 +209,6 @@ false MultiThreaded ProgramDatabase -All Console @@ -234,7 +233,6 @@ProgramDatabase true true -All Console diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj index 27a4889f6c8..2bb00689edb 100644 --- a/build/VS2010/libzstd/libzstd.vcxproj +++ b/build/VS2010/libzstd/libzstd.vcxproj @@ -162,7 +162,7 @@Level4 Disabled -ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) +ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -182,7 +182,7 @@Level4 Disabled -ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) +ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -202,11 +202,10 @@MaxSpeed true true -ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) +ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) false MultiThreaded ProgramDatabase -All Console @@ -224,14 +223,13 @@MaxSpeed true true -ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) +ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) false false MultiThreaded ProgramDatabase true true -All Console From 3968160a916a759c3d3418da533e1b4f8b795343 Mon Sep 17 00:00:00 2001 From: Mike SwansonDate: Sat, 8 Jun 2019 21:54:02 -0700 Subject: [PATCH 070/108] [programs] set chmod 600 after opening destination file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This resolves a race condition where zstd or unzstd may expose read permissions beyond the original file allowed. Mode 600 is used temporarily during the compression and decompression write stage and the new file inherits the original file’s mode at the end. Fixes #1630 --- programs/fileio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/fileio.c b/programs/fileio.c index 3c45a986434..12e1537e6c0 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -566,6 +566,7 @@ static FILE* FIO_openDstFile(FIO_prefs_t* const prefs, const char* srcFileName, { FILE* const f = fopen( dstFileName, "wb" ); if (f == NULL) DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno)); + chmod(dstFileName, 00600); return f; } } From af80f6dfacafcc2c916ecd57731107221e1f9986 Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Sun, 9 Jun 2019 01:52:45 -0700 Subject: [PATCH 071/108] =?UTF-8?q?[programs]=20Don=E2=80=99t=20try=20to?= =?UTF-8?q?=20chmod=20a=20dst=20file=20if=20it=20can=E2=80=99t=20be=20open?= =?UTF-8?q?ed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Repairs an oversight in my last commit, thanks @Cyan4973 --- programs/fileio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 12e1537e6c0..fba71157591 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -564,9 +564,11 @@ static FILE* FIO_openDstFile(FIO_prefs_t* const prefs, const char* srcFileName, } } { FILE* const f = fopen( dstFileName, "wb" ); - if (f == NULL) + if (f == NULL) { DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno)); - chmod(dstFileName, 00600); + } else { + chmod(dstFileName, 00600); + } return f; } } From d8970199f8cafb1d1536dd4fbf6c5801dc772b05 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 10 Jun 2019 11:21:28 -0400 Subject: [PATCH 072/108] Add Contbuild Test for C99 Build --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0abdadb3847..3d9c9d99a89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -153,6 +153,12 @@ matrix: - make clean - make travis-install # just ensures `make install` works + - name: c99 compatibility + if: branch = master + script: + - make c99build + - make -C tests test-zstd + - name: PPC64 if: branch = master script: From 6810dd619117bab2a6852bb2ab98aab222f68133 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 10 Jun 2019 11:05:45 -0700 Subject: [PATCH 073/108] [fuzz] Remove max_len from the options --- tests/fuzz/default.options | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 tests/fuzz/default.options diff --git a/tests/fuzz/default.options b/tests/fuzz/default.options deleted file mode 100644 index 8ea8588375d..00000000000 --- a/tests/fuzz/default.options +++ /dev/null @@ -1,2 +0,0 @@ -[libfuzzer] -max_len = 8192 From a4c0c27410de75e92970b4eecfad59a8eaa57eb6 Mon Sep 17 00:00:00 2001 From: LeeYoung624 Date: Tue, 11 Jun 2019 11:29:18 +0800 Subject: [PATCH 074/108] Install zstdless & zstdgrep as 'PROGRAMS' in CMake --- build/cmake/programs/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/cmake/programs/CMakeLists.txt b/build/cmake/programs/CMakeLists.txt index f6f7a3616f4..03194fa0441 100644 --- a/build/cmake/programs/CMakeLists.txt +++ b/build/cmake/programs/CMakeLists.txt @@ -38,6 +38,8 @@ if (UNIX) add_custom_target(unzstd ALL ${CMAKE_COMMAND} -E create_symlink zstd unzstd DEPENDS zstd COMMENT "Creating unzstd symlink") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zstdcat DESTINATION "bin") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/unzstd DESTINATION "bin") + install(PROGRAMS ${PROGRAMS_DIR}/zstdgrep DESTINATION "bin") + install(PROGRAMS ${PROGRAMS_DIR}/zstdless DESTINATION "bin") add_custom_target(zstd.1 ALL ${CMAKE_COMMAND} -E copy ${PROGRAMS_DIR}/zstd.1 . From f547dca9e3155308af4cffee47f380b763623e81 Mon Sep 17 00:00:00 2001 From: Sai Charan Koduru Date: Wed, 12 Jun 2019 12:26:36 -0700 Subject: [PATCH 075/108] Remove ZSTD_DLL_EXPORT=1 for static lib As a principle, static libs should not dllexport methods, that should only be used when building DLLs. Case in point: when static libs with dllexport directives are linked into DLLs created with a .def file, the VC++ compiler exports the dllexported methods into the DLL, in addition to the exports listed in the .def file. This will result in undesired link dependencies and is not the correct thing to do. --- build/VS2010/libzstd/libzstd.vcxproj | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj index 27a4889f6c8..a5e12f1ef5a 100644 --- a/build/VS2010/libzstd/libzstd.vcxproj +++ b/build/VS2010/libzstd/libzstd.vcxproj @@ -90,31 +90,26 @@ {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} Win32Proj libzstd +libzstd_static +MultiByte +StaticLibrary $(SolutionDir)bin\$(Platform)_$(Configuration)\ $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - StaticLibrary true -MultiByte - StaticLibrary true -MultiByte - StaticLibrary false true -MultiByte - StaticLibrary false true -MultiByte @@ -134,35 +129,36 @@ true -libzstd_static $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); false true -libzstd_static $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); false false -libzstd_static $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); false + false -libzstd_static $(IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib\common;$(SolutionDir)..\..\lib\dictBuilder;$(UniversalCRT_IncludePath); false + + +$(OutDir)$(TargetName).pdb +Level4 Disabled -ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) +ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -182,7 +178,7 @@Level4 Disabled -ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) +ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -202,7 +198,7 @@MaxSpeed true true -ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) +ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) false MultiThreaded ProgramDatabase @@ -224,7 +220,7 @@MaxSpeed true true -ZSTD_DLL_EXPORT=1;ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) +ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) false false MultiThreaded From 06d5e5ff5a9d7176aed075be3a2cb6f5cece845e Mon Sep 17 00:00:00 2001 From: Nick TerrellDate: Mon, 17 Jun 2019 10:40:33 -0700 Subject: [PATCH 076/108] [regression] Update results for small wlog patch PR#1624 --- tests/regression/results.csv | 160 +++++++++++++++++------------------ 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index a7c97d882a9..7f406baa5b0 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -6,15 +6,15 @@ silesia.tar, level 0, compress silesia.tar, level 1, compress simple, 5334825 silesia.tar, level 3, compress simple, 4875008 silesia.tar, level 4, compress simple, 4813507 -silesia.tar, level 5, compress simple, 4722235 -silesia.tar, level 6, compress simple, 4672194 -silesia.tar, level 7, compress simple, 4606658 -silesia.tar, level 9, compress simple, 4554098 -silesia.tar, level 13, compress simple, 4491702 -silesia.tar, level 16, compress simple, 4381284 -silesia.tar, level 19, compress simple, 4281512 +silesia.tar, level 5, compress simple, 4722271 +silesia.tar, level 6, compress simple, 4672231 +silesia.tar, level 7, compress simple, 4606657 +silesia.tar, level 9, compress simple, 4554099 +silesia.tar, level 13, compress simple, 4491706 +silesia.tar, level 16, compress simple, 4381265 +silesia.tar, level 19, compress simple, 4281551 silesia.tar, uncompressed literals, compress simple, 4875008 -silesia.tar, uncompressed literals optimal, compress simple, 4281512 +silesia.tar, uncompressed literals optimal, compress simple, 4281551 silesia.tar, huffman literals, compress simple, 6186038 silesia, level -5, compress cctx, 6737567 silesia, level -3, compress cctx, 6444663 @@ -36,7 +36,7 @@ silesia, multithreaded long distance mode, compress silesia, small window log, compress cctx, 7115734 silesia, small hash log, compress cctx, 6554898 silesia, small chain log, compress cctx, 4931093 -silesia, explicit params, compress cctx, 4813352 +silesia, explicit params, compress cctx, 4794609 silesia, uncompressed literals, compress cctx, 4862377 silesia, uncompressed literals optimal, compress cctx, 4293262 silesia, huffman literals, compress cctx, 6178442 @@ -100,7 +100,7 @@ silesia, multithreaded long distance mode, zstdcli, silesia, small window log, zstdcli, 7126434 silesia, small hash log, zstdcli, 6554946 silesia, small chain log, zstdcli, 4931141 -silesia, explicit params, zstdcli, 4815380 +silesia, explicit params, zstdcli, 4797048 silesia, uncompressed literals, zstdcli, 5155472 silesia, uncompressed literals optimal, zstdcli, 4325482 silesia, huffman literals, zstdcli, 5331158 @@ -112,23 +112,23 @@ silesia.tar, level 0, zstdcli, silesia.tar, level 1, zstdcli, 5336255 silesia.tar, level 3, zstdcli, 4875136 silesia.tar, level 4, zstdcli, 4814531 -silesia.tar, level 5, zstdcli, 4723284 -silesia.tar, level 6, zstdcli, 4673591 -silesia.tar, level 7, zstdcli, 4608342 -silesia.tar, level 9, zstdcli, 4554700 -silesia.tar, level 13, zstdcli, 4491706 -silesia.tar, level 16, zstdcli, 4381288 -silesia.tar, level 19, zstdcli, 4281516 +silesia.tar, level 5, zstdcli, 4723312 +silesia.tar, level 6, zstdcli, 4673616 +silesia.tar, level 7, zstdcli, 4608346 +silesia.tar, level 9, zstdcli, 4554702 +silesia.tar, level 13, zstdcli, 4491710 +silesia.tar, level 16, zstdcli, 4381269 +silesia.tar, level 19, zstdcli, 4281555 silesia.tar, no source size, zstdcli, 4875132 silesia.tar, long distance mode, zstdcli, 4866975 silesia.tar, multithreaded, zstdcli, 4875136 silesia.tar, multithreaded long distance mode, zstdcli, 4866975 silesia.tar, small window log, zstdcli, 7130434 silesia.tar, small hash log, zstdcli, 6587841 -silesia.tar, small chain log, zstdcli, 4943259 -silesia.tar, explicit params, zstdcli, 4839202 +silesia.tar, small chain log, zstdcli, 4943269 +silesia.tar, explicit params, zstdcli, 4822318 silesia.tar, uncompressed literals, zstdcli, 5158134 -silesia.tar, uncompressed literals optimal, zstdcli, 4321099 +silesia.tar, uncompressed literals optimal, zstdcli, 4320914 silesia.tar, huffman literals, zstdcli, 5347560 silesia.tar, multithreaded with advanced params, zstdcli, 5158134 github, level -5, zstdcli, 207285 @@ -191,7 +191,7 @@ silesia, multithreaded long distance mode, advanced silesia, small window log, advanced one pass, 7126386 silesia, small hash log, advanced one pass, 6554898 silesia, small chain log, advanced one pass, 4931093 -silesia, explicit params, advanced one pass, 4815369 +silesia, explicit params, advanced one pass, 4797035 silesia, uncompressed literals, advanced one pass, 5155424 silesia, uncompressed literals optimal, advanced one pass, 4325434 silesia, huffman literals, advanced one pass, 5326210 @@ -203,23 +203,23 @@ silesia.tar, level 0, advanced silesia.tar, level 1, advanced one pass, 5334825 silesia.tar, level 3, advanced one pass, 4875008 silesia.tar, level 4, advanced one pass, 4813507 -silesia.tar, level 5, advanced one pass, 4722235 -silesia.tar, level 6, advanced one pass, 4672194 -silesia.tar, level 7, advanced one pass, 4606658 -silesia.tar, level 9, advanced one pass, 4554098 -silesia.tar, level 13, advanced one pass, 4491702 -silesia.tar, level 16, advanced one pass, 4381284 -silesia.tar, level 19, advanced one pass, 4281512 +silesia.tar, level 5, advanced one pass, 4722271 +silesia.tar, level 6, advanced one pass, 4672231 +silesia.tar, level 7, advanced one pass, 4606657 +silesia.tar, level 9, advanced one pass, 4554099 +silesia.tar, level 13, advanced one pass, 4491706 +silesia.tar, level 16, advanced one pass, 4381265 +silesia.tar, level 19, advanced one pass, 4281551 silesia.tar, no source size, advanced one pass, 4875008 silesia.tar, long distance mode, advanced one pass, 4861218 silesia.tar, multithreaded, advanced one pass, 4874631 silesia.tar, multithreaded long distance mode, advanced one pass, 4860683 silesia.tar, small window log, advanced one pass, 7130394 silesia.tar, small hash log, advanced one pass, 6587833 -silesia.tar, small chain log, advanced one pass, 4943255 -silesia.tar, explicit params, advanced one pass, 4829974 +silesia.tar, small chain log, advanced one pass, 4943266 +silesia.tar, explicit params, advanced one pass, 4808543 silesia.tar, uncompressed literals, advanced one pass, 5157992 -silesia.tar, uncompressed literals optimal, advanced one pass, 4321095 +silesia.tar, uncompressed literals optimal, advanced one pass, 4320910 silesia.tar, huffman literals, advanced one pass, 5347283 silesia.tar, multithreaded with advanced params, advanced one pass, 5158545 github, level -5, advanced one pass, 205285 @@ -283,7 +283,7 @@ silesia, multithreaded long distance mode, advanced silesia, small window log, advanced one pass small out, 7126386 silesia, small hash log, advanced one pass small out, 6554898 silesia, small chain log, advanced one pass small out, 4931093 -silesia, explicit params, advanced one pass small out, 4815369 +silesia, explicit params, advanced one pass small out, 4797035 silesia, uncompressed literals, advanced one pass small out, 5155424 silesia, uncompressed literals optimal, advanced one pass small out, 4325434 silesia, huffman literals, advanced one pass small out, 5326210 @@ -295,23 +295,23 @@ silesia.tar, level 0, advanced silesia.tar, level 1, advanced one pass small out, 5334825 silesia.tar, level 3, advanced one pass small out, 4875008 silesia.tar, level 4, advanced one pass small out, 4813507 -silesia.tar, level 5, advanced one pass small out, 4722235 -silesia.tar, level 6, advanced one pass small out, 4672194 -silesia.tar, level 7, advanced one pass small out, 4606658 -silesia.tar, level 9, advanced one pass small out, 4554098 -silesia.tar, level 13, advanced one pass small out, 4491702 -silesia.tar, level 16, advanced one pass small out, 4381284 -silesia.tar, level 19, advanced one pass small out, 4281512 +silesia.tar, level 5, advanced one pass small out, 4722271 +silesia.tar, level 6, advanced one pass small out, 4672231 +silesia.tar, level 7, advanced one pass small out, 4606657 +silesia.tar, level 9, advanced one pass small out, 4554099 +silesia.tar, level 13, advanced one pass small out, 4491706 +silesia.tar, level 16, advanced one pass small out, 4381265 +silesia.tar, level 19, advanced one pass small out, 4281551 silesia.tar, no source size, advanced one pass small out, 4875008 silesia.tar, long distance mode, advanced one pass small out, 4861218 silesia.tar, multithreaded, advanced one pass small out, 4874631 silesia.tar, multithreaded long distance mode, advanced one pass small out, 4860683 silesia.tar, small window log, advanced one pass small out, 7130394 silesia.tar, small hash log, advanced one pass small out, 6587833 -silesia.tar, small chain log, advanced one pass small out, 4943255 -silesia.tar, explicit params, advanced one pass small out, 4829974 +silesia.tar, small chain log, advanced one pass small out, 4943266 +silesia.tar, explicit params, advanced one pass small out, 4808543 silesia.tar, uncompressed literals, advanced one pass small out, 5157992 -silesia.tar, uncompressed literals optimal, advanced one pass small out, 4321095 +silesia.tar, uncompressed literals optimal, advanced one pass small out, 4320910 silesia.tar, huffman literals, advanced one pass small out, 5347283 silesia.tar, multithreaded with advanced params, advanced one pass small out, 5158545 github, level -5, advanced one pass small out, 205285 @@ -375,7 +375,7 @@ silesia, multithreaded long distance mode, advanced silesia, small window log, advanced streaming, 7126389 silesia, small hash log, advanced streaming, 6554898 silesia, small chain log, advanced streaming, 4931093 -silesia, explicit params, advanced streaming, 4815380 +silesia, explicit params, advanced streaming, 4797048 silesia, uncompressed literals, advanced streaming, 5155424 silesia, uncompressed literals optimal, advanced streaming, 4325434 silesia, huffman literals, advanced streaming, 5331110 @@ -387,23 +387,23 @@ silesia.tar, level 0, advanced silesia.tar, level 1, advanced streaming, 5336879 silesia.tar, level 3, advanced streaming, 4875010 silesia.tar, level 4, advanced streaming, 4813507 -silesia.tar, level 5, advanced streaming, 4722240 -silesia.tar, level 6, advanced streaming, 4672203 -silesia.tar, level 7, advanced streaming, 4606658 -silesia.tar, level 9, advanced streaming, 4554105 -silesia.tar, level 13, advanced streaming, 4491703 +silesia.tar, level 5, advanced streaming, 4722276 +silesia.tar, level 6, advanced streaming, 4672240 +silesia.tar, level 7, advanced streaming, 4606657 +silesia.tar, level 9, advanced streaming, 4554106 +silesia.tar, level 13, advanced streaming, 4491707 silesia.tar, level 16, advanced streaming, 4381284 -silesia.tar, level 19, advanced streaming, 4281512 +silesia.tar, level 19, advanced streaming, 4281511 silesia.tar, no source size, advanced streaming, 4875006 silesia.tar, long distance mode, advanced streaming, 4861218 silesia.tar, multithreaded, advanced streaming, 4875132 silesia.tar, multithreaded long distance mode, advanced streaming, 4866971 silesia.tar, small window log, advanced streaming, 7130394 silesia.tar, small hash log, advanced streaming, 6587834 -silesia.tar, small chain log, advanced streaming, 4943260 -silesia.tar, explicit params, advanced streaming, 4830002 +silesia.tar, small chain log, advanced streaming, 4943271 +silesia.tar, explicit params, advanced streaming, 4808570 silesia.tar, uncompressed literals, advanced streaming, 5157995 -silesia.tar, uncompressed literals optimal, advanced streaming, 4321095 +silesia.tar, uncompressed literals optimal, advanced streaming, 4320841 silesia.tar, huffman literals, advanced streaming, 5352306 silesia.tar, multithreaded with advanced params, advanced streaming, 5158130 github, level -5, advanced streaming, 205285 @@ -479,13 +479,13 @@ silesia.tar, level 0, old stre silesia.tar, level 1, old streaming, 5336879 silesia.tar, level 3, old streaming, 4875010 silesia.tar, level 4, old streaming, 4813507 -silesia.tar, level 5, old streaming, 4722240 -silesia.tar, level 6, old streaming, 4672203 -silesia.tar, level 7, old streaming, 4606658 -silesia.tar, level 9, old streaming, 4554105 -silesia.tar, level 13, old streaming, 4491703 +silesia.tar, level 5, old streaming, 4722276 +silesia.tar, level 6, old streaming, 4672240 +silesia.tar, level 7, old streaming, 4606657 +silesia.tar, level 9, old streaming, 4554106 +silesia.tar, level 13, old streaming, 4491707 silesia.tar, level 16, old streaming, 4381284 -silesia.tar, level 19, old streaming, 4281512 +silesia.tar, level 19, old streaming, 4281511 silesia.tar, no source size, old streaming, 4875006 silesia.tar, long distance mode, old streaming, 12022046 silesia.tar, multithreaded, old streaming, 12022046 @@ -495,7 +495,7 @@ silesia.tar, small hash log, old stre silesia.tar, small chain log, old streaming, 12022046 silesia.tar, explicit params, old streaming, 12022046 silesia.tar, uncompressed literals, old streaming, 4875010 -silesia.tar, uncompressed literals optimal, old streaming, 4281512 +silesia.tar, uncompressed literals optimal, old streaming, 4281511 silesia.tar, huffman literals, old streaming, 6190789 silesia.tar, multithreaded with advanced params, old streaming, 12022046 github, level -5, old streaming, 205285 @@ -571,13 +571,13 @@ silesia.tar, level 0, old stre silesia.tar, level 1, old streaming advanced, 5336879 silesia.tar, level 3, old streaming advanced, 4875010 silesia.tar, level 4, old streaming advanced, 4813507 -silesia.tar, level 5, old streaming advanced, 4722240 -silesia.tar, level 6, old streaming advanced, 4672203 -silesia.tar, level 7, old streaming advanced, 4606658 -silesia.tar, level 9, old streaming advanced, 4554105 -silesia.tar, level 13, old streaming advanced, 4491703 +silesia.tar, level 5, old streaming advanced, 4722276 +silesia.tar, level 6, old streaming advanced, 4672240 +silesia.tar, level 7, old streaming advanced, 4606657 +silesia.tar, level 9, old streaming advanced, 4554106 +silesia.tar, level 13, old streaming advanced, 4491707 silesia.tar, level 16, old streaming advanced, 4381284 -silesia.tar, level 19, old streaming advanced, 4281512 +silesia.tar, level 19, old streaming advanced, 4281511 silesia.tar, no source size, old streaming advanced, 4875006 silesia.tar, long distance mode, old streaming advanced, 12022046 silesia.tar, multithreaded, old streaming advanced, 12022046 @@ -587,7 +587,7 @@ silesia.tar, small hash log, old stre silesia.tar, small chain log, old streaming advanced, 12022046 silesia.tar, explicit params, old streaming advanced, 12022046 silesia.tar, uncompressed literals, old streaming advanced, 4875010 -silesia.tar, uncompressed literals optimal, old streaming advanced, 4281512 +silesia.tar, uncompressed literals optimal, old streaming advanced, 4281511 silesia.tar, huffman literals, old streaming advanced, 6190789 silesia.tar, multithreaded with advanced params, old streaming advanced, 12022046 github, level -5, old streaming advanced, 205285 @@ -663,13 +663,13 @@ silesia.tar, level 0, old stre silesia.tar, level 1, old streaming cdcit, 5336879 silesia.tar, level 3, old streaming cdcit, 4875010 silesia.tar, level 4, old streaming cdcit, 4813507 -silesia.tar, level 5, old streaming cdcit, 4722240 -silesia.tar, level 6, old streaming cdcit, 4672203 -silesia.tar, level 7, old streaming cdcit, 4606658 -silesia.tar, level 9, old streaming cdcit, 4554105 -silesia.tar, level 13, old streaming cdcit, 4491703 +silesia.tar, level 5, old streaming cdcit, 4722276 +silesia.tar, level 6, old streaming cdcit, 4672240 +silesia.tar, level 7, old streaming cdcit, 4606657 +silesia.tar, level 9, old streaming cdcit, 4554106 +silesia.tar, level 13, old streaming cdcit, 4491707 silesia.tar, level 16, old streaming cdcit, 4381284 -silesia.tar, level 19, old streaming cdcit, 4281512 +silesia.tar, level 19, old streaming cdcit, 4281511 silesia.tar, no source size, old streaming cdcit, 4875006 silesia.tar, long distance mode, old streaming cdcit, 12022046 silesia.tar, multithreaded, old streaming cdcit, 12022046 @@ -679,7 +679,7 @@ silesia.tar, small hash log, old stre silesia.tar, small chain log, old streaming cdcit, 12022046 silesia.tar, explicit params, old streaming cdcit, 12022046 silesia.tar, uncompressed literals, old streaming cdcit, 4875010 -silesia.tar, uncompressed literals optimal, old streaming cdcit, 4281512 +silesia.tar, uncompressed literals optimal, old streaming cdcit, 4281511 silesia.tar, huffman literals, old streaming cdcit, 6190789 silesia.tar, multithreaded with advanced params, old streaming cdcit, 12022046 github, level -5, old streaming cdcit, 205285 @@ -755,13 +755,13 @@ silesia.tar, level 0, old stre silesia.tar, level 1, old streaming advanced cdict, 5336879 silesia.tar, level 3, old streaming advanced cdict, 4875010 silesia.tar, level 4, old streaming advanced cdict, 4813507 -silesia.tar, level 5, old streaming advanced cdict, 4722240 -silesia.tar, level 6, old streaming advanced cdict, 4672203 -silesia.tar, level 7, old streaming advanced cdict, 4606658 -silesia.tar, level 9, old streaming advanced cdict, 4554105 -silesia.tar, level 13, old streaming advanced cdict, 4491703 +silesia.tar, level 5, old streaming advanced cdict, 4722276 +silesia.tar, level 6, old streaming advanced cdict, 4672240 +silesia.tar, level 7, old streaming advanced cdict, 4606657 +silesia.tar, level 9, old streaming advanced cdict, 4554106 +silesia.tar, level 13, old streaming advanced cdict, 4491707 silesia.tar, level 16, old streaming advanced cdict, 4381284 -silesia.tar, level 19, old streaming advanced cdict, 4281512 +silesia.tar, level 19, old streaming advanced cdict, 4281511 silesia.tar, no source size, old streaming advanced cdict, 4875006 silesia.tar, long distance mode, old streaming advanced cdict, 12022046 silesia.tar, multithreaded, old streaming advanced cdict, 12022046 @@ -771,7 +771,7 @@ silesia.tar, small hash log, old stre silesia.tar, small chain log, old streaming advanced cdict, 12022046 silesia.tar, explicit params, old streaming advanced cdict, 12022046 silesia.tar, uncompressed literals, old streaming advanced cdict, 4875010 -silesia.tar, uncompressed literals optimal, old streaming advanced cdict, 4281512 +silesia.tar, uncompressed literals optimal, old streaming advanced cdict, 4281511 silesia.tar, huffman literals, old streaming advanced cdict, 6190789 silesia.tar, multithreaded with advanced params, old streaming advanced cdict, 12022046 github, level -5, old streaming advanced cdict, 205285 From 95e2b430eac97d342f49a5e20fbe914d6a0fdc76 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 21 Jun 2019 15:22:29 -0700 Subject: [PATCH 077/108] [opt] Add asserts for corruption in ZSTD_updateTree() --- lib/compress/zstd_opt.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 39858a82845..e32e542e021 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -525,8 +525,13 @@ void ZSTD_updateTree_internal( DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)", idx, target, dictMode); - while(idx < target) - idx += ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict); + while(idx < target) { + U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict); + assert(idx < (U32)(idx + forward)); + idx += forward; + } + assert((size_t)(ip - base) <= (size_t)(U32)(-1)); + assert((size_t)(iend - base) <= (size_t)(U32)(-1)); ms->nextToUpdate = target; } From 4156060ca498673b9938a512bc84d95a8a9c74b2 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 21 Jun 2019 15:39:33 -0700 Subject: [PATCH 078/108] [zstdmt] Update assert to use ZSTD_WINDOWLOG_MAX --- lib/compress/zstdmt_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 38fbb907685..f6d1fac4274 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1197,7 +1197,7 @@ static size_t ZSTDMT_computeOverlapSize(ZSTD_CCtx_params const params) ovLog = MIN(params.cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2) - overlapRLog; } - assert(0 <= ovLog && ovLog <= 30); + assert(0 <= ovLog && ovLog <= ZSTD_WINDOWLOG_MAX); DEBUGLOG(4, "overlapLog : %i", params.overlapLog); DEBUGLOG(4, "overlap size : %i", 1 << ovLog); return (ovLog==0) ? 0 : (size_t)1 << ovLog; From 674534a700cc110b374f9c0a6c7f518e18392af2 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 21 Jun 2019 15:39:43 -0700 Subject: [PATCH 079/108] [zstd] Fix data corruption in niche use case * Extract the overflow correction into a helper function. * Load the dictionary `ZSTD_CHUNKSIZE_MAX = 512 MB` bytes at a time and overflow correct between each chunk. Data corruption could happen when all these conditions are true: * You are using multithreading mode * Your overlap size is >= 512 MB (implies window size >= 512 MB) * You are using a strategy >= ZSTD_btlazy * You are compressing more than 4 GB The problem is that when loading a large dictionary we don't do overflow correction. We can only load 512 MB at a time, and may need to do overflow correction before each chunk. --- lib/compress/zstd_compress.c | 116 ++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 56 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 77b8b9b70cf..ad4e8a40ec9 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1826,16 +1826,15 @@ static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const /*! ZSTD_reduceIndex() : * rescale all indexes to avoid future overflow (indexes are U32) */ -static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue) +static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue) { - ZSTD_matchState_t* const ms = &zc->blockState.matchState; - { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog; + { U32 const hSize = (U32)1 << params->cParams.hashLog; ZSTD_reduceTable(ms->hashTable, hSize, reducerValue); } - if (zc->appliedParams.cParams.strategy != ZSTD_fast) { - U32 const chainSize = (U32)1 << zc->appliedParams.cParams.chainLog; - if (zc->appliedParams.cParams.strategy == ZSTD_btlazy2) + if (params->cParams.strategy != ZSTD_fast) { + U32 const chainSize = (U32)1 << params->cParams.chainLog; + if (params->cParams.strategy == ZSTD_btlazy2) ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue); else ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue); @@ -2821,6 +2820,25 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, } +static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, void const* ip, void const* iend) +{ + if (ZSTD_window_needOverflowCorrection(ms->window, iend)) { + U32 const maxDist = (U32)1 << params->cParams.windowLog; + U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy); + U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); + ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); + ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30); + ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31); + ZSTD_reduceIndex(ms, params, correction); + if (ms->nextToUpdate < correction) ms->nextToUpdate = 0; + else ms->nextToUpdate -= correction; + /* invalidate dictionaries on overflow correction */ + ms->loadedDictEnd = 0; + ms->dictMatchState = NULL; + } +} + + /*! ZSTD_compress_frameChunk() : * Compress a chunk of data into one or multiple blocks. * All blocks will be terminated, all input will be consumed. @@ -2854,20 +2872,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, "not enough space to store compressed block"); if (remaining < blockSize) blockSize = remaining; - if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) { - U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy); - U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); - ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); - ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30); - ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31); - ZSTD_reduceIndex(cctx, correction); - if (ms->nextToUpdate < correction) ms->nextToUpdate = 0; - else ms->nextToUpdate -= correction; - /* invalidate dictionaries on overflow correction */ - ms->loadedDictEnd = 0; - ms->dictMatchState = NULL; - } - + ZSTD_overflowCorrectIfNeeded(ms, &cctx->appliedParams, ip, ip + blockSize); ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); /* Ensure hash/chain table insertion resumes no sooner than lowlimit */ @@ -3007,18 +3012,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, if (!frame) { /* overflow check and correction for block mode */ - if (ZSTD_window_needOverflowCorrection(ms->window, (const char*)src + srcSize)) { - U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy); - U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, 1 << cctx->appliedParams.cParams.windowLog, src); - ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); - ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30); - ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31); - ZSTD_reduceIndex(cctx, correction); - if (ms->nextToUpdate < correction) ms->nextToUpdate = 0; - else ms->nextToUpdate -= correction; - ms->loadedDictEnd = 0; - ms->dictMatchState = NULL; - } + ZSTD_overflowCorrectIfNeeded(ms, &cctx->appliedParams, src, (BYTE const*)src + srcSize); } DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize); @@ -3074,7 +3068,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, const void* src, size_t srcSize, ZSTD_dictTableLoadMethod_e dtlm) { - const BYTE* const ip = (const BYTE*) src; + const BYTE* ip = (const BYTE*) src; const BYTE* const iend = ip + srcSize; ZSTD_window_update(&ms->window, src, srcSize); @@ -3085,32 +3079,42 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, if (srcSize <= HASH_READ_SIZE) return 0; - switch(params->cParams.strategy) - { - case ZSTD_fast: - ZSTD_fillHashTable(ms, iend, dtlm); - break; - case ZSTD_dfast: - ZSTD_fillDoubleHashTable(ms, iend, dtlm); - break; + while (iend - ip > HASH_READ_SIZE) { + size_t const remaining = iend - ip; + size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX); + const BYTE* const ichunk = ip + chunk; - case ZSTD_greedy: - case ZSTD_lazy: - case ZSTD_lazy2: - if (srcSize >= HASH_READ_SIZE) - ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE); - break; + ZSTD_overflowCorrectIfNeeded(ms, params, ip, ichunk); - case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ - case ZSTD_btopt: - case ZSTD_btultra: - case ZSTD_btultra2: - if (srcSize >= HASH_READ_SIZE) - ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend); - break; + switch(params->cParams.strategy) + { + case ZSTD_fast: + ZSTD_fillHashTable(ms, ichunk, dtlm); + break; + case ZSTD_dfast: + ZSTD_fillDoubleHashTable(ms, ichunk, dtlm); + break; - default: - assert(0); /* not possible : not a valid strategy id */ + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + if (chunk >= HASH_READ_SIZE) + ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE); + break; + + case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: + if (chunk >= HASH_READ_SIZE) + ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk); + break; + + default: + assert(0); /* not possible : not a valid strategy id */ + } + + ip = ichunk; } ms->nextToUpdate = (U32)(iend - ms->window.base); From 944e2e9e121e14cffddce28a79d477e19cc8a882 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 21 Jun 2019 15:58:55 -0700 Subject: [PATCH 080/108] benchfn : added macro macro CONTROL() like assert() but cannot be disabled. proper separation of user contract errors (CONTROL()) and invariant verification (assert()). --- lib/compress/zstd_compress_internal.h | 3 +++ programs/benchfn.c | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 55304fa317f..905e7ed6dab 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -563,6 +563,9 @@ MEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64 /*-************************************* * Round buffer management ***************************************/ +#if (ZSTD_WINDOWLOG_MAX_64 > 31) +# error "ZSTD_WINDOWLOG_MAX is too large : would overflow ZSTD_CURRENT_MAX" +#endif /* Max current allowed */ #define ZSTD_CURRENT_MAX ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX)) /* Maximum chunk size before overflow correction needs to be called again */ diff --git a/programs/benchfn.c b/programs/benchfn.c index 0932d155de4..2a51a34ff11 100644 --- a/programs/benchfn.c +++ b/programs/benchfn.c @@ -15,7 +15,6 @@ ***************************************/ #include /* malloc, free */ #include /* memset */ -#undef NDEBUG /* assert must not be disabled */ #include /* assert */ #include "timefn.h" /* UTIL_time_t, UTIL_getTime */ @@ -54,6 +53,9 @@ return retValue; \ } +/* Abort execution if a condition is not met */ +#define CONTROL(c) { if (!(c)) { DEBUGOUTPUT("error: %s \n", #c); abort(); } } + /* ************************************* * Benchmarking an arbitrary function @@ -68,13 +70,13 @@ int BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome) * check outcome validity first, using BMK_isValid_runResult() */ BMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome) { - assert(outcome.error_tag_never_ever_use_directly == 0); + CONTROL(outcome.error_tag_never_ever_use_directly == 0); return outcome.internal_never_ever_use_directly; } size_t BMK_extract_errorResult(BMK_runOutcome_t outcome) { - assert(outcome.error_tag_never_ever_use_directly != 0); + CONTROL(outcome.error_tag_never_ever_use_directly != 0); return outcome.error_result_never_ever_use_directly; } From 45c9fbd6d95ce84d8359aba5c1d2ee5b1083b04e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 21 Jun 2019 16:19:21 -0700 Subject: [PATCH 081/108] prefer memset() rather than reduceIndex() when close to index range limit by disabling continue mode when index is close to limit. --- lib/compress/zstd_compress.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 77b8b9b70cf..13a9f8e98e5 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -692,13 +692,13 @@ size_t ZSTD_CCtxParams_getParameter( *value = CCtxParams->compressionLevel; break; case ZSTD_c_windowLog : - *value = CCtxParams->cParams.windowLog; + *value = (int)CCtxParams->cParams.windowLog; break; case ZSTD_c_hashLog : - *value = CCtxParams->cParams.hashLog; + *value = (int)CCtxParams->cParams.hashLog; break; case ZSTD_c_chainLog : - *value = CCtxParams->cParams.chainLog; + *value = (int)CCtxParams->cParams.chainLog; break; case ZSTD_c_searchLog : *value = CCtxParams->cParams.searchLog; @@ -1376,6 +1376,19 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, return ptr; } +/* ZSTD_index_valid_for_continue() : + * minor optimization : prefer triggering a memset() rather than reduceIndex() + * which can apparenly be measurably slow in some circumstances (reported for Visual Studio). + * Works when re-using a context for a lot of smallish inputs : + * if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN, + * memset() will be triggered before reduceIndex(). + */ +#define ZSTD_INDEXOVERFLOW_MARGIN (16 MB) +static int ZSTD_index_valid_for_continue(ZSTD_window_t w) +{ + return (size_t)(w.nextSrc - w.base) < (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN); +} + #define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */ #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 /* when workspace is continuously too large * during at least this number of times, @@ -1399,7 +1412,9 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, if (ZSTD_equivalentParams(zc->appliedParams, params, zc->inBuffSize, zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit, - zbuff, pledgedSrcSize)) { + zbuff, pledgedSrcSize) + && ZSTD_index_valid_for_continue(zc->blockState.matchState.window) + ) { DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)", zc->appliedParams.cParams.windowLog, zc->blockSize); zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */ From 8e16b872e5e8bc2fa158edd9d0a74b350280251c Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 21 Jun 2019 17:35:43 -0700 Subject: [PATCH 082/108] [tests] Add tests for big dictionaries --- tests/Makefile | 8 ++- tests/bigdict.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 tests/bigdict.c diff --git a/tests/Makefile b/tests/Makefile index 684d6a1df13..bd2f909769c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -215,6 +215,9 @@ roundTripCrash : $(ZSTD_OBJECTS) roundTripCrash.c longmatch : $(ZSTD_OBJECTS) longmatch.c $(CC) $(FLAGS) $^ -o $@$(EXT) +bigdict: $(ZSTDMT_OBJECTS) $(PRGDIR)/datagen.c bigdict.c + $(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT) + invalidDictionaries : $(ZSTD_OBJECTS) invalidDictionaries.c $(CC) $(FLAGS) $^ -o $@$(EXT) @@ -256,7 +259,7 @@ clean: zstreamtest$(EXT) zstreamtest32$(EXT) \ datagen$(EXT) paramgrill$(EXT) roundTripCrash$(EXT) longmatch$(EXT) \ symbols$(EXT) invalidDictionaries$(EXT) legacy$(EXT) poolTests$(EXT) \ - decodecorpus$(EXT) checkTag$(EXT) + decodecorpus$(EXT) checkTag$(EXT) bigdict$(EXT) @echo Cleaning completed @@ -397,6 +400,9 @@ test-zstream32: zstreamtest32 test-longmatch: longmatch $(QEMU_SYS) ./longmatch +test-bigdict: bigdict + $(QEMU_SYS) ./bigdict + test-invalidDictionaries: invalidDictionaries $(QEMU_SYS) ./invalidDictionaries diff --git a/tests/bigdict.c b/tests/bigdict.c new file mode 100644 index 00000000000..11501f6df0f --- /dev/null +++ b/tests/bigdict.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include +#include +#include +#include +#include +#include "datagen.h" +#include "mem.h" +#define ZSTD_STATIC_LINKING_ONLY +#include "zstd.h" + +static int +compress(ZSTD_CCtx* cctx, ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + void const* src, size_t srcSize, + void* roundtrip, ZSTD_EndDirective end) +{ + ZSTD_inBuffer in = {src, srcSize, 0}; + ZSTD_outBuffer out = {dst, dstCapacity, 0}; + int ended = 0; + + while (!ended && (in.pos < in.size || out.pos > 0)) { + size_t rc; + out.pos = 0; + rc = ZSTD_compressStream2(cctx, &out, &in, end); + if (ZSTD_isError(rc)) + return 1; + if (end == ZSTD_e_end && rc == 0) + ended = 1; + { + ZSTD_inBuffer rtIn = {dst, out.pos, 0}; + ZSTD_outBuffer rtOut = {roundtrip, srcSize, 0}; + rc = 1; + while (rtIn.pos < rtIn.size || rtOut.pos > 0) { + rtOut.pos = 0; + rc = ZSTD_decompressStream(dctx, &rtOut, &rtIn); + if (ZSTD_isError(rc)) { + fprintf(stderr, "Decompression error: %s\n", ZSTD_getErrorName(rc)); + return 1; + } + if (rc == 0) + break; + } + if (ended && rc != 0) { + fprintf(stderr, "Frame not finished!\n"); + return 1; + } + } + } + + return 0; +} + +int main(int argc, const char** argv) +{ + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + ZSTD_DCtx* dctx = ZSTD_createDCtx(); + const size_t dataSize = (size_t)1 << 30; + const size_t outSize = ZSTD_compressBound(dataSize); + const size_t bufferSize = (size_t)1 << 31; + char* buffer = (char*)malloc(bufferSize); + void* out = malloc(outSize); + void* roundtrip = malloc(dataSize); + (void)argc; + (void)argv; + + if (!buffer || !out || !roundtrip || !cctx || !dctx) { + fprintf(stderr, "Allocation failure\n"); + return 1; + } + + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 31))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 1))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_overlapLog, 9))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, ZSTD_btopt))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, 7))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, 7))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, 1))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, 10))) + return 1; + if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, 10))) + return 1; + + if (ZSTD_isError(ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 31))) + return 1; + + RDG_genBuffer(buffer, bufferSize, 1.0, 0.0, 0xbeefcafe); + + /* Compress 30 GB */ + { + int i; + for (i = 0; i < 10; ++i) { + fprintf(stderr, "Compressing 1 GB\n"); + if (compress(cctx, dctx, out, outSize, buffer, dataSize, roundtrip, ZSTD_e_continue)) + return 1; + } + } + fprintf(stderr, "Compressing 1 GB\n"); + if (compress(cctx, dctx, out, outSize, buffer, dataSize, roundtrip, ZSTD_e_end)) + return 1; + + fprintf(stderr, "Success!\n"); + + free(roundtrip); + free(out); + free(buffer); + ZSTD_freeDCtx(dctx); + ZSTD_freeCCtx(cctx); + return 0; +} From 621adde3b2ec07d4984f4d232e9ae2f0981ca5e1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 24 Jun 2019 14:39:29 -0700 Subject: [PATCH 083/108] changed naming to ZSTD_indexTooCloseToMax() Also : minor speed optimization : shortcut to ZSTD_reset_matchState() rather than the full reset process. It still needs to be completed with ZSTD_continueCCtx() for proper initialization. Also : changed position of LDM hash tables in the context, so that the "regular" hash tables can be at a predictable position, hence allowing the shortcut to ZSTD_reset_matchState() without complex conditions. --- lib/compress/zstd_compress.c | 59 ++++++++++++++++++++-------------- lib/compress/zstdmt_compress.c | 9 ++++-- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 13a9f8e98e5..0796963d074 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1326,15 +1326,17 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pl typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e; +typedef enum { ZSTD_resetTarget_CDict, ZSTD_resetTarget_CCtx } ZSTD_resetTarget_e; + static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, const ZSTD_compressionParameters* cParams, - ZSTD_compResetPolicy_e const crp, U32 const forCCtx) + ZSTD_compResetPolicy_e const crp, ZSTD_resetTarget_e const forWho) { size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog); size_t const hSize = ((size_t)1) << cParams->hashLog; - U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; + U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; size_t const h3Size = ((size_t)1) << hashLog3; size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); @@ -1348,7 +1350,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, ZSTD_invalidateMatchState(ms); /* opt parser space */ - if (forCCtx && (cParams->strategy >= ZSTD_btopt)) { + if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) { DEBUGLOG(4, "reserving optimal parser space"); ms->opt.litFreq = (unsigned*)ptr; ms->opt.litLengthFreq = ms->opt.litFreq + (1< (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN); } #define ZSTD_WORKSPACETOOLARGE_FACTOR 3 /* define "workspace is too large" as this number of times larger than needed */ @@ -1412,15 +1414,21 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, if (ZSTD_equivalentParams(zc->appliedParams, params, zc->inBuffSize, zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit, - zbuff, pledgedSrcSize) - && ZSTD_index_valid_for_continue(zc->blockState.matchState.window) - ) { - DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)", - zc->appliedParams.cParams.windowLog, zc->blockSize); + zbuff, pledgedSrcSize) ) { + DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> consider continue mode"); zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */ - if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION) + if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION) { + DEBUGLOG(4, "continue mode confirmed (wLog1=%u, blockSize1=%zu)", + zc->appliedParams.cParams.windowLog, zc->blockSize); + if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) { + /* prefer a reset, faster than a rescale */ + ZSTD_reset_matchState(&zc->blockState.matchState, + zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32, + ¶ms.cParams, + crp, ZSTD_resetTarget_CCtx); + } return ZSTD_continueCCtx(zc, params, pledgedSrcSize); - } } + } } } DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx"); if (params.ldmParams.enableLdm) { @@ -1463,7 +1471,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize); if (workSpaceTooSmall || workSpaceWasteful) { - DEBUGLOG(4, "Need to resize workSpaceSize from %zuKB to %zuKB", + DEBUGLOG(4, "Resize workSpaceSize from %zuKB to %zuKB", zc->workSpaceSize >> 10, neededSpace >> 10); @@ -1505,7 +1513,10 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock); - ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32; + ptr = ZSTD_reset_matchState(&zc->blockState.matchState, + zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32, + ¶ms.cParams, + crp, ZSTD_resetTarget_CCtx); /* ldm hash table */ /* initialize bucketOffsets table later for pointer alignment */ @@ -1523,8 +1534,6 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, } assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */ - ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, ¶ms.cParams, crp, /* forCCtx */ 1); - /* sequences storage */ zc->seqStore.maxNbSeq = maxNbSeq; zc->seqStore.sequencesStart = (seqDef*)ptr; @@ -3569,10 +3578,10 @@ static size_t ZSTD_initCDict_internal( /* Reset the state to no dictionary */ ZSTD_reset_compressedBlockState(&cdict->cBlockState); - { void* const end = ZSTD_reset_matchState( - &cdict->matchState, - (U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32, - &cParams, ZSTDcrp_continue, /* forCCtx */ 0); + { void* const end = ZSTD_reset_matchState(&cdict->matchState, + (U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32, + &cParams, + ZSTDcrp_continue, ZSTD_resetTarget_CDict); assert(end == (char*)cdict->workspace + cdict->workspaceSize); (void)end; } @@ -4082,7 +4091,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, case zcss_flush: DEBUGLOG(5, "flush stage"); { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; - size_t const flushed = ZSTD_limitCopy(op, oend-op, + size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op), zcs->outBuff + zcs->outBuffFlushedSize, toFlush); DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u", (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed); @@ -4276,7 +4285,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */ /* single thread mode : attempt to calculate remaining to flush more precisely */ { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE; - size_t const checksumSize = zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4; + size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4); size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize; DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush); return toFlush; diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 38fbb907685..18e9383baf1 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1129,9 +1129,14 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx) size_t const produced = ZSTD_isError(cResult) ? 0 : cResult; size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed; assert(flushed <= produced); + assert(jobPtr->consumed <= jobPtr->src.size); toFlush = produced - flushed; - if (toFlush==0 && (jobPtr->consumed >= jobPtr->src.size)) { - /* doneJobID is not-fully-flushed, but toFlush==0 : doneJobID should be compressing some more data */ + /* if toFlush==0, nothing is available to flush. + * However, jobID is expected to still be active: + * if jobID was already completed and fully flushed, + * ZSTDMT_flushProduced() should have already moved onto next job. + * Therefore, some input has not yet been consumed. */ + if (toFlush==0) { assert(jobPtr->consumed < jobPtr->src.size); } } From 734eff70b8da08aefb480b2676981b273ae1d625 Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Wed, 26 Jun 2019 16:39:00 -0700 Subject: [PATCH 084/108] enable repeat mode on rle --- tests/decodecorpus.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c index 9910d3c551a..df40862b2f5 100644 --- a/tests/decodecorpus.c +++ b/tests/decodecorpus.c @@ -840,16 +840,16 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr, { unsigned max = MaxLL; size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, WKSP, sizeof(WKSP)); /* cannot fail */ assert(!HIST_isError(mostFrequent)); - if (mostFrequent == nbSeq) { - /* do RLE if we have the chance */ - *op++ = llCodeTable[0]; - FSE_buildCTable_rle(CTable_LitLength, (BYTE)max); - LLtype = set_rle; - } else if (frame->stats.fseInit && !(RAND(seed) & 3) && + if (frame->stats.fseInit && !(RAND(seed) & 3) && isSymbolSubset(llCodeTable, nbSeq, frame->stats.litlengthSymbolSet, 35)) { /* maybe do repeat mode if we're allowed to */ LLtype = set_repeat; + } else if (mostFrequent == nbSeq) { + /* do RLE if we have the chance */ + *op++ = llCodeTable[0]; + FSE_buildCTable_rle(CTable_LitLength, (BYTE)max); + LLtype = set_rle; } else if (!(RAND(seed) & 3)) { /* maybe use the default distribution */ FSE_buildCTable_wksp(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog, scratchBuffer, sizeof(scratchBuffer)); @@ -872,14 +872,14 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr, { unsigned max = MaxOff; size_t const mostFrequent = HIST_countFast_wksp(count, &max, ofCodeTable, nbSeq, WKSP, sizeof(WKSP)); /* cannot fail */ assert(!HIST_isError(mostFrequent)); - if (mostFrequent == nbSeq) { - *op++ = ofCodeTable[0]; - FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max); - Offtype = set_rle; - } else if (frame->stats.fseInit && !(RAND(seed) & 3) && + if (frame->stats.fseInit && !(RAND(seed) & 3) && isSymbolSubset(ofCodeTable, nbSeq, frame->stats.offsetSymbolSet, 28)) { Offtype = set_repeat; + } else if (mostFrequent == nbSeq) { + *op++ = ofCodeTable[0]; + FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max); + Offtype = set_rle; } else if (!(RAND(seed) & 3)) { FSE_buildCTable_wksp(CTable_OffsetBits, OF_defaultNorm, DefaultMaxOff, OF_defaultNormLog, scratchBuffer, sizeof(scratchBuffer)); Offtype = set_basic; @@ -900,14 +900,14 @@ static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr, { unsigned max = MaxML; size_t const mostFrequent = HIST_countFast_wksp(count, &max, mlCodeTable, nbSeq, WKSP, sizeof(WKSP)); /* cannot fail */ assert(!HIST_isError(mostFrequent)); - if (mostFrequent == nbSeq) { - *op++ = *mlCodeTable; - FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max); - MLtype = set_rle; - } else if (frame->stats.fseInit && !(RAND(seed) & 3) && + if (frame->stats.fseInit && !(RAND(seed) & 3) && isSymbolSubset(mlCodeTable, nbSeq, frame->stats.matchlengthSymbolSet, 52)) { MLtype = set_repeat; + } else if (mostFrequent == nbSeq) { + *op++ = *mlCodeTable; + FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max); + MLtype = set_rle; } else if (!(RAND(seed) & 3)) { /* sometimes do default distribution */ FSE_buildCTable_wksp(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog, scratchBuffer, sizeof(scratchBuffer)); From c7c1ba3a19fea25bef9efe8dcfd82fe97fc9483a Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Wed, 26 Jun 2019 16:43:37 -0700 Subject: [PATCH 085/108] Fix a constraint stricter than the spec --- lib/decompress/zstd_decompress_block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 7707c28bb08..741784fdf9f 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -505,7 +505,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, *nbSeqPtr = nbSeq; /* FSE table descriptors */ - RETURN_ERROR_IF(ip+4 > iend, srcSize_wrong); /* minimum possible size */ + RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong); /* minimum possible size: 1 byte for symbol encoding types */ { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); From c55d2e7ba366e45ed5e3995191805695d31ffd52 Mon Sep 17 00:00:00 2001 From: Tyler-Tran <39778355+Tyler-Tran@users.noreply.github.com> Date: Thu, 27 Jun 2019 16:26:57 -0700 Subject: [PATCH 086/108] Adding shrinking flag for cover and fastcover (#1656) * Changed ERROR(GENERIC) excluding inits * editing git ignore * Edited init functions to size_t returns * moved declarations earlier * resolved issues with changes to init functions * fixed style and an error check * attempting to add tests that might trigger changes * added && die to cases expecting to fail * resolved no die on expected failed command * fixed accel to be incorrect value * Adding an automated shrinking option * Fixing build * finalizing fixes * fix? * Removing added comment in cover.h * Styling fixes * Merging with fb dev * removing megic number for default regression * Requested revisions * fixing support for fast cover * fixing casting errors * parenthesis fix * fixing some build nits * resolving travis ci syntax * might resolve all compilation issues * removed unused variable * remodeling the selectDict function * fixing bad memory access * fixing error checks * fixed erroring check in selectDict * fixing mixed declarations * modify mixed declaration * fixing nits and adding test cases * Adding requested changes + fixed bug for error checking * switched double comparison from != to < * fixed declaration typing * refactoring COVER_best_finish() and changing shrinkDict * removing the const's * modifying ZDICT_optimizeTrainFromBuffer_cover functions * fixing potential bad memcpy * fixing the error function for dict size --- lib/dictBuilder/cover.c | 145 +++++++++++++++++++++++++++++++----- lib/dictBuilder/cover.h | 41 +++++++++- lib/dictBuilder/fastcover.c | 31 ++++---- lib/dictBuilder/zdict.h | 5 ++ programs/zstdcli.c | 39 +++++++++- tests/fuzzer.c | 32 ++++++++ tests/playTests.sh | 8 ++ 7 files changed, 259 insertions(+), 42 deletions(-) diff --git a/lib/dictBuilder/cover.c b/lib/dictBuilder/cover.c index 961e1cb9d23..621996759b6 100644 --- a/lib/dictBuilder/cover.c +++ b/lib/dictBuilder/cover.c @@ -889,9 +889,11 @@ void COVER_best_start(COVER_best_t *best) { * Decrements liveJobs and signals any waiting threads if liveJobs == 0. * If this dictionary is the best so far save it and its parameters. */ -void COVER_best_finish(COVER_best_t *best, size_t compressedSize, - ZDICT_cover_params_t parameters, void *dict, - size_t dictSize) { +void COVER_best_finish(COVER_best_t *best, ZDICT_cover_params_t parameters, + COVER_dictSelection_t selection) { + void* dict = selection.dictContent; + size_t compressedSize = selection.totalCompressedSize; + size_t dictSize = selection.dictSize; if (!best) { return; } @@ -917,6 +919,9 @@ void COVER_best_finish(COVER_best_t *best, size_t compressedSize, } } /* Save the dictionary, parameters, and size */ + if (!dict) { + return; + } memcpy(best->dict, dict, dictSize); best->dictSize = dictSize; best->parameters = parameters; @@ -929,6 +934,111 @@ void COVER_best_finish(COVER_best_t *best, size_t compressedSize, } } +COVER_dictSelection_t COVER_dictSelectionError(size_t error) { + COVER_dictSelection_t selection = { NULL, 0, error }; + return selection; +} + +unsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection) { + return (ZSTD_isError(selection.totalCompressedSize) || !selection.dictContent); +} + +void COVER_dictSelectionFree(COVER_dictSelection_t selection){ + free(selection.dictContent); +} + +COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, + size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples, + size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize) { + + size_t largestDict = 0; + size_t largestCompressed = 0; + BYTE* customDictContentEnd = customDictContent + dictContentSize; + + BYTE * largestDictbuffer = (BYTE *)malloc(dictContentSize); + BYTE * candidateDictBuffer = (BYTE *)malloc(dictContentSize); + double regressionTolerance = ((double)params.shrinkDictMaxRegression / 100.0) + 1.00; + + if (!largestDictbuffer || !candidateDictBuffer) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(dictContentSize); + } + + /* Initial dictionary size and compressed size */ + memcpy(largestDictbuffer, customDictContent, dictContentSize); + dictContentSize = ZDICT_finalizeDictionary( + largestDictbuffer, dictContentSize, customDictContent, dictContentSize, + samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams); + + if (ZDICT_isError(dictContentSize)) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(dictContentSize); + } + + totalCompressedSize = COVER_checkTotalCompressedSize(params, samplesSizes, + samplesBuffer, offsets, + nbCheckSamples, nbSamples, + largestDictbuffer, dictContentSize); + + if (ZSTD_isError(totalCompressedSize)) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(totalCompressedSize); + } + + if (params.shrinkDict == 0) { + COVER_dictSelection_t selection = { largestDictbuffer, dictContentSize, totalCompressedSize }; + free(candidateDictBuffer); + return selection; + } + + largestDict = dictContentSize; + largestCompressed = totalCompressedSize; + dictContentSize = ZDICT_DICTSIZE_MIN; + + /* Largest dict is initially at least ZDICT_DICTSIZE_MIN */ + while (dictContentSize < largestDict) { + memcpy(candidateDictBuffer, largestDictbuffer, largestDict); + dictContentSize = ZDICT_finalizeDictionary( + candidateDictBuffer, dictContentSize, customDictContentEnd - dictContentSize, dictContentSize, + samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams); + + if (ZDICT_isError(dictContentSize)) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(dictContentSize); + + } + + totalCompressedSize = COVER_checkTotalCompressedSize(params, samplesSizes, + samplesBuffer, offsets, + nbCheckSamples, nbSamples, + candidateDictBuffer, dictContentSize); + + if (ZSTD_isError(totalCompressedSize)) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(totalCompressedSize); + } + + if (totalCompressedSize <= largestCompressed * regressionTolerance) { + COVER_dictSelection_t selection = { candidateDictBuffer, dictContentSize, totalCompressedSize }; + free(largestDictbuffer); + return selection; + } + dictContentSize *= 2; + } + dictContentSize = largestDict; + totalCompressedSize = largestCompressed; + { + COVER_dictSelection_t selection = { largestDictbuffer, dictContentSize, totalCompressedSize }; + free(candidateDictBuffer); + return selection; + } +} + /** * Parameters for COVER_tryParameters(). */ @@ -954,6 +1064,7 @@ static void COVER_tryParameters(void *opaque) { /* Allocate space for hash table, dict, and freqs */ COVER_map_t activeDmers; BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity); + COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC)); U32 *freqs = (U32 *)malloc(ctx->suffixSize * sizeof(U32)); if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) { DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n"); @@ -969,29 +1080,21 @@ static void COVER_tryParameters(void *opaque) { { const size_t tail = COVER_buildDictionary(ctx, freqs, &activeDmers, dict, dictBufferCapacity, parameters); - dictBufferCapacity = ZDICT_finalizeDictionary( - dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, - ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples, - parameters.zParams); - if (ZDICT_isError(dictBufferCapacity)) { - DISPLAYLEVEL(1, "Failed to finalize dictionary\n"); + selection = COVER_selectDict(dict + tail, dictBufferCapacity - tail, + ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets, + totalCompressedSize); + + if (COVER_dictSelectionIsError(selection)) { + DISPLAYLEVEL(1, "Failed to select dictionary\n"); goto _cleanup; } } - /* Check total compressed size */ - totalCompressedSize = COVER_checkTotalCompressedSize(parameters, ctx->samplesSizes, - ctx->samples, ctx->offsets, - ctx->nbTrainSamples, ctx->nbSamples, - dict, dictBufferCapacity); - _cleanup: - COVER_best_finish(data->best, totalCompressedSize, parameters, dict, - dictBufferCapacity); + free(dict); + COVER_best_finish(data->best, parameters, selection); free(data); COVER_map_destroy(&activeDmers); - if (dict) { - free(dict); - } + COVER_dictSelectionFree(selection); if (freqs) { free(freqs); } @@ -1013,6 +1116,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover( const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1); const unsigned kIterations = (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize); + const unsigned shrinkDict = 0; /* Local variables */ const int displayLevel = parameters->zParams.notificationLevel; unsigned iteration = 1; @@ -1091,6 +1195,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover( data->parameters.d = d; data->parameters.splitPoint = splitPoint; data->parameters.steps = kSteps; + data->parameters.shrinkDict = shrinkDict; data->parameters.zParams.notificationLevel = g_displayLevel; /* Check the parameters */ if (!COVER_checkParameters(data->parameters, dictBufferCapacity)) { diff --git a/lib/dictBuilder/cover.h b/lib/dictBuilder/cover.h index efb46807c78..d9e0636a659 100644 --- a/lib/dictBuilder/cover.h +++ b/lib/dictBuilder/cover.h @@ -46,6 +46,15 @@ typedef struct { U32 size; } COVER_epoch_info_t; +/** + * Struct used for the dictionary selection function. + */ +typedef struct COVER_dictSelection { + BYTE* dictContent; + size_t dictSize; + size_t totalCompressedSize; +} COVER_dictSelection_t; + /** * Computes the number of epochs and the size of each epoch. * We will make sure that each epoch gets at least 10 * k bytes. @@ -107,6 +116,32 @@ void COVER_best_start(COVER_best_t *best); * Decrements liveJobs and signals any waiting threads if liveJobs == 0. * If this dictionary is the best so far save it and its parameters. */ -void COVER_best_finish(COVER_best_t *best, size_t compressedSize, - ZDICT_cover_params_t parameters, void *dict, - size_t dictSize); +void COVER_best_finish(COVER_best_t *best, ZDICT_cover_params_t parameters, + COVER_dictSelection_t selection); +/** + * Error function for COVER_selectDict function. Checks if the return + * value is an error. + */ +unsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection); + + /** + * Error function for COVER_selectDict function. Returns a struct where + * return.totalCompressedSize is a ZSTD error. + */ +COVER_dictSelection_t COVER_dictSelectionError(size_t error); + +/** + * Always call after selectDict is called to free up used memory from + * newly created dictionary. + */ +void COVER_dictSelectionFree(COVER_dictSelection_t selection); + +/** + * Called to finalize the dictionary and select one based on whether or not + * the shrink-dict flag was enabled. If enabled the dictionary used is the + * smallest dictionary within a specified regression of the compressed size + * from the largest dictionary. + */ + COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, + size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples, + size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize); diff --git a/lib/dictBuilder/fastcover.c b/lib/dictBuilder/fastcover.c index 40131e69363..941bb5a26ae 100644 --- a/lib/dictBuilder/fastcover.c +++ b/lib/dictBuilder/fastcover.c @@ -435,7 +435,6 @@ FASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx, return tail; } - /** * Parameters for FASTCOVER_tryParameters(). */ @@ -464,6 +463,7 @@ static void FASTCOVER_tryParameters(void *opaque) U16* segmentFreqs = (U16 *)calloc(((U64)1 << ctx->f), sizeof(U16)); /* Allocate space for hash table, dict, and freqs */ BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity); + COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC)); U32 *freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32)); if (!segmentFreqs || !dict || !freqs) { DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n"); @@ -473,27 +473,24 @@ static void FASTCOVER_tryParameters(void *opaque) memcpy(freqs, ctx->freqs, ((U64)1 << ctx->f) * sizeof(U32)); /* Build the dictionary */ { const size_t tail = FASTCOVER_buildDictionary(ctx, freqs, dict, dictBufferCapacity, - parameters, segmentFreqs); + parameters, segmentFreqs); + const unsigned nbFinalizeSamples = (unsigned)(ctx->nbTrainSamples * ctx->accelParams.finalize / 100); - dictBufferCapacity = ZDICT_finalizeDictionary( - dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, - ctx->samples, ctx->samplesSizes, nbFinalizeSamples, parameters.zParams); - if (ZDICT_isError(dictBufferCapacity)) { - DISPLAYLEVEL(1, "Failed to finalize dictionary\n"); + selection = COVER_selectDict(dict + tail, dictBufferCapacity - tail, + ctx->samples, ctx->samplesSizes, nbFinalizeSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets, + totalCompressedSize); + + if (COVER_dictSelectionIsError(selection)) { + DISPLAYLEVEL(1, "Failed to select dictionary\n"); goto _cleanup; } } - /* Check total compressed size */ - totalCompressedSize = COVER_checkTotalCompressedSize(parameters, ctx->samplesSizes, - ctx->samples, ctx->offsets, - ctx->nbTrainSamples, ctx->nbSamples, - dict, dictBufferCapacity); _cleanup: - COVER_best_finish(data->best, totalCompressedSize, parameters, dict, - dictBufferCapacity); + free(dict); + COVER_best_finish(data->best, parameters, selection); free(data); free(segmentFreqs); - free(dict); + COVER_dictSelectionFree(selection); free(freqs); } @@ -508,6 +505,7 @@ FASTCOVER_convertToCoverParams(ZDICT_fastCover_params_t fastCoverParams, coverParams->nbThreads = fastCoverParams.nbThreads; coverParams->splitPoint = fastCoverParams.splitPoint; coverParams->zParams = fastCoverParams.zParams; + coverParams->shrinkDict = fastCoverParams.shrinkDict; } @@ -524,6 +522,7 @@ FASTCOVER_convertToFastCoverParams(ZDICT_cover_params_t coverParams, fastCoverParams->f = f; fastCoverParams->accel = accel; fastCoverParams->zParams = coverParams.zParams; + fastCoverParams->shrinkDict = coverParams.shrinkDict; } @@ -619,6 +618,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover( (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize); const unsigned f = parameters->f == 0 ? DEFAULT_F : parameters->f; const unsigned accel = parameters->accel == 0 ? DEFAULT_ACCEL : parameters->accel; + const unsigned shrinkDict = 0; /* Local variables */ const int displayLevel = parameters->zParams.notificationLevel; unsigned iteration = 1; @@ -703,6 +703,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover( data->parameters.d = d; data->parameters.splitPoint = splitPoint; data->parameters.steps = kSteps; + data->parameters.shrinkDict = shrinkDict; data->parameters.zParams.notificationLevel = g_displayLevel; /* Check the parameters */ if (!FASTCOVER_checkParameters(data->parameters, dictBufferCapacity, diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h index e22973173cb..37978ecdfb8 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/dictBuilder/zdict.h @@ -94,6 +94,8 @@ typedef struct { unsigned steps; /* Number of steps : Only used for optimization : 0 means default (40) : Higher means more parameters checked */ unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */ double splitPoint; /* Percentage of samples used for training: Only used for optimization : the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (1.0), 1.0 when all samples are used for both training and testing */ + unsigned shrinkDict; /* Train dictionaries to shrink in size starting from the minimum size and selects the smallest dictionary that is shrinkDictMaxRegression% worse than the largest dictionary. 0 means no shrinking and 1 means shrinking */ + unsigned shrinkDictMaxRegression; /* Sets shrinkDictMaxRegression so that a smaller dictionary can be at worse shrinkDictMaxRegression% worse than the max dict size dictionary. */ ZDICT_params_t zParams; } ZDICT_cover_params_t; @@ -105,6 +107,9 @@ typedef struct { unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */ double splitPoint; /* Percentage of samples used for training: Only used for optimization : the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (0.75), 1.0 when all samples are used for both training and testing */ unsigned accel; /* Acceleration level: constraint: 0 < accel <= 10, higher means faster and less accurate, 0 means default(1) */ + unsigned shrinkDict; /* Train dictionaries to shrink in size starting from the minimum size and selects the smallest dictionary that is shrinkDictMaxRegression% worse than the largest dictionary. 0 means no shrinking and 1 means shrinking */ + unsigned shrinkDictMaxRegression; /* Sets shrinkDictMaxRegression so that a smaller dictionary can be at worse shrinkDictMaxRegression% worse than the max dict size dictionary. */ + ZDICT_params_t zParams; } ZDICT_fastCover_params_t; diff --git a/programs/zstdcli.c b/programs/zstdcli.c index c0dd925cefa..e862d398fb3 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -179,8 +179,8 @@ static int usage_advanced(const char* programName) DISPLAY( "\n"); DISPLAY( "Dictionary builder : \n"); DISPLAY( "--train ## : create a dictionary from a training set of files \n"); - DISPLAY( "--train-cover[=k=#,d=#,steps=#,split=#] : use the cover algorithm with optional args\n"); - DISPLAY( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#] : use the fast cover algorithm with optional args\n"); + DISPLAY( "--train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args\n"); + DISPLAY( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args\n"); DISPLAY( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u)\n", g_defaultSelectivityLevel); DISPLAY( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName); DISPLAY( "--maxdict=# : limit dictionary to specified size (default: %u) \n", g_defaultMaxDictSize); @@ -299,6 +299,7 @@ static unsigned longCommandWArg(const char** stringPtr, const char* longCommand) * @return 1 means that cover parameters were correct * @return 0 in case of malformed parameters */ +static const unsigned kDefaultRegression = 1; static unsigned parseCoverParameters(const char* stringPtr, ZDICT_cover_params_t* params) { memset(params, 0, sizeof(*params)); @@ -311,10 +312,23 @@ static unsigned parseCoverParameters(const char* stringPtr, ZDICT_cover_params_t params->splitPoint = (double)splitPercentage / 100.0; if (stringPtr[0]==',') { stringPtr++; continue; } else break; } + if (longCommandWArg(&stringPtr, "shrink")) { + params->shrinkDictMaxRegression = kDefaultRegression; + params->shrinkDict = 1; + if (stringPtr[0]=='=') { + stringPtr++; + params->shrinkDictMaxRegression = readU32FromChar(&stringPtr); + } + if (stringPtr[0]==',') { + stringPtr++; + continue; + } + else break; + } return 0; } if (stringPtr[0] != 0) return 0; - DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nsteps=%u\nsplit=%u\n", params->k, params->d, params->steps, (unsigned)(params->splitPoint * 100)); + DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nsteps=%u\nsplit=%u\nshrink%u\n", params->k, params->d, params->steps, (unsigned)(params->splitPoint * 100), params->shrinkDictMaxRegression); return 1; } @@ -338,10 +352,23 @@ static unsigned parseFastCoverParameters(const char* stringPtr, ZDICT_fastCover_ params->splitPoint = (double)splitPercentage / 100.0; if (stringPtr[0]==',') { stringPtr++; continue; } else break; } + if (longCommandWArg(&stringPtr, "shrink")) { + params->shrinkDictMaxRegression = kDefaultRegression; + params->shrinkDict = 1; + if (stringPtr[0]=='=') { + stringPtr++; + params->shrinkDictMaxRegression = readU32FromChar(&stringPtr); + } + if (stringPtr[0]==',') { + stringPtr++; + continue; + } + else break; + } return 0; } if (stringPtr[0] != 0) return 0; - DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nf=%u\nsteps=%u\nsplit=%u\naccel=%u\n", params->k, params->d, params->f, params->steps, (unsigned)(params->splitPoint * 100), params->accel); + DISPLAYLEVEL(4, "cover: k=%u\nd=%u\nf=%u\nsteps=%u\nsplit=%u\naccel=%u\nshrink=%u\n", params->k, params->d, params->f, params->steps, (unsigned)(params->splitPoint * 100), params->accel, params->shrinkDictMaxRegression); return 1; } @@ -367,6 +394,8 @@ static ZDICT_cover_params_t defaultCoverParams(void) params.d = 8; params.steps = 4; params.splitPoint = 1.0; + params.shrinkDict = 0; + params.shrinkDictMaxRegression = kDefaultRegression; return params; } @@ -379,6 +408,8 @@ static ZDICT_fastCover_params_t defaultFastCoverParams(void) params.steps = 4; params.splitPoint = 0.75; /* different from default splitPoint of cover */ params.accel = DEFAULT_ACCEL; + params.shrinkDict = 0; + params.shrinkDictMaxRegression = kDefaultRegression; return params; } #endif diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 2b6bfff6a4c..f42de9ed55c 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1104,6 +1104,22 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "OK, created dictionary of size %u \n", (unsigned)dictSize); + DISPLAYLEVEL(3, "test%3i : COVER dictBuilder with shrinkDict: ", testNb++); + { U32 u; for (u=0; u Date: Thu, 27 Jun 2019 17:27:29 -0700 Subject: [PATCH 087/108] Add test case for short bistream --- tests/zstreamtest.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 55c14ad5995..c7c0fd8ff90 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -1184,6 +1184,68 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + /* Small Sequence Section bug */ + DISPLAYLEVEL(3, "test%3i : decompress blocks with small sequences section : ", testNb++); + { /* This test consists of 3 blocks. Each block has one sequence. + The sequence has literal length of 10, match length of 10 and offset of 10. + The sequence value and compression mode for the blocks are following: + The order of values are ll, ml, of. + - First block : (10, 7, 13) (rle, rle, rle) + - size of sequences section: 6 bytes (1 byte for nbSeq, 1 byte for encoding mode, 3 bytes for rle, 1 byte bitstream) + - Second block : (10, 7, 1) (repeat, repeat, rle) + - size of sequences section: 4 bytes (1 byte for nbSeq, 1 byte for encoding mode, 1 bytes for rle, 1 byte bitstream) + - Third block : (10, 7, 1) (repeat, repeat, repeat) + - size of sequences section: 3 bytes (1 byte for nbSeq, 1 byte for encoding mode, 1 byte bitstream) */ + + unsigned char compressed[] = { + 0x28, 0xb5, 0x2f, 0xfd, 0x24, 0x3c, 0x35, 0x01, 0x00, 0xf0, 0x85, 0x08, + 0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x4c, 0x6b, 0xa9, 0x8b, + 0xbc, 0xc5, 0xb6, 0xd9, 0x7f, 0x4c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, + 0x69, 0x94, 0x89, 0x1c, 0x03, 0x44, 0x0a, 0x07, 0x00, 0xb4, 0x04, 0x80, + 0x40, 0x0a, 0xa4 + }; + unsigned int compressedSize = 51; + unsigned char decompressed[] = { + 0x85, 0x08, 0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x85, 0x08, + 0xc2, 0xc4, 0x70, 0xcf, 0xd7, 0xc0, 0x96, 0x7e, 0x4c, 0x6b, 0xa9, 0x8b, + 0xbc, 0xc5, 0xb6, 0xd9, 0x7f, 0x4c, 0x4c, 0x6b, 0xa9, 0x8b, 0xbc, 0xc5, + 0xb6, 0xd9, 0x7f, 0x4c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 0x69, 0x94, + 0x89, 0x1c, 0xf1, 0x05, 0xa6, 0x54, 0xef, 0xac, 0x69, 0x94, 0x89, 0x1c + }; + unsigned int decompressedSize = 60; + + ZSTD_DStream* const zds = ZSTD_createDStream(); + if (zds==NULL) goto _output_error; + + CHECK_Z( ZSTD_initDStream(zds) ); + inBuff.src = compressed; + inBuff.size = compressedSize; + inBuff.pos = 0; + outBuff.dst = decodedBuffer; + outBuff.size = CNBufferSize; + outBuff.pos = 0; + + while (inBuff.pos < inBuff.size) { + CHECK_Z( ZSTD_decompressStream(zds, &outBuff, &inBuff) ); + } + + { XXH64_state_t xxhStateIn, xxhStateOut; + U32 checkIn, checkOut; + XXH64_reset(&xxhStateIn, 0); + XXH64_reset(&xxhStateOut, 0); + + XXH64_update(&xxhStateIn, decompressed, decompressedSize); + XXH64_update(&xxhStateOut, outBuff.dst, outBuff.pos); + + checkIn = (U32)XXH64_digest(&xxhStateIn); + checkOut = (U32)XXH64_digest(&xxhStateOut); + CHECK(checkIn != checkOut, "Checksum does not match"); + } + + ZSTD_freeDStream(zds); + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : dictionary + uncompressible block + reusing tables checks offset table validity: ", testNb++); { ZSTD_CDict* const cdict = ZSTD_createCDict_advanced( dictionary.start, dictionary.filled, From 4d156854fe97bcbb2301ee98d47705f20d636b37 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 29 Jun 2019 01:42:17 +0700 Subject: [PATCH 088/108] meson: Beautify travis config --- .travis.yml | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3d9c9d99a89..9fbe1506fe4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -190,18 +190,23 @@ matrix: compiler: clang install: - sudo apt-get install -qq liblz4-dev valgrind tree - - travis_retry curl -o ~/ninja.zip -L 'https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip' - && unzip ~/ninja.zip -d ~/.local/bin - - travis_retry curl -o ~/get-pip.py -L 'https://bootstrap.pypa.io/get-pip.py' - && python3 ~/get-pip.py --user - && pip3 install --user meson - script: - - meson setup - --buildtype=debugoptimized - -Db_lundef=false - -Dauto_features=enabled - -Dbuild_{programs,tests,contrib}=true - -Ddefault_library=both + - | + travis_retry curl -o ~/ninja.zip -L 'https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip' && + unzip ~/ninja.zip -d ~/.local/bin + - | + travis_retry curl -o ~/get-pip.py -L 'https://bootstrap.pypa.io/get-pip.py' && + python3 ~/get-pip.py --user && + pip3 install --user meson + script: + - | + meson setup \ + --buildtype=debugoptimized \ + -Db_lundef=false \ + -Dauto_features=enabled \ + -Dbuild_programs=true \ + -Dbuild_tests=true \ + -Dbuild_contrib=true \ + -Ddefault_library=both \ build/meson builddir - pushd builddir - ninja From 8e590a1af3dc970ea9b1bcfdb5a060c89088789b Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 29 Jun 2019 01:59:57 +0700 Subject: [PATCH 089/108] meson: Fix deprecated build warnings on build options Meson now reserves the `build_` prefix for options --- .travis.yml | 6 +++--- build/meson/README.md | 2 +- build/meson/meson.build | 14 +++++++------- build/meson/meson_options.txt | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9fbe1506fe4..a2c1ae15fc1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -203,9 +203,9 @@ matrix: --buildtype=debugoptimized \ -Db_lundef=false \ -Dauto_features=enabled \ - -Dbuild_programs=true \ - -Dbuild_tests=true \ - -Dbuild_contrib=true \ + -Dbin_programs=true \ + -Dbin_tests=true \ + -Dbin_contrib=true \ -Ddefault_library=both \ build/meson builddir - pushd builddir diff --git a/build/meson/README.md b/build/meson/README.md index d79ed49696f..d393a063fc0 100644 --- a/build/meson/README.md +++ b/build/meson/README.md @@ -17,7 +17,7 @@ It outputs one `libzstd`, either shared or static, depending on `cd` to this meson directory (`build/meson`) ```sh -meson --buildtype=release -Dbuild_{programs,contrib}=true builddir +meson setup -Dbin_programs=true -Dbin_contrib=true builddir cd builddir ninja # to build ninja install # to install diff --git a/build/meson/meson.build b/build/meson/meson.build index 7178403c2fc..121811e7265 100644 --- a/build/meson/meson.build +++ b/build/meson/meson.build @@ -75,9 +75,9 @@ legacy_level = get_option('legacy_level') use_backtrace = get_option('backtrace') use_static_runtime = get_option('static_runtime') -build_programs = get_option('build_programs') -build_contrib = get_option('build_contrib') -build_tests = get_option('build_tests') +bin_programs = get_option('bin_programs') +bin_contrib = get_option('bin_contrib') +bin_tests = get_option('bin_tests') feature_multi_thread = get_option('multi_thread') feature_zlib = get_option('zlib') @@ -88,7 +88,7 @@ feature_lz4 = get_option('lz4') # Dependencies # ============================================================================= -libm_dep = cc.find_library('m', required: build_tests) +libm_dep = cc.find_library('m', required: bin_tests) thread_dep = dependency('threads', required: feature_multi_thread) use_multi_thread = thread_dep.found() # Arguments in dependency should be equivalent to those passed to pkg-config @@ -133,14 +133,14 @@ endif subdir('lib') -if build_programs +if bin_programs subdir('programs') endif -if build_tests +if bin_tests subdir('tests') endif -if build_contrib +if bin_contrib subdir('contrib') endif diff --git a/build/meson/meson_options.txt b/build/meson/meson_options.txt index 349d915c7c4..90a81c53918 100644 --- a/build/meson/meson_options.txt +++ b/build/meson/meson_options.txt @@ -19,11 +19,11 @@ option('backtrace', type: 'boolean', value: false, option('static_runtime', type: 'boolean', value: false, description: 'Link to static run-time libraries on MSVC') -option('build_programs', type: 'boolean', value: true, +option('bin_programs', type: 'boolean', value: true, description: 'Enable programs build') -option('build_tests', type: 'boolean', value: false, +option('bin_tests', type: 'boolean', value: false, description: 'Enable tests build') -option('build_contrib', type: 'boolean', value: false, +option('bin_contrib', type: 'boolean', value: false, description: 'Enable contrib build') option('multi_thread', type: 'feature', value: 'enabled', From 132a1ad2915652aa86f32362c36a52e9b03fe695 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 29 Jun 2019 02:05:05 +0700 Subject: [PATCH 090/108] meson: Always build gen_html on build machine Because we use gen_html as a generator instead of a binary to run on host machine. --- build/meson/contrib/gen_html/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/build/meson/contrib/gen_html/meson.build b/build/meson/contrib/gen_html/meson.build index cabff209dc9..3f302538d8e 100644 --- a/build/meson/contrib/gen_html/meson.build +++ b/build/meson/contrib/gen_html/meson.build @@ -17,6 +17,7 @@ gen_html_includes = include_directories(join_paths(zstd_rootdir, 'programs'), gen_html = executable('gen_html', join_paths(zstd_rootdir, 'contrib/gen_html/gen_html.cpp'), include_directories: gen_html_includes, + native: true, install: false) # Update zstd manual From 28309520c007ddfcc0e578ecf459fa1a03527e74 Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Mon, 1 Jul 2019 10:17:30 -0700 Subject: [PATCH 091/108] reflect code review comments --- tests/zstreamtest.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index c7c0fd8ff90..97d4e33e150 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -1225,22 +1225,12 @@ static int basicUnitTests(U32 seed, double compressibility) outBuff.size = CNBufferSize; outBuff.pos = 0; - while (inBuff.pos < inBuff.size) { - CHECK_Z( ZSTD_decompressStream(zds, &outBuff, &inBuff) ); - } - - { XXH64_state_t xxhStateIn, xxhStateOut; - U32 checkIn, checkOut; - XXH64_reset(&xxhStateIn, 0); - XXH64_reset(&xxhStateOut, 0); - - XXH64_update(&xxhStateIn, decompressed, decompressedSize); - XXH64_update(&xxhStateOut, outBuff.dst, outBuff.pos); - - checkIn = (U32)XXH64_digest(&xxhStateIn); - checkOut = (U32)XXH64_digest(&xxhStateOut); - CHECK(checkIn != checkOut, "Checksum does not match"); - } + CHECK(ZSTD_decompressStream(zds, &outBuff, &inBuff) != 0, + "Decompress did not reach the end of frame"); + CHECK(inBuff.pos != inBuff.size, "Decompress did not fully consume input"); + CHECK(outBuff.pos != decompressedSize, "Decompressed size does not match"); + CHECK(memcmp(outBuff.dst, decompressed, decompressedSize) != 0, + "Decompressed data does not match"); ZSTD_freeDStream(zds); } From 6c92ba774e269b950e0ed13f76b68d81612f2430 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 2 Jul 2019 15:45:47 -0700 Subject: [PATCH 092/108] ZSTD_compressSequences_internal assert op <= oend (#1667) When we wrote one byte beyond the end of the buffer for RLE blocks back in 1.3.7, we would then have `op > oend`. That is a problem when we use `oend - op` for the size of the destination buffer, and allows further writes beyond the end of the buffer for the rest of the function. Lets assert that it doesn't happen. --- lib/compress/zstd_compress.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 7ebb743f347..22db875db63 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2542,6 +2542,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2; else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3; + assert(op <= oend); if (nbSeq==0) { /* Copy the old tables over as if we repeated them */ memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse)); @@ -2550,6 +2551,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, /* seqHead : flags for FSE encoding type */ seqHead = op++; + assert(op <= oend); /* convert length/distances into codes */ ZSTD_seqToCodes(seqStorePtr); @@ -2573,6 +2575,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, if (LLtype == set_compressed) lastNCount = op; op += countSize; + assert(op <= oend); } } /* build CTable for Offsets */ { unsigned max = MaxOff; @@ -2595,6 +2598,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, if (Offtype == set_compressed) lastNCount = op; op += countSize; + assert(op <= oend); } } /* build CTable for MatchLengths */ { unsigned max = MaxML; @@ -2615,6 +2619,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, if (MLtype == set_compressed) lastNCount = op; op += countSize; + assert(op <= oend); } } *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); @@ -2628,6 +2633,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, longOffsets, bmi2); FORWARD_IF_ERROR(bitstreamSize); op += bitstreamSize; + assert(op <= oend); /* zstd versions <= 1.3.4 mistakenly report corruption when * FSE_readNCount() receives a buffer < 4 bytes. * Fixed by https://github.com/facebook/zstd/pull/1146. From e962f07d19a4064ada11fdf252790bbfc8436d49 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 2 Jul 2019 22:05:07 -0700 Subject: [PATCH 093/108] [fuzz] Add a compression fuzzer with randomly sized output buffer (#1670) --- tests/fuzz/Makefile | 10 ++++++-- tests/fuzz/fuzz.py | 1 + tests/fuzz/simple_compress.c | 47 ++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/fuzz/simple_compress.c diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index c2d8e48d9c7..8bf16b1fb0e 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -72,7 +72,8 @@ FUZZ_TARGETS := \ block_decompress \ dictionary_round_trip \ dictionary_decompress \ - zstd_frame_info + zstd_frame_info \ + simple_compress all: $(FUZZ_TARGETS) @@ -103,6 +104,9 @@ dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_round_trip.o dictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_decompress.o $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@ +simple_compress: $(FUZZ_HEADERS) $(FUZZ_OBJ) simple_compress.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) simple_compress.o $(LIB_FUZZING_ENGINE) -o $@ + zstd_frame_info: $(FUZZ_HEADERS) $(FUZZ_OBJ) zstd_frame_info.o $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) zstd_frame_info.o $(LIB_FUZZING_ENGINE) -o $@ @@ -139,7 +143,9 @@ clean: @$(MAKE) -C $(ZSTDDIR) clean @$(RM) *.a *.o @$(RM) simple_round_trip stream_round_trip simple_decompress \ - stream_decompress block_decompress block_round_trip + stream_decompress block_decompress block_round_trip \ + simple_compress dictionary_round_trip dictionary_decompress \ + zstd_frame_info cleanall: @$(RM) -r Fuzzer diff --git a/tests/fuzz/fuzz.py b/tests/fuzz/fuzz.py index 489ef9f9ed1..d993209a07c 100755 --- a/tests/fuzz/fuzz.py +++ b/tests/fuzz/fuzz.py @@ -37,6 +37,7 @@ def abs_join(a, *p): 'dictionary_round_trip', 'dictionary_decompress', 'zstd_frame_info', + 'simple_compress', ] ALL_TARGETS = TARGETS + ['all'] FUZZ_RNG_SEED_SIZE = 4 diff --git a/tests/fuzz/simple_compress.c b/tests/fuzz/simple_compress.c new file mode 100644 index 00000000000..aaed4035750 --- /dev/null +++ b/tests/fuzz/simple_compress.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + */ + +/** + * This fuzz target attempts to comprss the fuzzed data with the simple + * compression function with an output buffer that may be too small to + * ensure that the compressor never crashes. + */ + +#include +#include +#include +#include "fuzz_helpers.h" +#include "zstd.h" + +static ZSTD_CCtx *cctx = NULL; + +int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) +{ + uint32_t seed = FUZZ_seed(&src, &size); + size_t const maxSize = ZSTD_compressBound(size); + int i; + if (!cctx) { + cctx = ZSTD_createCCtx(); + FUZZ_ASSERT(cctx); + } + /* Run it 10 times over 10 output sizes. Reuse the context. */ + for (i = 0; i < 10; ++i) { + int const level = (int)FUZZ_rand32(&seed, 0, 19 + 3) - 3; /* [-3, 19] */ + size_t const bufSize = FUZZ_rand32(&seed, 0, maxSize); + void* rBuf = malloc(bufSize); + FUZZ_ASSERT(rBuf); + ZSTD_compressCCtx(cctx, rBuf, bufSize, src, size, level); + free(rBuf); + } + +#ifndef STATEFUL_FUZZING + ZSTD_freeCCtx(cctx); cctx = NULL; +#endif + return 0; +} From 90077016701522259a0969f622d7d14bf1289c1f Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Mon, 24 Jun 2019 13:40:52 -0700 Subject: [PATCH 094/108] Adding targetCBlockSize param --- doc/zstd_manual.html | 2 ++ lib/compress/zstd_compress.c | 16 ++++++++++++++++ lib/compress/zstd_compress_internal.h | 3 +++ lib/zstd.h | 11 +++++++++++ programs/fileio.c | 8 ++++++++ programs/fileio.h | 1 + programs/zstdcli.c | 6 +++++- 7 files changed, 46 insertions(+), 1 deletion(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 024c10e630f..c38c1f60cc3 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -318,6 +318,7 @@ Decompression context
When decompressing many times, * ZSTD_c_forceMaxWindow * ZSTD_c_forceAttachDict * ZSTD_c_literalCompressionMode + * ZSTD_c_targetCBlockSize * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly; * also, the enums values themselves are unstable and can still change. @@ -327,6 +328,7 @@Decompression context
When decompressing many times, ZSTD_c_experimentalParam3=1000, ZSTD_c_experimentalParam4=1001, ZSTD_c_experimentalParam5=1002, + ZSTD_c_experimentalParam6=1003, } ZSTD_cParameter;
typedef struct { diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b4feaef83f7..bf173db5dd0 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -385,6 +385,11 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) bounds.upperBound = ZSTD_lcm_uncompressed; return bounds; + case ZSTD_c_targetCBlockSize: + bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN; + bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX; + return bounds; + default: { ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 }; return boundError; @@ -452,6 +457,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_ldmHashRateLog: case ZSTD_c_forceAttachDict: case ZSTD_c_literalCompressionMode: + case ZSTD_c_targetCBlockSize: default: return 0; } @@ -497,6 +503,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_ldmHashLog: case ZSTD_c_ldmMinMatch: case ZSTD_c_ldmBucketSizeLog: + case ZSTD_c_targetCBlockSize: break; default: RETURN_ERROR(parameter_unsupported); @@ -671,6 +678,12 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, CCtxParams->ldmParams.hashRateLog = value; return CCtxParams->ldmParams.hashRateLog; + case ZSTD_c_targetCBlockSize : + if (value!=0) /* 0 ==> default */ + BOUNDCHECK(ZSTD_c_targetCBlockSize, value); + CCtxParams->targetCBlockSize = value; + return CCtxParams->targetCBlockSize; + default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); } } @@ -773,6 +786,9 @@ size_t ZSTD_CCtxParams_getParameter( case ZSTD_c_ldmHashRateLog : *value = CCtxParams->ldmParams.hashRateLog; break; + case ZSTD_c_targetCBlockSize : + *value = (int)CCtxParams->targetCBlockSize; + break; default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); } return 0; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ee9d9e31a23..8a9001c413b 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -194,6 +194,9 @@ struct ZSTD_CCtx_params_s { int compressionLevel; int forceWindow; /* force back-references to respect limit of * 1<ldmMinMatch = 0; ret->ldmBucketSizeLog = FIO_LDM_PARAM_NOTSET; ret->ldmHashRateLog = FIO_LDM_PARAM_NOTSET; + ret->targetCBlockSize = 0; ret->literalCompressionMode = ZSTD_lcm_auto; return ret; } @@ -416,6 +418,10 @@ void FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable) { prefs->rsyncable = rsyncable; } +void FIO_setTargetCBlockSize(FIO_prefs_t* const prefs, size_t targetCBlockSize) { + prefs->targetCBlockSize = targetCBlockSize; +} + void FIO_setLiteralCompressionMode( FIO_prefs_t* const prefs, ZSTD_literalCompressionMode_e mode) { @@ -656,6 +662,8 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) ); /* compression level */ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) ); + /* max compressed block size */ + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetCBlockSize, (int)prefs->targetCBlockSize) ); /* long distance matching */ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, prefs->ldmFlag) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, prefs->ldmHashLog) ); diff --git a/programs/fileio.h b/programs/fileio.h index e46633752f4..311f8c0e1f0 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -71,6 +71,7 @@ void FIO_setOverlapLog(FIO_prefs_t* const prefs, int overlapLog); void FIO_setRemoveSrcFile(FIO_prefs_t* const prefs, unsigned flag); void FIO_setSparseWrite(FIO_prefs_t* const prefs, unsigned sparse); /**< 0: no sparse; 1: disable on stdout; 2: always enabled */ void FIO_setRsyncable(FIO_prefs_t* const prefs, int rsyncable); +void FIO_setTargetCBlockSize(FIO_prefs_t* const prefs, size_t targetCBlockSize); void FIO_setLiteralCompressionMode( FIO_prefs_t* const prefs, ZSTD_literalCompressionMode_e mode); diff --git a/programs/zstdcli.c b/programs/zstdcli.c index c0dd925cefa..1d2e1ec7389 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -141,6 +141,7 @@ static int usage_advanced(const char* programName) DISPLAY( "--long[=#]: enable long distance matching with given window log (default: %u)\n", g_defaultMaxWindowLog); DISPLAY( "--fast[=#]: switch to ultra fast compression level (default: %u)\n", 1); DISPLAY( "--adapt : dynamically adapt compression level to I/O conditions \n"); + DISPLAY( "--target-compressed-block-size=# : make compressed block near targeted size \n"); #ifdef ZSTD_MULTITHREAD DISPLAY( " -T# : spawns # compression threads (default: 1, 0==# cores) \n"); DISPLAY( " -B# : select size of each job (default: 0==automatic) \n"); @@ -555,6 +556,7 @@ int main(int argCount, const char* argv[]) const char* suffix = ZSTD_EXTENSION; unsigned maxDictSize = g_defaultMaxDictSize; unsigned dictID = 0; + size_t targetCBlockSize = 0; int dictCLevel = g_defaultDictCLevel; unsigned dictSelect = g_defaultSelectivityLevel; #ifdef UTIL_HAS_CREATEFILELIST @@ -711,6 +713,7 @@ int main(int argCount, const char* argv[]) if (longCommandWArg(&argument, "--maxdict=")) { maxDictSize = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--dictID=")) { dictID = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) CLEAN_RETURN(badusage(programName)); continue; } + if (longCommandWArg(&argument, "--target-compressed-block-size=")) { targetCBlockSize = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--long")) { unsigned ldmWindowLog = 0; ldmFlag = 1; @@ -1115,6 +1118,7 @@ int main(int argCount, const char* argv[]) FIO_setAdaptMin(prefs, adaptMin); FIO_setAdaptMax(prefs, adaptMax); FIO_setRsyncable(prefs, rsyncable); + FIO_setTargetCBlockSize(prefs, targetCBlockSize); FIO_setLiteralCompressionMode(prefs, literalCompressionMode); if (adaptMin > cLevel) cLevel = adaptMin; if (adaptMax < cLevel) cLevel = adaptMax; @@ -1124,7 +1128,7 @@ int main(int argCount, const char* argv[]) else operationResult = FIO_compressMultipleFilenames(prefs, filenameTable, filenameIdx, outFileName, suffix, dictFileName, cLevel, compressionParams); #else - (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; /* not used when ZSTD_NOCOMPRESS set */ + (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; /* not used when ZSTD_NOCOMPRESS set */ DISPLAY("Compression not supported \n"); #endif } else { /* decompression or test */ From f57ac7b09ef7be96b598ba905d220214b8d63d4f Mon Sep 17 00:00:00 2001 From: Ephraim Park Date: Mon, 24 Jun 2019 15:26:07 -0700 Subject: [PATCH 095/108] Factor out the logic to build sequences --- lib/compress/zstd_compress.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index bf173db5dd0..2a8d80b994b 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2732,30 +2732,24 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr) ssPtr->longLengthID = 0; } -static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize) +typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e; + +static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) { ZSTD_matchState_t* const ms = &zc->blockState.matchState; - size_t cSize; - DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", - (unsigned)dstCapacity, (unsigned)ms->window.dictLimit, (unsigned)ms->nextToUpdate); + DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize); assert(srcSize <= ZSTD_BLOCKSIZE_MAX); - /* Assert that we have correctly flushed the ctx params into the ms's copy */ ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams); - if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) { ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch); - cSize = 0; - goto out; /* don't even attempt compression below a certain srcSize */ + return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */ } ZSTD_resetSeqStore(&(zc->seqStore)); /* required for optimal parser to read stats from dictionary */ ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; /* tell the optimal parser how we expect to compress literals */ ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode; - /* a gap between an attached dict and the current window is not safe, * they must remain adjacent, * and when that stops being the case, the dict must be unset */ @@ -2809,6 +2803,21 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize; ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize); } } + return ZSTDbss_compress; +} + +static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + size_t cSize; + DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", + (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate); + + { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); + FORWARD_IF_ERROR(bss); + if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; } + } /* encode sequences and literals */ cSize = ZSTD_compressSequences(&zc->seqStore, From 654cb9d4399e3a5f7739ebba31e5fd45f80cef59 Mon Sep 17 00:00:00 2001 From: LeeYoung624 Date: Tue, 9 Jul 2019 18:00:17 +0800 Subject: [PATCH 096/108] fix gitignore errors --- .gitignore | 7 +++++++ build/.gitignore | 2 ++ programs/.gitignore | 1 + tests/.gitignore | 1 + zlibWrapper/.gitignore | 3 +++ 5 files changed, 14 insertions(+) diff --git a/.gitignore b/.gitignore index abdf3b6338e..64cc811fb58 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,9 @@ # Executables zstd +!build/VS2008/zstd +!build/VS2010/zstd +!contrib/VS2005/zstd zstdmt *.exe *.out @@ -23,6 +26,10 @@ zstdmt # Test artefacts tmp* dictionary* +!examples/dictionary_compression.c +!examples/dictionary_decompression.c +!tests/fuzz/dictionary_decompress.c +!tests/fuzz/dictionary_round_trip.c NUL # Build artefacts diff --git a/build/.gitignore b/build/.gitignore index 1ceb70ebcc8..5a18b30a09b 100644 --- a/build/.gitignore +++ b/build/.gitignore @@ -29,3 +29,5 @@ compile_commands.json CTestTestfile.cmake build lib +!cmake/lib +!meson/lib diff --git a/programs/.gitignore b/programs/.gitignore index 701830c777c..0a8e18fbb2f 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -33,4 +33,5 @@ afl # Misc files *.bat +!windres/generate_res.bat dirTest* diff --git a/tests/.gitignore b/tests/.gitignore index 1f08c3995e8..4edf6ce1383 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -55,6 +55,7 @@ _* tmp* *.zst *.gz +!gzip/hufts-segv.gz result out *.zstd diff --git a/zlibWrapper/.gitignore b/zlibWrapper/.gitignore index 6167ca4dac8..289635d658c 100644 --- a/zlibWrapper/.gitignore +++ b/zlibWrapper/.gitignore @@ -1,11 +1,14 @@ # Default result files _* example.* +!examples/example.c example_zstd.* example_gz.* fitblk.* +!examples/fitblk.c fitblk_zstd.* zwrapbench.* +!examples/zwrapbench.c foo.gz minigzip From b8ec4b0fd6d32a9934cc8f9631e3a11974f7177b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 9 Jul 2019 11:43:59 -0700 Subject: [PATCH 097/108] updated version number (to v1.4.1) also : added doc on context re-use, as suggested by @scherepanov at #1676 --- doc/zstd_manual.html | 13 +++++++++---- lib/zstd.h | 11 ++++++++--- programs/zstd.1 | 6 +++++- programs/zstdgrep.1 | 2 +- programs/zstdless.1 | 2 +- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index c38c1f60cc3..f281120060c 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1,10 +1,10 @@ - zstd 1.4.0 Manual +zstd 1.4.1 Manual -zstd 1.4.0 Manual
+zstd 1.4.1 Manual
Contents
@@ -141,9 +141,14 @@
Helper functions
#define ZSTD_COMPRESSBOUND(srcSize)Explicit context
Compression context
When compressing many times, - it is recommended to allocate a context just once, and re-use it for each successive compression operation. + it is recommended to allocate a context just once, + and re-use it for each successive compression operation. This will make workload friendlier for system's memory. - Use one context per thread for parallel execution in multi-threaded environments. + Note : re-using context is just a speed / resource optimization. + It doesn't change the compression ratio, which remains identical. + Note 2 : In multi-threaded environments, + use one different context per thread for parallel execution. +typedef struct ZSTD_CCtx_s ZSTD_CCtx; ZSTD_CCtx* ZSTD_createCCtx(void); size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); diff --git a/lib/zstd.h b/lib/zstd.h index 922a2dfe7e8..a1910ee223e 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -71,7 +71,7 @@ extern "C" { /*------ Version ------*/ #define ZSTD_VERSION_MAJOR 1 #define ZSTD_VERSION_MINOR 4 -#define ZSTD_VERSION_RELEASE 0 +#define ZSTD_VERSION_RELEASE 1 #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */ @@ -183,9 +183,14 @@ ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compres ***************************************/ /*= Compression context * When compressing many times, - * it is recommended to allocate a context just once, and re-use it for each successive compression operation. + * it is recommended to allocate a context just once, + * and re-use it for each successive compression operation. * This will make workload friendlier for system's memory. - * Use one context per thread for parallel execution in multi-threaded environments. */ + * Note : re-using context is just a speed / resource optimization. + * It doesn't change the compression ratio, which remains identical. + * Note 2 : In multi-threaded environments, + * use one different context per thread for parallel execution. + */ typedef struct ZSTD_CCtx_s ZSTD_CCtx; ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); diff --git a/programs/zstd.1 b/programs/zstd.1 index cb4e1271a0f..beca9da421d 100644 --- a/programs/zstd.1 +++ b/programs/zstd.1 @@ -1,5 +1,5 @@ . -.TH "ZSTD" "1" "December 2018" "zstd 1.3.8" "User Commands" +.TH "ZSTD" "1" "July 2019" "zstd 1.4.1" "User Commands" . .SH "NAME" \fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files @@ -187,6 +187,10 @@ verbose mode suppress warnings, interactivity, and notifications\. specify twice to suppress errors too\. . .TP +\fB\-\-no\-progress\fR +do not display the progress bar, but keep all other messages\. +. +.TP \fB\-C\fR, \fB\-\-[no\-]check\fR add integrity check computed from uncompressed data (default: enabled) . diff --git a/programs/zstdgrep.1 b/programs/zstdgrep.1 index 57bc14de358..d0a0292215a 100644 --- a/programs/zstdgrep.1 +++ b/programs/zstdgrep.1 @@ -1,5 +1,5 @@ . -.TH "ZSTDGREP" "1" "December 2018" "zstd 1.3.8" "User Commands" +.TH "ZSTDGREP" "1" "July 2019" "zstd 1.4.1" "User Commands" . .SH "NAME" \fBzstdgrep\fR \- print lines matching a pattern in zstandard\-compressed files diff --git a/programs/zstdless.1 b/programs/zstdless.1 index ff39742bf8a..4e21d5a9063 100644 --- a/programs/zstdless.1 +++ b/programs/zstdless.1 @@ -1,5 +1,5 @@ . -.TH "ZSTDLESS" "1" "December 2018" "zstd 1.3.8" "User Commands" +.TH "ZSTDLESS" "1" "July 2019" "zstd 1.4.1" "User Commands" . .SH "NAME" \fBzstdless\fR \- view zstandard\-compressed files From 34a1a3724653323eb5b6b80b4e0c3a119565534e Mon Sep 17 00:00:00 2001 From: Yann ColletDate: Tue, 9 Jul 2019 14:44:22 -0700 Subject: [PATCH 098/108] updated .gitignore rule --- zlibWrapper/.gitignore | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zlibWrapper/.gitignore b/zlibWrapper/.gitignore index 289635d658c..b037ae6f293 100644 --- a/zlibWrapper/.gitignore +++ b/zlibWrapper/.gitignore @@ -1,14 +1,14 @@ +# object artifacts +*.o + # Default result files _* -example.* -!examples/example.c +example example_zstd.* example_gz.* -fitblk.* -!examples/fitblk.c +fitblk fitblk_zstd.* -zwrapbench.* -!examples/zwrapbench.c +zwrapbench foo.gz minigzip From 2387d574cb710056895d910a40a65d842dee2472 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 9 Jul 2019 14:54:48 -0700 Subject: [PATCH 099/108] updated .gitignore --- .gitignore | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 64cc811fb58..0c840b6b67b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,10 +14,7 @@ *.dylib # Executables -zstd -!build/VS2008/zstd -!build/VS2010/zstd -!contrib/VS2005/zstd +zstd. zstdmt *.exe *.out @@ -25,11 +22,7 @@ zstdmt # Test artefacts tmp* -dictionary* -!examples/dictionary_compression.c -!examples/dictionary_decompression.c -!tests/fuzz/dictionary_decompress.c -!tests/fuzz/dictionary_round_trip.c +dictionary. NUL # Build artefacts From d1327738c277643f09c972a407083ad73c8ecf7b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 11 Jul 2019 15:25:22 -0700 Subject: [PATCH 100/108] updated double_fast complementary insertion in a way which is more favorable to compression ratio, though very slightly slower (~-1%). More details in the PR. --- lib/compress/zstd_double_fast.c | 46 +++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index f156da9dfaf..bdb26ef80ee 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -254,11 +254,23 @@ size_t ZSTD_compressBlock_doubleFast_generic( anchor = ip; if (ip <= ilimit) { - /* Fill Table */ - hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2; /* here because current+2 could be > iend-8 */ - hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base); + /* Complementary insertion */ + /* done after iLimit test, as candidates could be > iend-8 */ + { U32 const indexToInsert = current+2; + hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = + hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = + indexToInsert; + } + { const BYTE* const ipToInsert = ip - 2; + hashLong[ZSTD_hashPtr(ipToInsert, hBitsL, 8)] = + hashSmall[ZSTD_hashPtr(ipToInsert, hBitsS, mls)] = + (U32)(ipToInsert-base); + } + { const BYTE* const ipToInsert = ip - 1; + hashLong[ZSTD_hashPtr(ipToInsert, hBitsL, 8)] = + hashSmall[ZSTD_hashPtr(ipToInsert, hBitsS, mls)] = + (U32)(ipToInsert-base); + } /* check immediate repcode */ if (dictMode == ZSTD_dictMatchState) { @@ -452,16 +464,28 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( continue; } } - /* found a match : store it */ + /* move to next sequence start */ ip += mLength; anchor = ip; if (ip <= ilimit) { - /* Fill Table */ - hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2; - hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2; - hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base); - hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); + /* Complementary insertion */ + /* done after iLimit test, as candidates could be > iend-8 */ + { U32 const indexToInsert = current+2; + hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = + hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = + indexToInsert; + } + { const BYTE* const ipToInsert = ip - 2; + hashLong[ZSTD_hashPtr(ipToInsert, hBitsL, 8)] = + hashSmall[ZSTD_hashPtr(ipToInsert, hBitsS, mls)] = + (U32)(ipToInsert-base); + } + { const BYTE* const ipToInsert = ip - 1; + hashLong[ZSTD_hashPtr(ipToInsert, hBitsL, 8)] = + hashSmall[ZSTD_hashPtr(ipToInsert, hBitsS, mls)] = + (U32)(ipToInsert-base); + } /* check immediate repcode */ while (ip <= ilimit) { U32 const current2 = (U32)(ip-base); From 812e8f2a16ff7999fc733903db80357e85b2fba8 Mon Sep 17 00:00:00 2001 From: mgrice Date: Thu, 11 Jul 2019 15:31:07 -0700 Subject: [PATCH 101/108] perf improvements for zstd decode (#1668) * perf improvements for zstd decode tldr: 7.5% average decode speedup on silesia corpus at compression levels 1-3 (sandy bridge) Background: while investigating zstd perf differences between clang and gcc I noticed that even though gcc is vectorizing the loop in in wildcopy, it was not being done as well as could be done by hand. The sites where wildcopy is invoked have an interesting distribution of lengths to be copied. The loop trip count is rarely above 1, yet long copies are common enough to make their performance important.The code in zstd_decompress.c to invoke wildcopy handles the latter well but the gcc autovectorizer introduces a needlessly expensive startup check for vectorization. See how GCC autovectorizes the loop here: https://godbolt.org/z/apr0x0 Here is the code after this diff has been applied: (left hand side is the good one, right is with vectorizer on) After: https://godbolt.org/z/OwO4F8 Note that autovectorization still does not do a good job on the optimized version, so it's turned off\ via attribute and flag. I found that neither attribute nor command-line flag were entirely successful in turning off vectorization, which is why there were both. silesia benchmark data - second triad of each file is with the original code: file orig compressedratio encode decode change 1#dickens 10192446-> 4268865(2.388), 198.9MB/s 709.6MB/s 2#dickens 10192446-> 3876126(2.630), 128.7MB/s 552.5MB/s 3#dickens 10192446-> 3682956(2.767), 104.6MB/s 537MB/s 1#dickens 10192446-> 4268865(2.388), 195.4MB/s 659.5MB/s 7.60% 2#dickens 10192446-> 3876126(2.630), 127MB/s 516.3MB/s 7.01% 3#dickens 10192446-> 3682956(2.767), 105MB/s 479.5MB/s 11.99% 1#mozilla 51220480-> 20117517(2.546), 285.4MB/s 734.9MB/s 2#mozilla 51220480-> 19067018(2.686), 220.8MB/s 686.3MB/s 3#mozilla 51220480-> 18508283(2.767), 152.2MB/s 669.4MB/s 1#mozilla 51220480-> 20117517(2.546), 283.4MB/s 697.9MB/s 5.30% 2#mozilla 51220480-> 19067018(2.686), 225.9MB/s 665MB/s 3.20% 3#mozilla 51220480-> 18508283(2.767), 154.5MB/s 640.6MB/s 4.50% 1#mr 9970564-> 3840242(2.596), 262.4MB/s 899.8MB/s 2#mr 9970564-> 3600976(2.769), 181.2MB/s 717.9MB/s 3#mr 9970564-> 3563987(2.798), 116.3MB/s 620MB/s 1#mr 9970564-> 3840242(2.596), 253.2MB/s 827.3MB/s 8.76% 2#mr 9970564-> 3600976(2.769), 177.4MB/s 655.4MB/s 9.54% 3#mr 9970564-> 3563987(2.798), 111.2MB/s 564.2MB/s 9.89% 1#nci 33553445-> 2849306(11.78), 575.2MB/s , 1335.8MB/s 2#nci 33553445-> 2890166(11.61), 509.3MB/s , 1238.1MB/s 3#nci 33553445-> 2857408(11.74), 431MB/s , 1210.7MB/s 1#nci 33553445-> 2849306(11.78), 565.4MB/s , 1220.2MB/s 9.47% 2#nci 33553445-> 2890166(11.61), 508.2MB/s , 1128.4MB/s 9.72% 3#nci 33553445-> 2857408(11.74), 429.1MB/s , 1097.7MB/s 10.29% 1#ooffice 6152192-> 3590954(1.713), 231.4MB/s , 662.6MB/s 2#ooffice 6152192-> 3323931(1.851), 162.8MB/s , 592.6MB/s 3#ooffice 6152192-> 3145625(1.956), 99.9MB/s , 549.6MB/s 1#ooffice 6152192-> 3590954(1.713), 224.7MB/s , 624.2MB/s 6.15% 2#ooffice 6152192-> 3323931 (1.851), 155MB/s , 564.5MB/s 4.98% 3#ooffice 6152192-> 3145625(1.956), 101.1MB/s , 521.2MB/s 5.45% 1#osdb 10085684-> 3739042(2.697), 271.9MB/s 876.4MB/s 2#osdb 10085684-> 3493875(2.887), 208.2MB/s 857MB/s 3#osdb 10085684-> 3515831(2.869), 135.3MB/s 805.4MB/s 1#osdb 10085684-> 3739042(2.697), 257.4MB/s 793.8MB/s 10.41% 2#osdb 10085684-> 3493875(2.887), 209.7MB/s 776.1MB/s 10.42% 3#osdb 10085684-> 3515831(2.869), 130.6MB/s 727.7MB/s 10.68% 1#reymont 6627202-> 2152771(3.078), 198.9MB/s 696.2MB/s 2#reymont 6627202-> 2071140(3.200), 170MB/s 595.2MB/s 3#reymont 6627202-> 1953597(3.392), 128.5MB/s 609.7MB/s 1#reymont 6627202-> 2152771(3.078), 199.6MB/s 655.2MB/s 6.26% 2#reymont 6627202-> 2071140(3.200), 168.2MB/s 554.4MB/s 7.36% 3#reymont 6627202-> 1953597(3.392), 128.7MB/s 557.4MB/s 9.38% 1#samba 21606400-> 5510994(3.921), 338.1MB/s 1066MB/s 2#samba 21606400-> 5240208(4.123), 258.7MB/s 992.3MB/s 3#samba 21606400-> 5003358(4.318), 200.2MB/s 991.1MB/s 1#samba 21606400-> 5510994(3.921), 330.8MB/s 974MB/s 9.45% 2#samba 21606400-> 5240208(4.123), 257.9MB/s 919.4MB/s 7.93% 3#samba 21606400-> 5003358(4.318), 198.5MB/s 908.9MB/s 9.04% 1#sao 7251944-> 6256401(1.159), 194.6MB/s 602.2MB/s 2#sao 7251944-> 5808761(1.248), 128.2MB/s 532.1MB/s 3#sao 7251944-> 5556318(1.305), 73MB/s 509.4MB/s 1#sao 7251944-> 6256401(1.159), 198.7MB/s 580.7MB/s 3.70% 2#sao 7251944-> 5808761(1.248), 129.1MB/s 502.7MB/s 5.85% 3#sao 7251944-> 5556318(1.305), 74.6MB/s 493.1MB/s 3.31% 1#webster 41458703-> 13692222(3.028), 222.3MB/s 752MB/s 2#webster 41458703-> 12842646(3.228), 157.6MB/s 532.2MB/s 3#webster 41458703-> 12191964(3.400), 124MB/s 468.5MB/s 1#webster 41458703-> 13692222(3.028), 219.7MB/s 697MB/s 7.89% 2#webster 41458703-> 12842646(3.228), 153.9MB/s 495.4MB/s 7.43% 3#webster 41458703-> 12191964(3.400), 124.8MB/s 444.8MB/s 5.33% 1#xml 5345280-> 696652(7.673), 485MB/s , 1333.9MB/s 2#xml 5345280-> 681492(7.843), 405.2MB/s , 1237.5MB/s 3#xml 5345280-> 639057(8.364), 328.5MB/s , 1281.3MB/s 1#xml 5345280-> 696652(7.673), 473.1MB/s , 1232.4MB/s 8.24% 2#xml 5345280-> 681492(7.843), 398.6MB/s , 1145.9MB/s 7.99% 3#xml 5345280-> 639057(8.364), 327.1MB/s , 1175MB/s 9.05% 1#x-ray 8474240-> 6772557(1.251), 521.3MB/s 762.6MB/s 2#x-ray 8474240-> 6684531(1.268), 230.5MB/s 688.5MB/s 3#x-ray 8474240-> 6166679(1.374), 68.7MB/s 478.8MB/s 1#x-ray 8474240-> 6772557(1.251), 502.8MB/s 736.7MB/s 3.52% 2#x-ray 8474240-> 6684531(1.268), 224.4MB/s 662MB/s 4.00% 3#x-ray 8474240-> 6166679(1.374), 67.3MB/s 437.8MB/s 9.37% 7.51% * makefile changed to only pass -fno-tree-vectorize to gcc * Don't add "no-tree-vectorize" attribute on clang (which defines __GNUC__) * fix for warning/error with subtraction of void* pointers * fix c90 conformance issue - ISO C90 forbids mixed declarations and code * Fix assert for negative diff, only when there is no overlap * fix overflow revealed in fuzzing tests * tweak for small speed increase --- lib/Makefile | 5 ++ lib/common/compiler.h | 7 +++ lib/common/zstd_internal.h | 64 +++++++++++++++++++++++--- lib/compress/zstd_compress_internal.h | 2 +- lib/decompress/zstd_decompress_block.c | 21 +++++---- 5 files changed, 84 insertions(+), 15 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 404f5b69210..87a396c53eb 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,6 +17,7 @@ LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT)) LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT)) LIBVER := $(shell echo $(LIBVER_SCRIPT)) VERSION?= $(LIBVER) +CCVER := $(shell $(CC) --version) CPPFLAGS+= -I. -I./common -DXXH_NAMESPACE=ZSTD_ ifeq ($(OS),Windows_NT) # MinGW assumed @@ -45,6 +46,10 @@ ZDICT_FILES := $(sort $(wildcard dictBuilder/*.c)) ZDEPR_FILES := $(sort $(wildcard deprecated/*.c)) ZSTD_FILES := $(ZSTDCOMMON_FILES) +ifeq ($(findstring GCC,$(CCVER)),GCC) +decompress/zstd_decompress_block.o : CFLAGS+=-fno-tree-vectorize +endif + ZSTD_LEGACY_SUPPORT ?= 5 ZSTD_LIB_COMPRESSION ?= 1 ZSTD_LIB_DECOMPRESSION ?= 1 diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 0836e3ed27a..87bf51ae8c8 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -127,6 +127,13 @@ } \ } +/* vectorization */ +#if !defined(__clang__) && defined(__GNUC__) +# define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) +#else +# define DONT_VECTORIZE +#endif + /* disable warnings */ #ifdef _MSC_VER /* Visual Studio */ # include /* For Visual 2005 */ diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 31f756ab581..81b16eac2ea 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -34,7 +34,6 @@ #endif #include "xxhash.h" /* XXH_reset, update, digest */ - #if defined (__cplusplus) extern "C" { #endif @@ -193,19 +192,72 @@ static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; * Shared functions to include for inlining *********************************************/ static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); } + #define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; } +static void ZSTD_copy16(void* dst, const void* src) { memcpy(dst, src, 16); } +#define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; } + +#define WILDCOPY_OVERLENGTH 8 +#define VECLEN 16 + +typedef enum { + ZSTD_no_overlap, + ZSTD_overlap_src_before_dst, + /* ZSTD_overlap_dst_before_src, */ +} ZSTD_overlap_e; /*! ZSTD_wildcopy() : * custom version of memcpy(), can overwrite up to WILDCOPY_OVERLENGTH bytes (if length==0) */ -#define WILDCOPY_OVERLENGTH 8 -MEM_STATIC void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length) +MEM_STATIC FORCE_INLINE_ATTR DONT_VECTORIZE +void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e ovtype) { + ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src; const BYTE* ip = (const BYTE*)src; BYTE* op = (BYTE*)dst; BYTE* const oend = op + length; - do - COPY8(op, ip) - while (op < oend); + + assert(diff >= 8 || (ovtype == ZSTD_no_overlap && diff < -8)); + if (length < VECLEN || (ovtype == ZSTD_overlap_src_before_dst && diff < VECLEN)) { + do + COPY8(op, ip) + while (op < oend); + } + else { + if ((length & 8) == 0) + COPY8(op, ip); + do { + COPY16(op, ip); + } + while (op < oend); + } +} + +/*! ZSTD_wildcopy_16min() : + * same semantics as ZSTD_wilcopy() except guaranteed to be able to copy 16 bytes at the start */ +MEM_STATIC FORCE_INLINE_ATTR DONT_VECTORIZE +void ZSTD_wildcopy_16min(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e ovtype) +{ + ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src; + const BYTE* ip = (const BYTE*)src; + BYTE* op = (BYTE*)dst; + BYTE* const oend = op + length; + + assert(length >= 8); + assert(diff >= 8 || (ovtype == ZSTD_no_overlap && diff < -8)); + + if (ovtype == ZSTD_overlap_src_before_dst && diff < VECLEN) { + do + COPY8(op, ip) + while (op < oend); + } + else { + if ((length & 8) == 0) + COPY8(op, ip); + do { + COPY16(op, ip); + } + while (op < oend); + } } MEM_STATIC void ZSTD_wildcopy_e(void* dst, const void* src, void* dstEnd) /* should be faster for decoding, but strangely, not verified on all platform */ diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ffcf26310f0..5495899be35 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -326,7 +326,7 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const v /* copy Literals */ assert(seqStorePtr->maxNbLit <= 128 KB); assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit); - ZSTD_wildcopy(seqStorePtr->lit, literals, litLength); + ZSTD_wildcopy(seqStorePtr->lit, literals, litLength, ZSTD_no_overlap); seqStorePtr->lit += litLength; /* literal Length */ diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 741784fdf9f..24f4859c56c 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -637,9 +637,10 @@ size_t ZSTD_execSequence(BYTE* op, if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd); /* copy Literals */ - ZSTD_copy8(op, *litPtr); if (sequence.litLength > 8) - ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ + ZSTD_wildcopy_16min(op, (*litPtr), sequence.litLength, ZSTD_no_overlap); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ + else + ZSTD_copy8(op, *litPtr); op = oLitEnd; *litPtr = iLitEnd; /* update for next sequence */ @@ -686,13 +687,13 @@ size_t ZSTD_execSequence(BYTE* op, if (oMatchEnd > oend-(16-MINMATCH)) { if (op < oend_w) { - ZSTD_wildcopy(op, match, oend_w - op); + ZSTD_wildcopy(op, match, oend_w - op, ZSTD_overlap_src_before_dst); match += oend_w - op; op = oend_w; } while (op < oMatchEnd) *op++ = *match++; } else { - ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */ + ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst); /* works even if matchLength < 8 */ } return sequenceLength; } @@ -717,9 +718,11 @@ size_t ZSTD_execSequenceLong(BYTE* op, if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd); /* copy Literals */ - ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */ if (sequence.litLength > 8) - ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ + ZSTD_wildcopy_16min(op, *litPtr, sequence.litLength, ZSTD_no_overlap); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ + else + ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */ + op = oLitEnd; *litPtr = iLitEnd; /* update for next sequence */ @@ -766,13 +769,13 @@ size_t ZSTD_execSequenceLong(BYTE* op, if (oMatchEnd > oend-(16-MINMATCH)) { if (op < oend_w) { - ZSTD_wildcopy(op, match, oend_w - op); + ZSTD_wildcopy(op, match, oend_w - op, ZSTD_overlap_src_before_dst); match += oend_w - op; op = oend_w; } while (op < oMatchEnd) *op++ = *match++; } else { - ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */ + ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst); /* works even if matchLength < 8 */ } return sequenceLength; } @@ -889,6 +892,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets) } FORCE_INLINE_TEMPLATE size_t +DONT_VECTORIZE ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* seqStart, size_t seqSize, int nbSeq, @@ -1137,6 +1141,7 @@ ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx, #ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG static TARGET_ATTRIBUTE("bmi2") size_t +DONT_VECTORIZE ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* seqStart, size_t seqSize, int nbSeq, From e8a7f5d3ce0ebb36e4ad850ab12463b1127dba17 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 12 Jul 2019 11:34:53 -0700 Subject: [PATCH 102/108] double-fast: changed the trade-off for a smaller positive change same number of complementary insertions, just organized differently (long at `ip-2`, short at `ip-1`). --- .gitignore | 2 +- lib/compress/zstd_double_fast.c | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 0c840b6b67b..4c297053b49 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ *.dylib # Executables -zstd. +/zstd zstdmt *.exe *.out diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index bdb26ef80ee..b65fd41e742 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -257,19 +257,10 @@ size_t ZSTD_compressBlock_doubleFast_generic( /* Complementary insertion */ /* done after iLimit test, as candidates could be > iend-8 */ { U32 const indexToInsert = current+2; - hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = - indexToInsert; - } - { const BYTE* const ipToInsert = ip - 2; - hashLong[ZSTD_hashPtr(ipToInsert, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(ipToInsert, hBitsS, mls)] = - (U32)(ipToInsert-base); - } - { const BYTE* const ipToInsert = ip - 1; - hashLong[ZSTD_hashPtr(ipToInsert, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(ipToInsert, hBitsS, mls)] = - (U32)(ipToInsert-base); + hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; + hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); + hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; + hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base); } /* check immediate repcode */ From eaeb7f00b5dea51b3e39175cee930bef0b0e16eb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 12 Jul 2019 14:17:17 -0700 Subject: [PATCH 103/108] updated the _extDict variant of double fast --- lib/compress/zstd_double_fast.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index b65fd41e742..5957255d904 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -463,20 +463,12 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( /* Complementary insertion */ /* done after iLimit test, as candidates could be > iend-8 */ { U32 const indexToInsert = current+2; - hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = - indexToInsert; - } - { const BYTE* const ipToInsert = ip - 2; - hashLong[ZSTD_hashPtr(ipToInsert, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(ipToInsert, hBitsS, mls)] = - (U32)(ipToInsert-base); - } - { const BYTE* const ipToInsert = ip - 1; - hashLong[ZSTD_hashPtr(ipToInsert, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(ipToInsert, hBitsS, mls)] = - (U32)(ipToInsert-base); + hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; + hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); + hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; + hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base); } + /* check immediate repcode */ while (ip <= ilimit) { U32 const current2 = (U32)(ip-base); From 75cfe1dc6998fed2e69919efa8652863caf7c999 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 12 Jul 2019 18:45:18 -0400 Subject: [PATCH 104/108] [ldm] Fix bug in overflow correction with large job size (#1678) * [ldm] Fix bug in overflow correction with large job size * [zstdmt] Respect ZSTDMT_JOBSIZE_MAX (1G in 64-bit mode) * [test] Add test that exposes the bug Sadly the test fails on our CI because it uses too much memory, so I had to comment it out. --- lib/compress/zstd_ldm.c | 2 +- lib/compress/zstdmt_compress.c | 14 ++++++++++---- lib/compress/zstdmt_compress.h | 1 + tests/playTests.sh | 4 ++++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 784d20f3ab7..3dcf86e6e8a 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -447,7 +447,7 @@ size_t ZSTD_ldm_generateSequences( if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) { U32 const ldmHSize = 1U << params->hashLog; U32 const correction = ZSTD_window_correctOverflow( - &ldmState->window, /* cycleLog */ 0, maxDist, src); + &ldmState->window, /* cycleLog */ 0, maxDist, chunkStart); ZSTD_ldm_reduceTable(ldmState->hashTable, ldmHSize, correction); } /* 2. We enforce the maximum offset allowed. diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 5557b478e6f..9e537b88485 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1153,12 +1153,16 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx) static unsigned ZSTDMT_computeTargetJobLog(ZSTD_CCtx_params const params) { - if (params.ldmParams.enableLdm) + unsigned jobLog; + if (params.ldmParams.enableLdm) { /* In Long Range Mode, the windowLog is typically oversized. * In which case, it's preferable to determine the jobSize * based on chainLog instead. */ - return MAX(21, params.cParams.chainLog + 4); - return MAX(20, params.cParams.windowLog + 2); + jobLog = MAX(21, params.cParams.chainLog + 4); + } else { + jobLog = MAX(20, params.cParams.windowLog + 2); + } + return MIN(jobLog, (unsigned)ZSTDMT_JOBLOG_MAX); } static int ZSTDMT_overlapLog_default(ZSTD_strategy strat) @@ -1396,7 +1400,7 @@ size_t ZSTDMT_initCStream_internal( FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) ); if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN; - if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX; + if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX; mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */ if (mtctx->singleBlockingThread) { @@ -1437,6 +1441,8 @@ size_t ZSTDMT_initCStream_internal( if (mtctx->targetSectionSize == 0) { mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(params); } + assert(mtctx->targetSectionSize <= (size_t)ZSTDMT_JOBSIZE_MAX); + if (params.rsyncable) { /* Aim for the targetsectionSize as the average job size. */ U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20); diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h index 12e6bcb3a33..12a526087db 100644 --- a/lib/compress/zstdmt_compress.h +++ b/lib/compress/zstdmt_compress.h @@ -50,6 +50,7 @@ #ifndef ZSTDMT_JOBSIZE_MIN # define ZSTDMT_JOBSIZE_MIN (1 MB) #endif +#define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30) #define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB)) diff --git a/tests/playTests.sh b/tests/playTests.sh index 2b8843f9784..69387321f92 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -974,6 +974,10 @@ then roundTripTest -g500000000 -P97 "1 -T999" " " fileRoundTripTest -g4103M -P98 " -T0" " " roundTripTest -g400000000 -P97 "1 --long=24 -T2" " " + # Exposes the bug in https://github.com/facebook/zstd/pull/1678 + # This test fails on 4 different travis builds at the time of writing + # because it needs to allocate 8 GB of memory. + # roundTripTest -g10G -P99 "1 -T1 --long=31 --zstd=clog=27 --fast=1000" else println "\n**** no multithreading, skipping zstdmt tests **** " fi From 4c2943df23b7178c20940a6bdc9fd7c90807c697 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 15 Jul 2019 11:25:22 -0700 Subject: [PATCH 105/108] [regression] Update results for ZSTD_double_fast update --- tests/regression/results.csv | 436 +++++++++++++++++------------------ 1 file changed, 218 insertions(+), 218 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 7f406baa5b0..e66787fc02f 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -2,10 +2,10 @@ Data, Config, Method, silesia.tar, level -5, compress simple, 6738558 silesia.tar, level -3, compress simple, 6446362 silesia.tar, level -1, compress simple, 6186038 -silesia.tar, level 0, compress simple, 4875008 +silesia.tar, level 0, compress simple, 4861374 silesia.tar, level 1, compress simple, 5334825 -silesia.tar, level 3, compress simple, 4875008 -silesia.tar, level 4, compress simple, 4813507 +silesia.tar, level 3, compress simple, 4861374 +silesia.tar, level 4, compress simple, 4799583 silesia.tar, level 5, compress simple, 4722271 silesia.tar, level 6, compress simple, 4672231 silesia.tar, level 7, compress simple, 4606657 @@ -13,16 +13,16 @@ silesia.tar, level 9, compress silesia.tar, level 13, compress simple, 4491706 silesia.tar, level 16, compress simple, 4381265 silesia.tar, level 19, compress simple, 4281551 -silesia.tar, uncompressed literals, compress simple, 4875008 +silesia.tar, uncompressed literals, compress simple, 4861374 silesia.tar, uncompressed literals optimal, compress simple, 4281551 silesia.tar, huffman literals, compress simple, 6186038 silesia, level -5, compress cctx, 6737567 silesia, level -3, compress cctx, 6444663 silesia, level -1, compress cctx, 6178442 -silesia, level 0, compress cctx, 4862377 +silesia, level 0, compress cctx, 4849491 silesia, level 1, compress cctx, 5313144 -silesia, level 3, compress cctx, 4862377 -silesia, level 4, compress cctx, 4800629 +silesia, level 3, compress cctx, 4849491 +silesia, level 4, compress cctx, 4786913 silesia, level 5, compress cctx, 4710178 silesia, level 6, compress cctx, 4659996 silesia, level 7, compress cctx, 4596234 @@ -30,31 +30,31 @@ silesia, level 9, compress silesia, level 13, compress cctx, 4482073 silesia, level 16, compress cctx, 4377389 silesia, level 19, compress cctx, 4293262 -silesia, long distance mode, compress cctx, 4862377 -silesia, multithreaded, compress cctx, 4862377 -silesia, multithreaded long distance mode, compress cctx, 4862377 -silesia, small window log, compress cctx, 7115734 +silesia, long distance mode, compress cctx, 4849491 +silesia, multithreaded, compress cctx, 4849491 +silesia, multithreaded long distance mode, compress cctx, 4849491 +silesia, small window log, compress cctx, 7112784 silesia, small hash log, compress cctx, 6554898 silesia, small chain log, compress cctx, 4931093 silesia, explicit params, compress cctx, 4794609 -silesia, uncompressed literals, compress cctx, 4862377 +silesia, uncompressed literals, compress cctx, 4849491 silesia, uncompressed literals optimal, compress cctx, 4293262 silesia, huffman literals, compress cctx, 6178442 -silesia, multithreaded with advanced params, compress cctx, 4862377 +silesia, multithreaded with advanced params, compress cctx, 4849491 github, level -5, compress cctx, 205285 github, level -5 with dict, compress cctx, 47294 github, level -3, compress cctx, 190643 github, level -3 with dict, compress cctx, 48047 github, level -1, compress cctx, 175568 github, level -1 with dict, compress cctx, 43527 -github, level 0, compress cctx, 136397 -github, level 0 with dict, compress cctx, 41536 +github, level 0, compress cctx, 136311 +github, level 0 with dict, compress cctx, 41534 github, level 1, compress cctx, 142450 github, level 1 with dict, compress cctx, 42157 -github, level 3, compress cctx, 136397 -github, level 3 with dict, compress cctx, 41536 +github, level 3, compress cctx, 136311 +github, level 3 with dict, compress cctx, 41534 github, level 4, compress cctx, 136144 -github, level 4 with dict, compress cctx, 41721 +github, level 4 with dict, compress cctx, 41725 github, level 5, compress cctx, 135106 github, level 5 with dict, compress cctx, 38934 github, level 6, compress cctx, 135108 @@ -69,24 +69,24 @@ github, level 16, compress github, level 16 with dict, compress cctx, 37568 github, level 19, compress cctx, 133717 github, level 19 with dict, compress cctx, 37567 -github, long distance mode, compress cctx, 141473 -github, multithreaded, compress cctx, 141473 -github, multithreaded long distance mode, compress cctx, 141473 -github, small window log, compress cctx, 141473 +github, long distance mode, compress cctx, 141101 +github, multithreaded, compress cctx, 141101 +github, multithreaded long distance mode, compress cctx, 141101 +github, small window log, compress cctx, 141101 github, small hash log, compress cctx, 138943 github, small chain log, compress cctx, 139239 github, explicit params, compress cctx, 140924 -github, uncompressed literals, compress cctx, 136397 +github, uncompressed literals, compress cctx, 136311 github, uncompressed literals optimal, compress cctx, 133717 github, huffman literals, compress cctx, 175568 -github, multithreaded with advanced params, compress cctx, 141473 +github, multithreaded with advanced params, compress cctx, 141101 silesia, level -5, zstdcli, 6882514 silesia, level -3, zstdcli, 6568406 silesia, level -1, zstdcli, 6183433 -silesia, level 0, zstdcli, 4862425 +silesia, level 0, zstdcli, 4849539 silesia, level 1, zstdcli, 5314157 -silesia, level 3, zstdcli, 4862425 -silesia, level 4, zstdcli, 4800677 +silesia, level 3, zstdcli, 4849539 +silesia, level 4, zstdcli, 4786961 silesia, level 5, zstdcli, 4710226 silesia, level 6, zstdcli, 4660044 silesia, level 7, zstdcli, 4596282 @@ -94,24 +94,24 @@ silesia, level 9, zstdcli, silesia, level 13, zstdcli, 4482121 silesia, level 16, zstdcli, 4377437 silesia, level 19, zstdcli, 4293310 -silesia, long distance mode, zstdcli, 4853437 -silesia, multithreaded, zstdcli, 4862425 -silesia, multithreaded long distance mode, zstdcli, 4853437 -silesia, small window log, zstdcli, 7126434 +silesia, long distance mode, zstdcli, 4839698 +silesia, multithreaded, zstdcli, 4849539 +silesia, multithreaded long distance mode, zstdcli, 4839698 +silesia, small window log, zstdcli, 7123892 silesia, small hash log, zstdcli, 6554946 silesia, small chain log, zstdcli, 4931141 silesia, explicit params, zstdcli, 4797048 -silesia, uncompressed literals, zstdcli, 5155472 +silesia, uncompressed literals, zstdcli, 5128008 silesia, uncompressed literals optimal, zstdcli, 4325482 silesia, huffman literals, zstdcli, 5331158 -silesia, multithreaded with advanced params, zstdcli, 5155472 +silesia, multithreaded with advanced params, zstdcli, 5128008 silesia.tar, level -5, zstdcli, 6738906 silesia.tar, level -3, zstdcli, 6448409 silesia.tar, level -1, zstdcli, 6186908 -silesia.tar, level 0, zstdcli, 4875136 +silesia.tar, level 0, zstdcli, 4861462 silesia.tar, level 1, zstdcli, 5336255 -silesia.tar, level 3, zstdcli, 4875136 -silesia.tar, level 4, zstdcli, 4814531 +silesia.tar, level 3, zstdcli, 4861462 +silesia.tar, level 4, zstdcli, 4800482 silesia.tar, level 5, zstdcli, 4723312 silesia.tar, level 6, zstdcli, 4673616 silesia.tar, level 7, zstdcli, 4608346 @@ -119,32 +119,32 @@ silesia.tar, level 9, zstdcli, silesia.tar, level 13, zstdcli, 4491710 silesia.tar, level 16, zstdcli, 4381269 silesia.tar, level 19, zstdcli, 4281555 -silesia.tar, no source size, zstdcli, 4875132 -silesia.tar, long distance mode, zstdcli, 4866975 -silesia.tar, multithreaded, zstdcli, 4875136 -silesia.tar, multithreaded long distance mode, zstdcli, 4866975 -silesia.tar, small window log, zstdcli, 7130434 +silesia.tar, no source size, zstdcli, 4861458 +silesia.tar, long distance mode, zstdcli, 4853140 +silesia.tar, multithreaded, zstdcli, 4861462 +silesia.tar, multithreaded long distance mode, zstdcli, 4853140 +silesia.tar, small window log, zstdcli, 7127964 silesia.tar, small hash log, zstdcli, 6587841 silesia.tar, small chain log, zstdcli, 4943269 silesia.tar, explicit params, zstdcli, 4822318 -silesia.tar, uncompressed literals, zstdcli, 5158134 +silesia.tar, uncompressed literals, zstdcli, 5129548 silesia.tar, uncompressed literals optimal, zstdcli, 4320914 silesia.tar, huffman literals, zstdcli, 5347560 -silesia.tar, multithreaded with advanced params, zstdcli, 5158134 +silesia.tar, multithreaded with advanced params, zstdcli, 5129548 github, level -5, zstdcli, 207285 github, level -5 with dict, zstdcli, 48718 github, level -3, zstdcli, 192643 github, level -3 with dict, zstdcli, 47395 github, level -1, zstdcli, 177568 github, level -1 with dict, zstdcli, 45170 -github, level 0, zstdcli, 138397 -github, level 0 with dict, zstdcli, 43170 +github, level 0, zstdcli, 138311 +github, level 0 with dict, zstdcli, 43148 github, level 1, zstdcli, 144450 github, level 1 with dict, zstdcli, 43682 -github, level 3, zstdcli, 138397 -github, level 3 with dict, zstdcli, 43170 +github, level 3, zstdcli, 138311 +github, level 3 with dict, zstdcli, 43148 github, level 4, zstdcli, 138144 -github, level 4 with dict, zstdcli, 43306 +github, level 4 with dict, zstdcli, 43251 github, level 5, zstdcli, 137106 github, level 5 with dict, zstdcli, 40938 github, level 6, zstdcli, 137108 @@ -159,24 +159,24 @@ github, level 16, zstdcli, github, level 16 with dict, zstdcli, 39577 github, level 19, zstdcli, 135717 github, level 19 with dict, zstdcli, 39576 -github, long distance mode, zstdcli, 138397 -github, multithreaded, zstdcli, 138397 -github, multithreaded long distance mode, zstdcli, 138397 -github, small window log, zstdcli, 138397 +github, long distance mode, zstdcli, 138311 +github, multithreaded, zstdcli, 138311 +github, multithreaded long distance mode, zstdcli, 138311 +github, small window log, zstdcli, 138311 github, small hash log, zstdcli, 137467 github, small chain log, zstdcli, 138314 github, explicit params, zstdcli, 136140 -github, uncompressed literals, zstdcli, 169004 +github, uncompressed literals, zstdcli, 167915 github, uncompressed literals optimal, zstdcli, 158824 github, huffman literals, zstdcli, 144450 -github, multithreaded with advanced params, zstdcli, 169004 +github, multithreaded with advanced params, zstdcli, 167915 silesia, level -5, advanced one pass, 6737567 silesia, level -3, advanced one pass, 6444663 silesia, level -1, advanced one pass, 6178442 -silesia, level 0, advanced one pass, 4862377 +silesia, level 0, advanced one pass, 4849491 silesia, level 1, advanced one pass, 5313144 -silesia, level 3, advanced one pass, 4862377 -silesia, level 4, advanced one pass, 4800629 +silesia, level 3, advanced one pass, 4849491 +silesia, level 4, advanced one pass, 4786913 silesia, level 5, advanced one pass, 4710178 silesia, level 6, advanced one pass, 4659996 silesia, level 7, advanced one pass, 4596234 @@ -184,25 +184,25 @@ silesia, level 9, advanced silesia, level 13, advanced one pass, 4482073 silesia, level 16, advanced one pass, 4377389 silesia, level 19, advanced one pass, 4293262 -silesia, no source size, advanced one pass, 4862377 -silesia, long distance mode, advanced one pass, 4853389 -silesia, multithreaded, advanced one pass, 4862377 -silesia, multithreaded long distance mode, advanced one pass, 4853389 -silesia, small window log, advanced one pass, 7126386 +silesia, no source size, advanced one pass, 4849491 +silesia, long distance mode, advanced one pass, 4839650 +silesia, multithreaded, advanced one pass, 4849491 +silesia, multithreaded long distance mode, advanced one pass, 4839650 +silesia, small window log, advanced one pass, 7123844 silesia, small hash log, advanced one pass, 6554898 silesia, small chain log, advanced one pass, 4931093 silesia, explicit params, advanced one pass, 4797035 -silesia, uncompressed literals, advanced one pass, 5155424 +silesia, uncompressed literals, advanced one pass, 5127960 silesia, uncompressed literals optimal, advanced one pass, 4325434 silesia, huffman literals, advanced one pass, 5326210 -silesia, multithreaded with advanced params, advanced one pass, 5155424 +silesia, multithreaded with advanced params, advanced one pass, 5127960 silesia.tar, level -5, advanced one pass, 6738558 silesia.tar, level -3, advanced one pass, 6446362 silesia.tar, level -1, advanced one pass, 6186038 -silesia.tar, level 0, advanced one pass, 4875008 +silesia.tar, level 0, advanced one pass, 4861374 silesia.tar, level 1, advanced one pass, 5334825 -silesia.tar, level 3, advanced one pass, 4875008 -silesia.tar, level 4, advanced one pass, 4813507 +silesia.tar, level 3, advanced one pass, 4861374 +silesia.tar, level 4, advanced one pass, 4799583 silesia.tar, level 5, advanced one pass, 4722271 silesia.tar, level 6, advanced one pass, 4672231 silesia.tar, level 7, advanced one pass, 4606657 @@ -210,32 +210,32 @@ silesia.tar, level 9, advanced silesia.tar, level 13, advanced one pass, 4491706 silesia.tar, level 16, advanced one pass, 4381265 silesia.tar, level 19, advanced one pass, 4281551 -silesia.tar, no source size, advanced one pass, 4875008 -silesia.tar, long distance mode, advanced one pass, 4861218 -silesia.tar, multithreaded, advanced one pass, 4874631 -silesia.tar, multithreaded long distance mode, advanced one pass, 4860683 -silesia.tar, small window log, advanced one pass, 7130394 +silesia.tar, no source size, advanced one pass, 4861374 +silesia.tar, long distance mode, advanced one pass, 4848046 +silesia.tar, multithreaded, advanced one pass, 4860726 +silesia.tar, multithreaded long distance mode, advanced one pass, 4847343 +silesia.tar, small window log, advanced one pass, 7127924 silesia.tar, small hash log, advanced one pass, 6587833 silesia.tar, small chain log, advanced one pass, 4943266 silesia.tar, explicit params, advanced one pass, 4808543 -silesia.tar, uncompressed literals, advanced one pass, 5157992 +silesia.tar, uncompressed literals, advanced one pass, 5129447 silesia.tar, uncompressed literals optimal, advanced one pass, 4320910 silesia.tar, huffman literals, advanced one pass, 5347283 -silesia.tar, multithreaded with advanced params, advanced one pass, 5158545 +silesia.tar, multithreaded with advanced params, advanced one pass, 5129766 github, level -5, advanced one pass, 205285 github, level -5 with dict, advanced one pass, 46718 github, level -3, advanced one pass, 190643 github, level -3 with dict, advanced one pass, 45395 github, level -1, advanced one pass, 175568 github, level -1 with dict, advanced one pass, 43170 -github, level 0, advanced one pass, 136397 -github, level 0 with dict, advanced one pass, 41170 +github, level 0, advanced one pass, 136311 +github, level 0 with dict, advanced one pass, 41148 github, level 1, advanced one pass, 142450 github, level 1 with dict, advanced one pass, 41682 -github, level 3, advanced one pass, 136397 -github, level 3 with dict, advanced one pass, 41170 +github, level 3, advanced one pass, 136311 +github, level 3 with dict, advanced one pass, 41148 github, level 4, advanced one pass, 136144 -github, level 4 with dict, advanced one pass, 41306 +github, level 4 with dict, advanced one pass, 41251 github, level 5, advanced one pass, 135106 github, level 5 with dict, advanced one pass, 38938 github, level 6, advanced one pass, 135108 @@ -250,25 +250,25 @@ github, level 16, advanced github, level 16 with dict, advanced one pass, 37577 github, level 19, advanced one pass, 133717 github, level 19 with dict, advanced one pass, 37576 -github, no source size, advanced one pass, 136397 -github, long distance mode, advanced one pass, 136397 -github, multithreaded, advanced one pass, 136397 -github, multithreaded long distance mode, advanced one pass, 136397 -github, small window log, advanced one pass, 136397 +github, no source size, advanced one pass, 136311 +github, long distance mode, advanced one pass, 136311 +github, multithreaded, advanced one pass, 136311 +github, multithreaded long distance mode, advanced one pass, 136311 +github, small window log, advanced one pass, 136311 github, small hash log, advanced one pass, 135467 github, small chain log, advanced one pass, 136314 github, explicit params, advanced one pass, 137670 -github, uncompressed literals, advanced one pass, 167004 +github, uncompressed literals, advanced one pass, 165915 github, uncompressed literals optimal, advanced one pass, 156824 github, huffman literals, advanced one pass, 142450 -github, multithreaded with advanced params, advanced one pass, 167004 +github, multithreaded with advanced params, advanced one pass, 165915 silesia, level -5, advanced one pass small out, 6737567 silesia, level -3, advanced one pass small out, 6444663 silesia, level -1, advanced one pass small out, 6178442 -silesia, level 0, advanced one pass small out, 4862377 +silesia, level 0, advanced one pass small out, 4849491 silesia, level 1, advanced one pass small out, 5313144 -silesia, level 3, advanced one pass small out, 4862377 -silesia, level 4, advanced one pass small out, 4800629 +silesia, level 3, advanced one pass small out, 4849491 +silesia, level 4, advanced one pass small out, 4786913 silesia, level 5, advanced one pass small out, 4710178 silesia, level 6, advanced one pass small out, 4659996 silesia, level 7, advanced one pass small out, 4596234 @@ -276,25 +276,25 @@ silesia, level 9, advanced silesia, level 13, advanced one pass small out, 4482073 silesia, level 16, advanced one pass small out, 4377389 silesia, level 19, advanced one pass small out, 4293262 -silesia, no source size, advanced one pass small out, 4862377 -silesia, long distance mode, advanced one pass small out, 4853389 -silesia, multithreaded, advanced one pass small out, 4862377 -silesia, multithreaded long distance mode, advanced one pass small out, 4853389 -silesia, small window log, advanced one pass small out, 7126386 +silesia, no source size, advanced one pass small out, 4849491 +silesia, long distance mode, advanced one pass small out, 4839650 +silesia, multithreaded, advanced one pass small out, 4849491 +silesia, multithreaded long distance mode, advanced one pass small out, 4839650 +silesia, small window log, advanced one pass small out, 7123844 silesia, small hash log, advanced one pass small out, 6554898 silesia, small chain log, advanced one pass small out, 4931093 silesia, explicit params, advanced one pass small out, 4797035 -silesia, uncompressed literals, advanced one pass small out, 5155424 +silesia, uncompressed literals, advanced one pass small out, 5127960 silesia, uncompressed literals optimal, advanced one pass small out, 4325434 silesia, huffman literals, advanced one pass small out, 5326210 -silesia, multithreaded with advanced params, advanced one pass small out, 5155424 +silesia, multithreaded with advanced params, advanced one pass small out, 5127960 silesia.tar, level -5, advanced one pass small out, 6738558 silesia.tar, level -3, advanced one pass small out, 6446362 silesia.tar, level -1, advanced one pass small out, 6186038 -silesia.tar, level 0, advanced one pass small out, 4875008 +silesia.tar, level 0, advanced one pass small out, 4861374 silesia.tar, level 1, advanced one pass small out, 5334825 -silesia.tar, level 3, advanced one pass small out, 4875008 -silesia.tar, level 4, advanced one pass small out, 4813507 +silesia.tar, level 3, advanced one pass small out, 4861374 +silesia.tar, level 4, advanced one pass small out, 4799583 silesia.tar, level 5, advanced one pass small out, 4722271 silesia.tar, level 6, advanced one pass small out, 4672231 silesia.tar, level 7, advanced one pass small out, 4606657 @@ -302,32 +302,32 @@ silesia.tar, level 9, advanced silesia.tar, level 13, advanced one pass small out, 4491706 silesia.tar, level 16, advanced one pass small out, 4381265 silesia.tar, level 19, advanced one pass small out, 4281551 -silesia.tar, no source size, advanced one pass small out, 4875008 -silesia.tar, long distance mode, advanced one pass small out, 4861218 -silesia.tar, multithreaded, advanced one pass small out, 4874631 -silesia.tar, multithreaded long distance mode, advanced one pass small out, 4860683 -silesia.tar, small window log, advanced one pass small out, 7130394 +silesia.tar, no source size, advanced one pass small out, 4861374 +silesia.tar, long distance mode, advanced one pass small out, 4848046 +silesia.tar, multithreaded, advanced one pass small out, 4860726 +silesia.tar, multithreaded long distance mode, advanced one pass small out, 4847343 +silesia.tar, small window log, advanced one pass small out, 7127924 silesia.tar, small hash log, advanced one pass small out, 6587833 silesia.tar, small chain log, advanced one pass small out, 4943266 silesia.tar, explicit params, advanced one pass small out, 4808543 -silesia.tar, uncompressed literals, advanced one pass small out, 5157992 +silesia.tar, uncompressed literals, advanced one pass small out, 5129447 silesia.tar, uncompressed literals optimal, advanced one pass small out, 4320910 silesia.tar, huffman literals, advanced one pass small out, 5347283 -silesia.tar, multithreaded with advanced params, advanced one pass small out, 5158545 +silesia.tar, multithreaded with advanced params, advanced one pass small out, 5129766 github, level -5, advanced one pass small out, 205285 github, level -5 with dict, advanced one pass small out, 46718 github, level -3, advanced one pass small out, 190643 github, level -3 with dict, advanced one pass small out, 45395 github, level -1, advanced one pass small out, 175568 github, level -1 with dict, advanced one pass small out, 43170 -github, level 0, advanced one pass small out, 136397 -github, level 0 with dict, advanced one pass small out, 41170 +github, level 0, advanced one pass small out, 136311 +github, level 0 with dict, advanced one pass small out, 41148 github, level 1, advanced one pass small out, 142450 github, level 1 with dict, advanced one pass small out, 41682 -github, level 3, advanced one pass small out, 136397 -github, level 3 with dict, advanced one pass small out, 41170 +github, level 3, advanced one pass small out, 136311 +github, level 3 with dict, advanced one pass small out, 41148 github, level 4, advanced one pass small out, 136144 -github, level 4 with dict, advanced one pass small out, 41306 +github, level 4 with dict, advanced one pass small out, 41251 github, level 5, advanced one pass small out, 135106 github, level 5 with dict, advanced one pass small out, 38938 github, level 6, advanced one pass small out, 135108 @@ -342,25 +342,25 @@ github, level 16, advanced github, level 16 with dict, advanced one pass small out, 37577 github, level 19, advanced one pass small out, 133717 github, level 19 with dict, advanced one pass small out, 37576 -github, no source size, advanced one pass small out, 136397 -github, long distance mode, advanced one pass small out, 136397 -github, multithreaded, advanced one pass small out, 136397 -github, multithreaded long distance mode, advanced one pass small out, 136397 -github, small window log, advanced one pass small out, 136397 +github, no source size, advanced one pass small out, 136311 +github, long distance mode, advanced one pass small out, 136311 +github, multithreaded, advanced one pass small out, 136311 +github, multithreaded long distance mode, advanced one pass small out, 136311 +github, small window log, advanced one pass small out, 136311 github, small hash log, advanced one pass small out, 135467 github, small chain log, advanced one pass small out, 136314 github, explicit params, advanced one pass small out, 137670 -github, uncompressed literals, advanced one pass small out, 167004 +github, uncompressed literals, advanced one pass small out, 165915 github, uncompressed literals optimal, advanced one pass small out, 156824 github, huffman literals, advanced one pass small out, 142450 -github, multithreaded with advanced params, advanced one pass small out, 167004 +github, multithreaded with advanced params, advanced one pass small out, 165915 silesia, level -5, advanced streaming, 6882466 silesia, level -3, advanced streaming, 6568358 silesia, level -1, advanced streaming, 6183385 -silesia, level 0, advanced streaming, 4862377 +silesia, level 0, advanced streaming, 4849491 silesia, level 1, advanced streaming, 5314109 -silesia, level 3, advanced streaming, 4862377 -silesia, level 4, advanced streaming, 4800629 +silesia, level 3, advanced streaming, 4849491 +silesia, level 4, advanced streaming, 4786913 silesia, level 5, advanced streaming, 4710178 silesia, level 6, advanced streaming, 4659996 silesia, level 7, advanced streaming, 4596234 @@ -368,25 +368,25 @@ silesia, level 9, advanced silesia, level 13, advanced streaming, 4482073 silesia, level 16, advanced streaming, 4377389 silesia, level 19, advanced streaming, 4293262 -silesia, no source size, advanced streaming, 4862341 -silesia, long distance mode, advanced streaming, 4853389 -silesia, multithreaded, advanced streaming, 4862377 -silesia, multithreaded long distance mode, advanced streaming, 4853389 -silesia, small window log, advanced streaming, 7126389 +silesia, no source size, advanced streaming, 4849455 +silesia, long distance mode, advanced streaming, 4839650 +silesia, multithreaded, advanced streaming, 4849491 +silesia, multithreaded long distance mode, advanced streaming, 4839650 +silesia, small window log, advanced streaming, 7123846 silesia, small hash log, advanced streaming, 6554898 silesia, small chain log, advanced streaming, 4931093 silesia, explicit params, advanced streaming, 4797048 -silesia, uncompressed literals, advanced streaming, 5155424 +silesia, uncompressed literals, advanced streaming, 5127960 silesia, uncompressed literals optimal, advanced streaming, 4325434 silesia, huffman literals, advanced streaming, 5331110 -silesia, multithreaded with advanced params, advanced streaming, 5155424 +silesia, multithreaded with advanced params, advanced streaming, 5127960 silesia.tar, level -5, advanced streaming, 6982738 silesia.tar, level -3, advanced streaming, 6641264 silesia.tar, level -1, advanced streaming, 6190789 -silesia.tar, level 0, advanced streaming, 4875010 +silesia.tar, level 0, advanced streaming, 4861376 silesia.tar, level 1, advanced streaming, 5336879 -silesia.tar, level 3, advanced streaming, 4875010 -silesia.tar, level 4, advanced streaming, 4813507 +silesia.tar, level 3, advanced streaming, 4861376 +silesia.tar, level 4, advanced streaming, 4799583 silesia.tar, level 5, advanced streaming, 4722276 silesia.tar, level 6, advanced streaming, 4672240 silesia.tar, level 7, advanced streaming, 4606657 @@ -394,32 +394,32 @@ silesia.tar, level 9, advanced silesia.tar, level 13, advanced streaming, 4491707 silesia.tar, level 16, advanced streaming, 4381284 silesia.tar, level 19, advanced streaming, 4281511 -silesia.tar, no source size, advanced streaming, 4875006 -silesia.tar, long distance mode, advanced streaming, 4861218 -silesia.tar, multithreaded, advanced streaming, 4875132 -silesia.tar, multithreaded long distance mode, advanced streaming, 4866971 -silesia.tar, small window log, advanced streaming, 7130394 +silesia.tar, no source size, advanced streaming, 4861372 +silesia.tar, long distance mode, advanced streaming, 4848046 +silesia.tar, multithreaded, advanced streaming, 4861458 +silesia.tar, multithreaded long distance mode, advanced streaming, 4853136 +silesia.tar, small window log, advanced streaming, 7127924 silesia.tar, small hash log, advanced streaming, 6587834 silesia.tar, small chain log, advanced streaming, 4943271 silesia.tar, explicit params, advanced streaming, 4808570 -silesia.tar, uncompressed literals, advanced streaming, 5157995 +silesia.tar, uncompressed literals, advanced streaming, 5129450 silesia.tar, uncompressed literals optimal, advanced streaming, 4320841 silesia.tar, huffman literals, advanced streaming, 5352306 -silesia.tar, multithreaded with advanced params, advanced streaming, 5158130 +silesia.tar, multithreaded with advanced params, advanced streaming, 5129544 github, level -5, advanced streaming, 205285 github, level -5 with dict, advanced streaming, 46718 github, level -3, advanced streaming, 190643 github, level -3 with dict, advanced streaming, 45395 github, level -1, advanced streaming, 175568 github, level -1 with dict, advanced streaming, 43170 -github, level 0, advanced streaming, 136397 -github, level 0 with dict, advanced streaming, 41170 +github, level 0, advanced streaming, 136311 +github, level 0 with dict, advanced streaming, 41148 github, level 1, advanced streaming, 142450 github, level 1 with dict, advanced streaming, 41682 -github, level 3, advanced streaming, 136397 -github, level 3 with dict, advanced streaming, 41170 +github, level 3, advanced streaming, 136311 +github, level 3 with dict, advanced streaming, 41148 github, level 4, advanced streaming, 136144 -github, level 4 with dict, advanced streaming, 41306 +github, level 4 with dict, advanced streaming, 41251 github, level 5, advanced streaming, 135106 github, level 5 with dict, advanced streaming, 38938 github, level 6, advanced streaming, 135108 @@ -434,25 +434,25 @@ github, level 16, advanced github, level 16 with dict, advanced streaming, 37577 github, level 19, advanced streaming, 133717 github, level 19 with dict, advanced streaming, 37576 -github, no source size, advanced streaming, 136397 -github, long distance mode, advanced streaming, 136397 -github, multithreaded, advanced streaming, 136397 -github, multithreaded long distance mode, advanced streaming, 136397 -github, small window log, advanced streaming, 136397 +github, no source size, advanced streaming, 136311 +github, long distance mode, advanced streaming, 136311 +github, multithreaded, advanced streaming, 136311 +github, multithreaded long distance mode, advanced streaming, 136311 +github, small window log, advanced streaming, 136311 github, small hash log, advanced streaming, 135467 github, small chain log, advanced streaming, 136314 github, explicit params, advanced streaming, 137670 -github, uncompressed literals, advanced streaming, 167004 +github, uncompressed literals, advanced streaming, 165915 github, uncompressed literals optimal, advanced streaming, 156824 github, huffman literals, advanced streaming, 142450 -github, multithreaded with advanced params, advanced streaming, 167004 +github, multithreaded with advanced params, advanced streaming, 165915 silesia, level -5, old streaming, 6882466 silesia, level -3, old streaming, 6568358 silesia, level -1, old streaming, 6183385 -silesia, level 0, old streaming, 4862377 +silesia, level 0, old streaming, 4849491 silesia, level 1, old streaming, 5314109 -silesia, level 3, old streaming, 4862377 -silesia, level 4, old streaming, 4800629 +silesia, level 3, old streaming, 4849491 +silesia, level 4, old streaming, 4786913 silesia, level 5, old streaming, 4710178 silesia, level 6, old streaming, 4659996 silesia, level 7, old streaming, 4596234 @@ -460,7 +460,7 @@ silesia, level 9, old stre silesia, level 13, old streaming, 4482073 silesia, level 16, old streaming, 4377389 silesia, level 19, old streaming, 4293262 -silesia, no source size, old streaming, 4862341 +silesia, no source size, old streaming, 4849455 silesia, long distance mode, old streaming, 12000408 silesia, multithreaded, old streaming, 12000408 silesia, multithreaded long distance mode, old streaming, 12000408 @@ -468,17 +468,17 @@ silesia, small window log, old stre silesia, small hash log, old streaming, 12000408 silesia, small chain log, old streaming, 12000408 silesia, explicit params, old streaming, 12000408 -silesia, uncompressed literals, old streaming, 4862377 +silesia, uncompressed literals, old streaming, 4849491 silesia, uncompressed literals optimal, old streaming, 4293262 silesia, huffman literals, old streaming, 6183385 silesia, multithreaded with advanced params, old streaming, 12000408 silesia.tar, level -5, old streaming, 6982738 silesia.tar, level -3, old streaming, 6641264 silesia.tar, level -1, old streaming, 6190789 -silesia.tar, level 0, old streaming, 4875010 +silesia.tar, level 0, old streaming, 4861376 silesia.tar, level 1, old streaming, 5336879 -silesia.tar, level 3, old streaming, 4875010 -silesia.tar, level 4, old streaming, 4813507 +silesia.tar, level 3, old streaming, 4861376 +silesia.tar, level 4, old streaming, 4799583 silesia.tar, level 5, old streaming, 4722276 silesia.tar, level 6, old streaming, 4672240 silesia.tar, level 7, old streaming, 4606657 @@ -486,7 +486,7 @@ silesia.tar, level 9, old stre silesia.tar, level 13, old streaming, 4491707 silesia.tar, level 16, old streaming, 4381284 silesia.tar, level 19, old streaming, 4281511 -silesia.tar, no source size, old streaming, 4875006 +silesia.tar, no source size, old streaming, 4861372 silesia.tar, long distance mode, old streaming, 12022046 silesia.tar, multithreaded, old streaming, 12022046 silesia.tar, multithreaded long distance mode, old streaming, 12022046 @@ -494,7 +494,7 @@ silesia.tar, small window log, old stre silesia.tar, small hash log, old streaming, 12022046 silesia.tar, small chain log, old streaming, 12022046 silesia.tar, explicit params, old streaming, 12022046 -silesia.tar, uncompressed literals, old streaming, 4875010 +silesia.tar, uncompressed literals, old streaming, 4861376 silesia.tar, uncompressed literals optimal, old streaming, 4281511 silesia.tar, huffman literals, old streaming, 6190789 silesia.tar, multithreaded with advanced params, old streaming, 12022046 @@ -504,14 +504,14 @@ github, level -3, old stre github, level -3 with dict, old streaming, 45395 github, level -1, old streaming, 175568 github, level -1 with dict, old streaming, 43170 -github, level 0, old streaming, 136397 -github, level 0 with dict, old streaming, 41170 +github, level 0, old streaming, 136311 +github, level 0 with dict, old streaming, 41148 github, level 1, old streaming, 142450 github, level 1 with dict, old streaming, 41682 -github, level 3, old streaming, 136397 -github, level 3 with dict, old streaming, 41170 +github, level 3, old streaming, 136311 +github, level 3 with dict, old streaming, 41148 github, level 4, old streaming, 136144 -github, level 4 with dict, old streaming, 41306 +github, level 4 with dict, old streaming, 41251 github, level 5, old streaming, 135106 github, level 5 with dict, old streaming, 38938 github, level 6, old streaming, 135108 @@ -526,7 +526,7 @@ github, level 16, old stre github, level 16 with dict, old streaming, 37577 github, level 19, old streaming, 133717 github, level 19 with dict, old streaming, 37576 -github, no source size, old streaming, 141003 +github, no source size, old streaming, 140631 github, long distance mode, old streaming, 412933 github, multithreaded, old streaming, 412933 github, multithreaded long distance mode, old streaming, 412933 @@ -534,17 +534,17 @@ github, small window log, old stre github, small hash log, old streaming, 412933 github, small chain log, old streaming, 412933 github, explicit params, old streaming, 412933 -github, uncompressed literals, old streaming, 136397 +github, uncompressed literals, old streaming, 136311 github, uncompressed literals optimal, old streaming, 133717 github, huffman literals, old streaming, 175568 github, multithreaded with advanced params, old streaming, 412933 silesia, level -5, old streaming advanced, 6882466 silesia, level -3, old streaming advanced, 6568358 silesia, level -1, old streaming advanced, 6183385 -silesia, level 0, old streaming advanced, 4862377 +silesia, level 0, old streaming advanced, 4849491 silesia, level 1, old streaming advanced, 5314109 -silesia, level 3, old streaming advanced, 4862377 -silesia, level 4, old streaming advanced, 4800629 +silesia, level 3, old streaming advanced, 4849491 +silesia, level 4, old streaming advanced, 4786913 silesia, level 5, old streaming advanced, 4710178 silesia, level 6, old streaming advanced, 4659996 silesia, level 7, old streaming advanced, 4596234 @@ -552,7 +552,7 @@ silesia, level 9, old stre silesia, level 13, old streaming advanced, 4482073 silesia, level 16, old streaming advanced, 4377389 silesia, level 19, old streaming advanced, 4293262 -silesia, no source size, old streaming advanced, 4862341 +silesia, no source size, old streaming advanced, 4849455 silesia, long distance mode, old streaming advanced, 12000408 silesia, multithreaded, old streaming advanced, 12000408 silesia, multithreaded long distance mode, old streaming advanced, 12000408 @@ -560,17 +560,17 @@ silesia, small window log, old stre silesia, small hash log, old streaming advanced, 12000408 silesia, small chain log, old streaming advanced, 12000408 silesia, explicit params, old streaming advanced, 12000408 -silesia, uncompressed literals, old streaming advanced, 4862377 +silesia, uncompressed literals, old streaming advanced, 4849491 silesia, uncompressed literals optimal, old streaming advanced, 4293262 silesia, huffman literals, old streaming advanced, 6183385 silesia, multithreaded with advanced params, old streaming advanced, 12000408 silesia.tar, level -5, old streaming advanced, 6982738 silesia.tar, level -3, old streaming advanced, 6641264 silesia.tar, level -1, old streaming advanced, 6190789 -silesia.tar, level 0, old streaming advanced, 4875010 +silesia.tar, level 0, old streaming advanced, 4861376 silesia.tar, level 1, old streaming advanced, 5336879 -silesia.tar, level 3, old streaming advanced, 4875010 -silesia.tar, level 4, old streaming advanced, 4813507 +silesia.tar, level 3, old streaming advanced, 4861376 +silesia.tar, level 4, old streaming advanced, 4799583 silesia.tar, level 5, old streaming advanced, 4722276 silesia.tar, level 6, old streaming advanced, 4672240 silesia.tar, level 7, old streaming advanced, 4606657 @@ -578,7 +578,7 @@ silesia.tar, level 9, old stre silesia.tar, level 13, old streaming advanced, 4491707 silesia.tar, level 16, old streaming advanced, 4381284 silesia.tar, level 19, old streaming advanced, 4281511 -silesia.tar, no source size, old streaming advanced, 4875006 +silesia.tar, no source size, old streaming advanced, 4861372 silesia.tar, long distance mode, old streaming advanced, 12022046 silesia.tar, multithreaded, old streaming advanced, 12022046 silesia.tar, multithreaded long distance mode, old streaming advanced, 12022046 @@ -586,7 +586,7 @@ silesia.tar, small window log, old stre silesia.tar, small hash log, old streaming advanced, 12022046 silesia.tar, small chain log, old streaming advanced, 12022046 silesia.tar, explicit params, old streaming advanced, 12022046 -silesia.tar, uncompressed literals, old streaming advanced, 4875010 +silesia.tar, uncompressed literals, old streaming advanced, 4861376 silesia.tar, uncompressed literals optimal, old streaming advanced, 4281511 silesia.tar, huffman literals, old streaming advanced, 6190789 silesia.tar, multithreaded with advanced params, old streaming advanced, 12022046 @@ -596,14 +596,14 @@ github, level -3, old stre github, level -3 with dict, old streaming advanced, 45395 github, level -1, old streaming advanced, 175568 github, level -1 with dict, old streaming advanced, 43170 -github, level 0, old streaming advanced, 136397 -github, level 0 with dict, old streaming advanced, 41170 +github, level 0, old streaming advanced, 136311 +github, level 0 with dict, old streaming advanced, 41148 github, level 1, old streaming advanced, 142450 github, level 1 with dict, old streaming advanced, 41682 -github, level 3, old streaming advanced, 136397 -github, level 3 with dict, old streaming advanced, 41170 +github, level 3, old streaming advanced, 136311 +github, level 3 with dict, old streaming advanced, 41148 github, level 4, old streaming advanced, 136144 -github, level 4 with dict, old streaming advanced, 41306 +github, level 4 with dict, old streaming advanced, 41251 github, level 5, old streaming advanced, 135106 github, level 5 with dict, old streaming advanced, 38938 github, level 6, old streaming advanced, 135108 @@ -618,7 +618,7 @@ github, level 16, old stre github, level 16 with dict, old streaming advanced, 37577 github, level 19, old streaming advanced, 133717 github, level 19 with dict, old streaming advanced, 37576 -github, no source size, old streaming advanced, 141003 +github, no source size, old streaming advanced, 140631 github, long distance mode, old streaming advanced, 412933 github, multithreaded, old streaming advanced, 412933 github, multithreaded long distance mode, old streaming advanced, 412933 @@ -626,17 +626,17 @@ github, small window log, old stre github, small hash log, old streaming advanced, 412933 github, small chain log, old streaming advanced, 412933 github, explicit params, old streaming advanced, 412933 -github, uncompressed literals, old streaming advanced, 136397 +github, uncompressed literals, old streaming advanced, 136311 github, uncompressed literals optimal, old streaming advanced, 133717 github, huffman literals, old streaming advanced, 175568 github, multithreaded with advanced params, old streaming advanced, 412933 silesia, level -5, old streaming cdcit, 6882466 silesia, level -3, old streaming cdcit, 6568358 silesia, level -1, old streaming cdcit, 6183385 -silesia, level 0, old streaming cdcit, 4862377 +silesia, level 0, old streaming cdcit, 4849491 silesia, level 1, old streaming cdcit, 5314109 -silesia, level 3, old streaming cdcit, 4862377 -silesia, level 4, old streaming cdcit, 4800629 +silesia, level 3, old streaming cdcit, 4849491 +silesia, level 4, old streaming cdcit, 4786913 silesia, level 5, old streaming cdcit, 4710178 silesia, level 6, old streaming cdcit, 4659996 silesia, level 7, old streaming cdcit, 4596234 @@ -644,7 +644,7 @@ silesia, level 9, old stre silesia, level 13, old streaming cdcit, 4482073 silesia, level 16, old streaming cdcit, 4377389 silesia, level 19, old streaming cdcit, 4293262 -silesia, no source size, old streaming cdcit, 4862341 +silesia, no source size, old streaming cdcit, 4849455 silesia, long distance mode, old streaming cdcit, 12000408 silesia, multithreaded, old streaming cdcit, 12000408 silesia, multithreaded long distance mode, old streaming cdcit, 12000408 @@ -652,17 +652,17 @@ silesia, small window log, old stre silesia, small hash log, old streaming cdcit, 12000408 silesia, small chain log, old streaming cdcit, 12000408 silesia, explicit params, old streaming cdcit, 12000408 -silesia, uncompressed literals, old streaming cdcit, 4862377 +silesia, uncompressed literals, old streaming cdcit, 4849491 silesia, uncompressed literals optimal, old streaming cdcit, 4293262 silesia, huffman literals, old streaming cdcit, 6183385 silesia, multithreaded with advanced params, old streaming cdcit, 12000408 silesia.tar, level -5, old streaming cdcit, 6982738 silesia.tar, level -3, old streaming cdcit, 6641264 silesia.tar, level -1, old streaming cdcit, 6190789 -silesia.tar, level 0, old streaming cdcit, 4875010 +silesia.tar, level 0, old streaming cdcit, 4861376 silesia.tar, level 1, old streaming cdcit, 5336879 -silesia.tar, level 3, old streaming cdcit, 4875010 -silesia.tar, level 4, old streaming cdcit, 4813507 +silesia.tar, level 3, old streaming cdcit, 4861376 +silesia.tar, level 4, old streaming cdcit, 4799583 silesia.tar, level 5, old streaming cdcit, 4722276 silesia.tar, level 6, old streaming cdcit, 4672240 silesia.tar, level 7, old streaming cdcit, 4606657 @@ -670,7 +670,7 @@ silesia.tar, level 9, old stre silesia.tar, level 13, old streaming cdcit, 4491707 silesia.tar, level 16, old streaming cdcit, 4381284 silesia.tar, level 19, old streaming cdcit, 4281511 -silesia.tar, no source size, old streaming cdcit, 4875006 +silesia.tar, no source size, old streaming cdcit, 4861372 silesia.tar, long distance mode, old streaming cdcit, 12022046 silesia.tar, multithreaded, old streaming cdcit, 12022046 silesia.tar, multithreaded long distance mode, old streaming cdcit, 12022046 @@ -678,7 +678,7 @@ silesia.tar, small window log, old stre silesia.tar, small hash log, old streaming cdcit, 12022046 silesia.tar, small chain log, old streaming cdcit, 12022046 silesia.tar, explicit params, old streaming cdcit, 12022046 -silesia.tar, uncompressed literals, old streaming cdcit, 4875010 +silesia.tar, uncompressed literals, old streaming cdcit, 4861376 silesia.tar, uncompressed literals optimal, old streaming cdcit, 4281511 silesia.tar, huffman literals, old streaming cdcit, 6190789 silesia.tar, multithreaded with advanced params, old streaming cdcit, 12022046 @@ -688,14 +688,14 @@ github, level -3, old stre github, level -3 with dict, old streaming cdcit, 45395 github, level -1, old streaming cdcit, 175568 github, level -1 with dict, old streaming cdcit, 43170 -github, level 0, old streaming cdcit, 136397 -github, level 0 with dict, old streaming cdcit, 41170 +github, level 0, old streaming cdcit, 136311 +github, level 0 with dict, old streaming cdcit, 41148 github, level 1, old streaming cdcit, 142450 github, level 1 with dict, old streaming cdcit, 41682 -github, level 3, old streaming cdcit, 136397 -github, level 3 with dict, old streaming cdcit, 41170 +github, level 3, old streaming cdcit, 136311 +github, level 3 with dict, old streaming cdcit, 41148 github, level 4, old streaming cdcit, 136144 -github, level 4 with dict, old streaming cdcit, 41306 +github, level 4 with dict, old streaming cdcit, 41251 github, level 5, old streaming cdcit, 135106 github, level 5 with dict, old streaming cdcit, 38938 github, level 6, old streaming cdcit, 135108 @@ -710,7 +710,7 @@ github, level 16, old stre github, level 16 with dict, old streaming cdcit, 37577 github, level 19, old streaming cdcit, 133717 github, level 19 with dict, old streaming cdcit, 37576 -github, no source size, old streaming cdcit, 141003 +github, no source size, old streaming cdcit, 140631 github, long distance mode, old streaming cdcit, 412933 github, multithreaded, old streaming cdcit, 412933 github, multithreaded long distance mode, old streaming cdcit, 412933 @@ -718,17 +718,17 @@ github, small window log, old stre github, small hash log, old streaming cdcit, 412933 github, small chain log, old streaming cdcit, 412933 github, explicit params, old streaming cdcit, 412933 -github, uncompressed literals, old streaming cdcit, 136397 +github, uncompressed literals, old streaming cdcit, 136311 github, uncompressed literals optimal, old streaming cdcit, 133717 github, huffman literals, old streaming cdcit, 175568 github, multithreaded with advanced params, old streaming cdcit, 412933 silesia, level -5, old streaming advanced cdict, 6882466 silesia, level -3, old streaming advanced cdict, 6568358 silesia, level -1, old streaming advanced cdict, 6183385 -silesia, level 0, old streaming advanced cdict, 4862377 +silesia, level 0, old streaming advanced cdict, 4849491 silesia, level 1, old streaming advanced cdict, 5314109 -silesia, level 3, old streaming advanced cdict, 4862377 -silesia, level 4, old streaming advanced cdict, 4800629 +silesia, level 3, old streaming advanced cdict, 4849491 +silesia, level 4, old streaming advanced cdict, 4786913 silesia, level 5, old streaming advanced cdict, 4710178 silesia, level 6, old streaming advanced cdict, 4659996 silesia, level 7, old streaming advanced cdict, 4596234 @@ -736,7 +736,7 @@ silesia, level 9, old stre silesia, level 13, old streaming advanced cdict, 4482073 silesia, level 16, old streaming advanced cdict, 4377389 silesia, level 19, old streaming advanced cdict, 4293262 -silesia, no source size, old streaming advanced cdict, 4862341 +silesia, no source size, old streaming advanced cdict, 4849455 silesia, long distance mode, old streaming advanced cdict, 12000408 silesia, multithreaded, old streaming advanced cdict, 12000408 silesia, multithreaded long distance mode, old streaming advanced cdict, 12000408 @@ -744,17 +744,17 @@ silesia, small window log, old stre silesia, small hash log, old streaming advanced cdict, 12000408 silesia, small chain log, old streaming advanced cdict, 12000408 silesia, explicit params, old streaming advanced cdict, 12000408 -silesia, uncompressed literals, old streaming advanced cdict, 4862377 +silesia, uncompressed literals, old streaming advanced cdict, 4849491 silesia, uncompressed literals optimal, old streaming advanced cdict, 4293262 silesia, huffman literals, old streaming advanced cdict, 6183385 silesia, multithreaded with advanced params, old streaming advanced cdict, 12000408 silesia.tar, level -5, old streaming advanced cdict, 6982738 silesia.tar, level -3, old streaming advanced cdict, 6641264 silesia.tar, level -1, old streaming advanced cdict, 6190789 -silesia.tar, level 0, old streaming advanced cdict, 4875010 +silesia.tar, level 0, old streaming advanced cdict, 4861376 silesia.tar, level 1, old streaming advanced cdict, 5336879 -silesia.tar, level 3, old streaming advanced cdict, 4875010 -silesia.tar, level 4, old streaming advanced cdict, 4813507 +silesia.tar, level 3, old streaming advanced cdict, 4861376 +silesia.tar, level 4, old streaming advanced cdict, 4799583 silesia.tar, level 5, old streaming advanced cdict, 4722276 silesia.tar, level 6, old streaming advanced cdict, 4672240 silesia.tar, level 7, old streaming advanced cdict, 4606657 @@ -762,7 +762,7 @@ silesia.tar, level 9, old stre silesia.tar, level 13, old streaming advanced cdict, 4491707 silesia.tar, level 16, old streaming advanced cdict, 4381284 silesia.tar, level 19, old streaming advanced cdict, 4281511 -silesia.tar, no source size, old streaming advanced cdict, 4875006 +silesia.tar, no source size, old streaming advanced cdict, 4861372 silesia.tar, long distance mode, old streaming advanced cdict, 12022046 silesia.tar, multithreaded, old streaming advanced cdict, 12022046 silesia.tar, multithreaded long distance mode, old streaming advanced cdict, 12022046 @@ -770,7 +770,7 @@ silesia.tar, small window log, old stre silesia.tar, small hash log, old streaming advanced cdict, 12022046 silesia.tar, small chain log, old streaming advanced cdict, 12022046 silesia.tar, explicit params, old streaming advanced cdict, 12022046 -silesia.tar, uncompressed literals, old streaming advanced cdict, 4875010 +silesia.tar, uncompressed literals, old streaming advanced cdict, 4861376 silesia.tar, uncompressed literals optimal, old streaming advanced cdict, 4281511 silesia.tar, huffman literals, old streaming advanced cdict, 6190789 silesia.tar, multithreaded with advanced params, old streaming advanced cdict, 12022046 @@ -780,14 +780,14 @@ github, level -3, old stre github, level -3 with dict, old streaming advanced cdict, 45395 github, level -1, old streaming advanced cdict, 175568 github, level -1 with dict, old streaming advanced cdict, 43170 -github, level 0, old streaming advanced cdict, 136397 -github, level 0 with dict, old streaming advanced cdict, 41170 +github, level 0, old streaming advanced cdict, 136311 +github, level 0 with dict, old streaming advanced cdict, 41148 github, level 1, old streaming advanced cdict, 142450 github, level 1 with dict, old streaming advanced cdict, 41682 -github, level 3, old streaming advanced cdict, 136397 -github, level 3 with dict, old streaming advanced cdict, 41170 +github, level 3, old streaming advanced cdict, 136311 +github, level 3 with dict, old streaming advanced cdict, 41148 github, level 4, old streaming advanced cdict, 136144 -github, level 4 with dict, old streaming advanced cdict, 41306 +github, level 4 with dict, old streaming advanced cdict, 41251 github, level 5, old streaming advanced cdict, 135106 github, level 5 with dict, old streaming advanced cdict, 38938 github, level 6, old streaming advanced cdict, 135108 @@ -802,7 +802,7 @@ github, level 16, old stre github, level 16 with dict, old streaming advanced cdict, 37577 github, level 19, old streaming advanced cdict, 133717 github, level 19 with dict, old streaming advanced cdict, 37576 -github, no source size, old streaming advanced cdict, 141003 +github, no source size, old streaming advanced cdict, 140631 github, long distance mode, old streaming advanced cdict, 412933 github, multithreaded, old streaming advanced cdict, 412933 github, multithreaded long distance mode, old streaming advanced cdict, 412933 @@ -810,7 +810,7 @@ github, small window log, old stre github, small hash log, old streaming advanced cdict, 412933 github, small chain log, old streaming advanced cdict, 412933 github, explicit params, old streaming advanced cdict, 412933 -github, uncompressed literals, old streaming advanced cdict, 136397 +github, uncompressed literals, old streaming advanced cdict, 136311 github, uncompressed literals optimal, old streaming advanced cdict, 133717 github, huffman literals, old streaming advanced cdict, 175568 github, multithreaded with advanced params, old streaming advanced cdict, 412933 From c05b270edc293cfd337176f9efdf9d16904229b8 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 17 Jul 2019 17:30:09 -0400 Subject: [PATCH 106/108] [doc] Remove Limitation that Compressed Block is Smaller than Uncompressed Content This changes the size limit on compressed blocks to match those of the other block types: they may not be larger than the `Block_Maximum_Decompressed_Size`, which is the smaller of the `Window_Size` and 128 KB, removing the additional restriction that had been placed on `Compressed_Block`s, that they be smaller than the decompressed content they represent. Several things motivate removing this restriction. On the one hand, this restriction is not useful for decoders: the decoder must nonetheless be prepared to accept compressed blocks that are the full `Block_Maximum_Decompressed_Size`. And on the other, this bound is actually artificially limiting. If block representations were entirely independent, a compressed representation of a block that is larger than the contents of the block would be ipso facto useless, and it would be strictly better to send it as an `Raw_Block`. However, blocks are not entirely independent, and it can make sense to pay the cost of encoding custom entropy tables in a block, even if that pushes that block size over the size of the data it represents, because those tables can be re-used by subsequent blocks. Finally, as far as I can tell, this restriction in the spec is not currently enforced in any Zstandard implementation, nor has it ever been. This change should therefore be safe to make. --- doc/zstd_compression_format.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index ed758cf598a..ad5a61ec7d5 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -390,9 +390,7 @@ A block can contain any number of bytes (even zero), up to - Window_Size - 128 KB -A `Compressed_Block` has the extra restriction that `Block_Size` is always -strictly less than the decompressed size. -If this condition cannot be respected, +If this condition cannot be respected when generating a `Compressed_Block`, the block must be sent uncompressed instead (`Raw_Block`). From a2861d75eb255ebb6bde02f8653ae530aefe7356 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 17 Jul 2019 17:55:15 -0400 Subject: [PATCH 107/108] [doc] Bump Format Spec Version --- doc/zstd_compression_format.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index ad5a61ec7d5..7d02426a50a 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -16,7 +16,7 @@ Distribution of this document is unlimited. ### Version -0.3.1 (25/10/18) +0.3.2 (17/07/19) Introduction @@ -1653,6 +1653,7 @@ or at least provide a meaningful error code explaining for which reason it canno Version changes --------------- +- 0.3.2 : remove additional block size restriction on compressed blocks - 0.3.1 : minor clarification regarding offset history update rules - 0.3.0 : minor edits to match RFC8478 - 0.2.9 : clarifications for huffman weights direct representation, by Ulrich Kunitz From 62a0dc57b10cc53200eea3e96328556fc986b929 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 19 Jul 2019 11:18:10 -0400 Subject: [PATCH 108/108] Update CHANGELOG with v1.4.1 Changes --- CHANGELOG | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index bf04a8a131c..a3a1f6154f5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,33 @@ +v1.4.1 +bug: Fix data corruption in niche use cases by @terrelln (#1659) +bug: Fuzz legacy modes, fix uncovered bugs by @terrelln (#1593, #1594, #1595) +bug: Fix out of bounds read by @terrelln (#1590) +perf: Improve decode speed by ~7% @mgrice (#1668) +perf: Slightly improved compression ratio of level 3 and 4 (ZSTD_dfast) by @cyan4973 (#1681) +perf: Slightly faster compression speed when re-using a context by @cyan4973 (#1658) +perf: Improve compression ratio for small windowLog by @cyan4973 (#1624) +perf: Faster compression speed in high compression mode for repetitive data by @terrelln (#1635) +api: Add parameter to generate smaller dictionaries by @tyler-tran (#1656) +cli: Recognize symlinks when built in C99 mode by @felixhandte (#1640) +cli: Expose cpu load indicator for each file on -vv mode by @ephiepark (#1631) +cli: Restrict read permissions on destination files by @chungy (#1644) +cli: zstdgrep: handle -f flag by @felixhandte (#1618) +cli: zstdcat: follow symlinks by @vejnar (#1604) +doc: Remove extra size limit on compressed blocks by @felixhandte (#1689) +doc: Fix typo by @yk-tanigawa (#1633) +doc: Improve documentation on streaming buffer sizes by @cyan4973 (#1629) +build: CMake: support building with LZ4 @leeyoung624 (#1626) +build: CMake: install zstdless and zstdgrep by @leeyoung624 (#1647) +build: CMake: respect existing uninstall target by @j301scott (#1619) +build: Make: skip multithread tests when built without support by @michaelforney (#1620) +build: Make: Fix examples/ test target by @sjnam (#1603) +build: Meson: rename options out of deprecated namespace by @lzutao (#1665) +build: Meson: fix build by @lzutao (#1602) +build: Visual Studio: don't export symbols in static lib by @scharan (#1650) +build: Visual Studio: fix linking by @absotively (#1639) +build: Fix MinGW-W64 build by @myzhang1029 (#1600) +misc: Expand decodecorpus coverage by @ephiepark (#1664) + v1.4.0 perf: Improve level 1 compression speed in most scenarios by 6% by @gbtucker and @terrelln api: Move the advanced API, including all functions in the staging section, to the stable section