From a5bce4ae84daa5885e61753fa98903964c3348bd Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 14:35:29 -0700 Subject: [PATCH 01/44] XP: add a pre-splitter instead of ingesting only full blocks, make an analysis of data, and infer where to split. --- lib/compress/zstd_compress.c | 31 ++++++-- lib/compress/zstd_preSplit.c | 139 +++++++++++++++++++++++++++++++++++ lib/compress/zstd_preSplit.h | 26 +++++++ 3 files changed, 188 insertions(+), 8 deletions(-) create mode 100644 lib/compress/zstd_preSplit.c create mode 100644 lib/compress/zstd_preSplit.h diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index aad25049d..040333e59 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -883,7 +883,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, value = ZSTDMT_JOBSIZE_MIN; FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); assert(value >= 0); - CCtxParams->jobSize = value; + CCtxParams->jobSize = (size_t)value; return CCtxParams->jobSize; #endif @@ -1002,7 +1002,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, case ZSTD_c_maxBlockSize: if (value!=0) /* 0 ==> default */ BOUNDCHECK(ZSTD_c_maxBlockSize, value); - CCtxParams->maxBlockSize = value; + assert(value>=0); + CCtxParams->maxBlockSize = (size_t)value; return CCtxParams->maxBlockSize; case ZSTD_c_searchForExternalRepcodes: @@ -2444,7 +2445,8 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, } /* Zero the hashTable3, since the cdict never fills it */ - { int const h3log = cctx->blockState.matchState.hashLog3; + assert(cctx->blockState.matchState.hashLog3 <= 31); + { U32 const h3log = cctx->blockState.matchState.hashLog3; size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; assert(cdict->matchState.hashLog3 == 0); ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); @@ -4484,6 +4486,18 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, } } +#include "zstd_preSplit.h" + +static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat) +{ + if (srcSize <= 128 KB || blockSizeMax < 128 KB) + return MIN(srcSize, blockSizeMax); + (void)strat; + if (strat >= ZSTD_btlazy2) + return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); + return 92 KB; +} + /*! ZSTD_compress_frameChunk() : * Compress a chunk of data into one or multiple blocks. * All blocks will be terminated, all input will be consumed. @@ -4496,7 +4510,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, const void* src, size_t srcSize, U32 lastFrameChunk) { - size_t blockSize = cctx->blockSize; + size_t blockSizeMax = cctx->blockSize; size_t remaining = srcSize; const BYTE* ip = (const BYTE*)src; BYTE* const ostart = (BYTE*)dst; @@ -4505,20 +4519,21 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); - DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); + DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSizeMax=%u)", (unsigned)blockSizeMax); if (cctx->appliedParams.fParams.checksumFlag && srcSize) XXH64_update(&cctx->xxhState, src, srcSize); while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; - U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); + U32 const lastBlock = lastFrameChunk & (blockSizeMax >= remaining); + size_t blockSize = ZSTD_optimalBlockSize(ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy); + assert(blockSize <= remaining); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding * additional 1. We need to revisit and change this logic to be more consistent */ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE + 1, dstSize_tooSmall, "not enough space to store compressed block"); - if (remaining < blockSize) blockSize = remaining; ZSTD_overflowCorrectIfNeeded( ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize); @@ -5022,7 +5037,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); } } } - return dictPtr - (const BYTE*)dict; + return (size_t)(dictPtr - (const BYTE*)dict); } /* Dictionary format : diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c new file mode 100644 index 000000000..eaa1c0516 --- /dev/null +++ b/lib/compress/zstd_preSplit.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * 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 "../common/mem.h" /* U64 */ +#include "zstd_preSplit.h" + + +#define BLOCKSIZE_MIN 3500 +#define THRESHOLD_PENALTY_RATE 16 +#define THRESHOLD_BASE (THRESHOLD_PENALTY_RATE - 2) +#define THRESHOLD_PENALTY 4 + +#define HASHLENGTH 2 +#define HASHLOG 10 +#define HASHTABLESIZE (1 << HASHLOG) +#define HASHMASK (HASHTABLESIZE - 1) +#define KNUTH 0x9e3779b9 + +static unsigned hash2(const void *p) +{ + return (U32)(MEM_read16(p)) * KNUTH >> (32 - HASHLOG); +} + + +/* ==================================== */ +/* Global array -> for testing only !!! */ +/* ==================================== */ +typedef struct { + int events[HASHTABLESIZE]; + S64 nbEvents; +} FingerPrint; +static FingerPrint pastEvents = {}; +static FingerPrint newEvents = {}; + +static void initStats(void) { + memset(&pastEvents, 0, sizeof(pastEvents)); + memset(&newEvents, 0, sizeof(newEvents)); +} +/* ==================================== */ + +static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { + const char* p = src; + size_t limit = s - HASHLENGTH + 1; + assert(s >= HASHLENGTH); + for (size_t n = 0; n < limit; n++) { + fp->events[hash2(p++)]++; + } + fp->nbEvents += limit; +} + +static void recordFingerprint(FingerPrint *fp, const void *src, size_t s) { + memset(fp, 0, sizeof(*fp)); + addToFingerprint(fp, src, s); +} + +static S64 abs64(S64 i) { return (i < 0) ? -i : i; } + +static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { + S64 distance = 0; + for (size_t n = 0; n < HASHTABLESIZE; n++) { + distance += + abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); + } + return distance; +} + +// Compare newEvents with pastEvents +// return 1 when considered "too different" +// debug:write Deviation value in % +static int compareFingerprints(const FingerPrint *ref, + const FingerPrint *new, + int penalty) +{ + if (ref->nbEvents <= BLOCKSIZE_MIN) + return 0; + { S64 p50 = ref->nbEvents * new->nbEvents; + S64 deviation = fpDistance(ref, new); + // printf("Deviation: %.2f%% \n", (double)deviation / (double)ref * 100.); + S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; + return deviation >= threshold; + } +} + +static void mergeEvents(FingerPrint *acc, const FingerPrint *new) { + for (size_t n = 0; n < HASHTABLESIZE; n++) { + acc->events[n] += new->events[n]; + } + acc->nbEvents += new->nbEvents; +} + +static void flushEvents(void) { + for (size_t n = 0; n < HASHTABLESIZE; n++) { + pastEvents.events[n] = newEvents.events[n]; + } + pastEvents.nbEvents = newEvents.nbEvents; + memset(&newEvents, 0, sizeof(newEvents)); +} + +static void removeEvents(FingerPrint *acc, const FingerPrint *slice) { + for (size_t n = 0; n < HASHTABLESIZE; n++) { + assert(acc->events[n] >= slice->events[n]); + acc->events[n] -= slice->events[n]; + } + acc->nbEvents -= slice->nbEvents; +} + +#define CHUNKSIZE (8 << 10) +/* Note: technically, we use CHUNKSIZE, so that's 8 KB */ +size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax) +{ + const char* p = src; + int penalty = THRESHOLD_PENALTY; + size_t pos = 0; + if (srcSize <= blockSizeMax) return srcSize; + assert(blockSizeMax == (128 << 10)); + + initStats(); + for (pos = 0; pos < blockSizeMax;) { + assert(pos <= blockSizeMax - CHUNKSIZE); + recordFingerprint(&newEvents, p + pos, CHUNKSIZE); + if (compareFingerprints(&pastEvents, &newEvents, penalty)) { + return pos; + } else { + mergeEvents(&pastEvents, &newEvents); + memset(&newEvents, 0, sizeof(newEvents)); + penalty = penalty - 1 + (penalty == 0); + } + pos += CHUNKSIZE; + } + return blockSizeMax; + (void)flushEvents; (void)removeEvents; +} diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h new file mode 100644 index 000000000..148fc1936 --- /dev/null +++ b/lib/compress/zstd_preSplit.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * 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. + */ + +#ifndef ZSTD_PRESPLIT_H +#define ZSTD_PRESPLIT_H + +#include /* size_t */ + +#if defined (__cplusplus) +extern "C" { +#endif + +size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax); + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_PRESPLIT_H */ From 9e52789962bc5d47ee62bc3e499c52435c693e89 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:44:30 -0700 Subject: [PATCH 02/44] fixed strict C90 semantic --- lib/compress/zstd_preSplit.c | 56 ++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index eaa1c0516..f2319986c 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -36,8 +36,8 @@ typedef struct { int events[HASHTABLESIZE]; S64 nbEvents; } FingerPrint; -static FingerPrint pastEvents = {}; -static FingerPrint newEvents = {}; +static FingerPrint pastEvents; +static FingerPrint newEvents; static void initStats(void) { memset(&pastEvents, 0, sizeof(pastEvents)); @@ -48,8 +48,9 @@ static void initStats(void) { static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { const char* p = src; size_t limit = s - HASHLENGTH + 1; + size_t n; assert(s >= HASHLENGTH); - for (size_t n = 0; n < limit; n++) { + for (n = 0; n < limit; n++) { fp->events[hash2(p++)]++; } fp->nbEvents += limit; @@ -64,7 +65,8 @@ static S64 abs64(S64 i) { return (i < 0) ? -i : i; } static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { S64 distance = 0; - for (size_t n = 0; n < HASHTABLESIZE; n++) { + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { distance += abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); } @@ -73,42 +75,46 @@ static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { // Compare newEvents with pastEvents // return 1 when considered "too different" -// debug:write Deviation value in % -static int compareFingerprints(const FingerPrint *ref, - const FingerPrint *new, +static int compareFingerprints(const FingerPrint* ref, + const FingerPrint* new, int penalty) { if (ref->nbEvents <= BLOCKSIZE_MIN) return 0; { S64 p50 = ref->nbEvents * new->nbEvents; S64 deviation = fpDistance(ref, new); - // printf("Deviation: %.2f%% \n", (double)deviation / (double)ref * 100.); S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; return deviation >= threshold; } } -static void mergeEvents(FingerPrint *acc, const FingerPrint *new) { - for (size_t n = 0; n < HASHTABLESIZE; n++) { - acc->events[n] += new->events[n]; - } - acc->nbEvents += new->nbEvents; +static void mergeEvents(FingerPrint* acc, const FingerPrint* new) +{ + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { + acc->events[n] += new->events[n]; + } + acc->nbEvents += new->nbEvents; } -static void flushEvents(void) { - for (size_t n = 0; n < HASHTABLESIZE; n++) { - pastEvents.events[n] = newEvents.events[n]; - } - pastEvents.nbEvents = newEvents.nbEvents; - memset(&newEvents, 0, sizeof(newEvents)); +static void flushEvents(void) +{ + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { + pastEvents.events[n] = newEvents.events[n]; + } + pastEvents.nbEvents = newEvents.nbEvents; + memset(&newEvents, 0, sizeof(newEvents)); } -static void removeEvents(FingerPrint *acc, const FingerPrint *slice) { - for (size_t n = 0; n < HASHTABLESIZE; n++) { - assert(acc->events[n] >= slice->events[n]); - acc->events[n] -= slice->events[n]; - } - acc->nbEvents -= slice->nbEvents; +static void removeEvents(FingerPrint* acc, const FingerPrint* slice) +{ + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { + assert(acc->events[n] >= slice->events[n]); + acc->events[n] -= slice->events[n]; + } + acc->nbEvents -= slice->nbEvents; } #define CHUNKSIZE (8 << 10) From 586ca96fec794cde09f4aa01fe792a9779b62368 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:48:52 -0700 Subject: [PATCH 03/44] do not use `new` as variable name --- lib/compress/zstd_preSplit.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index f2319986c..bba348927 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -76,25 +76,25 @@ static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { // Compare newEvents with pastEvents // return 1 when considered "too different" static int compareFingerprints(const FingerPrint* ref, - const FingerPrint* new, + const FingerPrint* newfp, int penalty) { if (ref->nbEvents <= BLOCKSIZE_MIN) return 0; - { S64 p50 = ref->nbEvents * new->nbEvents; - S64 deviation = fpDistance(ref, new); + { S64 p50 = ref->nbEvents * newfp->nbEvents; + S64 deviation = fpDistance(ref, newfp); S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; return deviation >= threshold; } } -static void mergeEvents(FingerPrint* acc, const FingerPrint* new) +static void mergeEvents(FingerPrint* acc, const FingerPrint* newfp) { size_t n; for (n = 0; n < HASHTABLESIZE; n++) { - acc->events[n] += new->events[n]; + acc->events[n] += newfp->events[n]; } - acc->nbEvents += new->nbEvents; + acc->nbEvents += newfp->nbEvents; } static void flushEvents(void) From e2d7d08888f915667c94e6dbbadaee38a5d50fa5 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:52:10 -0700 Subject: [PATCH 04/44] use ZSTD_memset() for better portability on Linux kernel --- lib/compress/zstd_preSplit.c | 50 +++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index bba348927..8db742c4d 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -39,38 +39,42 @@ typedef struct { static FingerPrint pastEvents; static FingerPrint newEvents; -static void initStats(void) { - memset(&pastEvents, 0, sizeof(pastEvents)); - memset(&newEvents, 0, sizeof(newEvents)); +static void initStats(void) +{ + ZSTD_memset(&pastEvents, 0, sizeof(pastEvents)); + ZSTD_memset(&newEvents, 0, sizeof(newEvents)); } /* ==================================== */ -static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { - const char* p = src; - size_t limit = s - HASHLENGTH + 1; - size_t n; - assert(s >= HASHLENGTH); - for (n = 0; n < limit; n++) { - fp->events[hash2(p++)]++; - } - fp->nbEvents += limit; +static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) +{ + const char* p = src; + size_t limit = s - HASHLENGTH + 1; + size_t n; + assert(s >= HASHLENGTH); + for (n = 0; n < limit; n++) { + fp->events[hash2(p++)]++; + } + fp->nbEvents += limit; } -static void recordFingerprint(FingerPrint *fp, const void *src, size_t s) { - memset(fp, 0, sizeof(*fp)); - addToFingerprint(fp, src, s); +static void recordFingerprint(FingerPrint* fp, const void* src, size_t s) +{ + memset(fp, 0, sizeof(*fp)); + addToFingerprint(fp, src, s); } static S64 abs64(S64 i) { return (i < 0) ? -i : i; } -static S64 fpDistance(const FingerPrint *fp1, const FingerPrint *fp2) { - S64 distance = 0; - size_t n; - for (n = 0; n < HASHTABLESIZE; n++) { - distance += - abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); - } - return distance; +static S64 fpDistance(const FingerPrint* fp1, const FingerPrint* fp2) +{ + S64 distance = 0; + size_t n; + for (n = 0; n < HASHTABLESIZE; n++) { + distance += + abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); + } + return distance; } // Compare newEvents with pastEvents From 6021b6663a4705f446f7cf856d944819caa575c3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:54:36 -0700 Subject: [PATCH 05/44] minor C++-ism though I really wonder if this is a property worth maintaining. --- lib/compress/zstd_preSplit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 8db742c4d..7d9a32c8f 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -48,7 +48,7 @@ static void initStats(void) static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { - const char* p = src; + const char* p = (const char*)src; size_t limit = s - HASHLENGTH + 1; size_t n; assert(s >= HASHLENGTH); @@ -125,7 +125,7 @@ static void removeEvents(FingerPrint* acc, const FingerPrint* slice) /* Note: technically, we use CHUNKSIZE, so that's 8 KB */ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax) { - const char* p = src; + const char* p = (const char*)src; int penalty = THRESHOLD_PENALTY; size_t pos = 0; if (srcSize <= blockSizeMax) return srcSize; From fa147cbb4d3fbd8c31b1f35c7984ae62f4c6ea03 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Sep 2024 16:59:06 -0700 Subject: [PATCH 06/44] more ZSTD_memset() to apply --- lib/compress/zstd_preSplit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 7d9a32c8f..9c84c2b4a 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -60,7 +60,7 @@ static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) static void recordFingerprint(FingerPrint* fp, const void* src, size_t s) { - memset(fp, 0, sizeof(*fp)); + ZSTD_memset(fp, 0, sizeof(*fp)); addToFingerprint(fp, src, s); } @@ -108,7 +108,7 @@ static void flushEvents(void) pastEvents.events[n] = newEvents.events[n]; } pastEvents.nbEvents = newEvents.nbEvents; - memset(&newEvents, 0, sizeof(newEvents)); + ZSTD_memset(&newEvents, 0, sizeof(newEvents)); } static void removeEvents(FingerPrint* acc, const FingerPrint* slice) @@ -139,7 +139,7 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax) return pos; } else { mergeEvents(&pastEvents, &newEvents); - memset(&newEvents, 0, sizeof(newEvents)); + ZSTD_memset(&newEvents, 0, sizeof(newEvents)); penalty = penalty - 1 + (penalty == 0); } pos += CHUNKSIZE; From 83a3402a928ef07700b1431c86534bec902ad11d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 12:55:08 -0700 Subject: [PATCH 07/44] fix overlap write scenario in presence of incompressible data --- lib/compress/zstd_compress.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 040333e59..eb7b06df9 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1631,7 +1631,8 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( { ZSTD_compressionParameters cParams; if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { - srcSizeHint = CCtxParams->srcSizeHint; + assert(srcSizeHint>=0); + srcSizeHint = (U64)CCtxParams->srcSizeHint; } cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; @@ -4488,14 +4489,18 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, #include "zstd_preSplit.h" -static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat) +static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { if (srcSize <= 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); (void)strat; if (strat >= ZSTD_btlazy2) return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); - return 92 KB; + /* blind split strategy + * heuristic, just tested as being "generally better" + * do not split incompressible data though: just respect the 3 bytes per block overhead limit. + */ + return savings ? 92 KB : 128 KB; } /*! ZSTD_compress_frameChunk() : @@ -4516,6 +4521,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; + S64 savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize; assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); @@ -4526,7 +4532,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; U32 const lastBlock = lastFrameChunk & (blockSizeMax >= remaining); - size_t blockSize = ZSTD_optimalBlockSize(ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy); + size_t const blockSize = ZSTD_optimalBlockSize(ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); assert(blockSize <= remaining); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding @@ -4571,7 +4577,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ - + if (cSize < blockSize) savings += (blockSize - cSize); ip += blockSize; assert(remaining >= blockSize); remaining -= blockSize; From f83ed087f6310a8cf51267ea431ec4a7b7ffd94f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 13:21:55 -0700 Subject: [PATCH 08/44] fixed RLE detection test --- lib/compress/zstd_compress.c | 10 +++++----- tests/fuzzer.c | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index eb7b06df9..25a11f070 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4491,14 +4491,14 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { - if (srcSize <= 128 KB || blockSizeMax < 128 KB) - return MIN(srcSize, blockSizeMax); - (void)strat; if (strat >= ZSTD_btlazy2) return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); + if (srcSize <= 128 KB || blockSizeMax < 128 KB) + return MIN(srcSize, blockSizeMax); /* blind split strategy - * heuristic, just tested as being "generally better" - * do not split incompressible data though: just respect the 3 bytes per block overhead limit. + * no cpu cost, but can over-split homegeneous data. + * heuristic, tested as being "generally better". + * do not split incompressible data though: respect the 3 bytes per block overhead limit. */ return savings ? 92 KB : 128 KB; } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index ead3cc8dd..f5a894354 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -3653,16 +3653,19 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTD_freeDCtx(dctx); } - /* long rle test */ + /* rle detection test: must compress better blocks with a single identical byte repeated */ { size_t sampleSize = 0; - size_t expectedCompressedSize = 39; /* block 1, 2: compressed, block 3: RLE, zstd 1.4.4 */ - DISPLAYLEVEL(3, "test%3i : Long RLE test : ", testNb++); - memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1); - sampleSize += 256 KB - 1; - memset((char*)CNBuffer+sampleSize, 'A', 96 KB); - sampleSize += 96 KB; + size_t maxCompressedSize = 46; /* block 1, 2: compressed, block 3: RLE, zstd 1.4.4 */ + DISPLAYLEVEL(3, "test%3i : RLE detection test : ", testNb++); + memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 2); + sampleSize += 256 KB - 2; + memset((char*)CNBuffer+sampleSize, 'A', 100 KB); + sampleSize += 100 KB; cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize, 1); - if (ZSTD_isError(cSize) || cSize > expectedCompressedSize) goto _output_error; + if (ZSTD_isError(cSize) || cSize > maxCompressedSize) { + DISPLAYLEVEL(4, "error: cSize %u > %u expected ! \n", (unsigned)cSize, (unsigned)maxCompressedSize); + goto _output_error; + } { CHECK_NEWV(regenSize, ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize)); if (regenSize!=sampleSize) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); From 8b3887f579f7e98d09ec3823736b467ceaebbcd1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 13:26:57 -0700 Subject: [PATCH 09/44] fixed kernel build --- lib/compress/zstd_preSplit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 9c84c2b4a..93e77248b 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -8,7 +8,8 @@ * You may select, at your option, one of the above-listed licenses. */ -#include "../common/mem.h" /* U64 */ +#include "../common/mem.h" /* S64 */ +#include "../common/zstd_deps.h" /* ZSTD_memset */ #include "zstd_preSplit.h" From dd38c677ebd680f29afdf4eab5c08d7a01eb8f39 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 14:41:26 -0700 Subject: [PATCH 10/44] fixed single-library build --- build/single_file_libs/zstd-in.c | 1 + 1 file changed, 1 insertion(+) diff --git a/build/single_file_libs/zstd-in.c b/build/single_file_libs/zstd-in.c index e6fca9e4a..f381ecc4f 100644 --- a/build/single_file_libs/zstd-in.c +++ b/build/single_file_libs/zstd-in.c @@ -69,6 +69,7 @@ #include "compress/zstd_compress_literals.c" #include "compress/zstd_compress_sequences.c" #include "compress/zstd_compress_superblock.c" +#include "compress/zstd_preSplit.c" #include "compress/zstd_compress.c" #include "compress/zstd_double_fast.c" #include "compress/zstd_fast.c" From 0d4b52065791a8e96faf8eb7665cb701b29d186e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 14:46:47 -0700 Subject: [PATCH 11/44] only split full blocks short term simplification --- lib/compress/zstd_compress.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 25a11f070..11c8ceabd 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4491,10 +4491,15 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { - if (strat >= ZSTD_btlazy2) - return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); + /* note: we currenly only split full blocks (128 KB) + * and when there is more than 128 KB input remaining + */ if (srcSize <= 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); + /* dynamic splitting has a cpu cost for analysis, + * due to that cost it's only used for btlazy2+ strategies */ + if (strat >= ZSTD_btlazy2) + return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); /* blind split strategy * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". From 20c3d176cd8871d01fe8135bdc7693a208d739bc Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 14:50:46 -0700 Subject: [PATCH 12/44] fix assert --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 11c8ceabd..d9f10f849 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1631,7 +1631,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( { ZSTD_compressionParameters cParams; if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { - assert(srcSizeHint>=0); + assert(CCtxParams->srcSizeHint>=0); srcSizeHint = (U64)CCtxParams->srcSizeHint; } cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); From 6dc52122e6e8b28b8477a202726dfff7d0ce0b9c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 14:52:49 -0700 Subject: [PATCH 13/44] fixed c90 comment style --- lib/compress/zstd_preSplit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 93e77248b..3256905df 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -78,8 +78,9 @@ static S64 fpDistance(const FingerPrint* fp1, const FingerPrint* fp2) return distance; } -// Compare newEvents with pastEvents -// return 1 when considered "too different" +/* Compare newEvents with pastEvents + * return 1 when considered "too different" + */ static int compareFingerprints(const FingerPrint* ref, const FingerPrint* newfp, int penalty) From 80a912dec1e5ec1fad6e6a698cfe04685c0d865e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 15:16:57 -0700 Subject: [PATCH 14/44] fixed zstreamtest --- tests/zstreamtest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 2c25adf3c..93032d21e 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -958,7 +958,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) break; out.size = MIN(out.size + cSize / 4, compressedBufferSize); } - CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, cSize)); + CHECK_Z(ZSTD_decompress(decodedBuffer, CNBufferSize, compressedBuffer, out.pos)); DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : ZSTD_compressStream2() ZSTD_c_stableInBuffer modify buffer : ", testNb++); From 6939235f010255bbe513dc5b18b1796cbee39d52 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 15:35:56 -0700 Subject: [PATCH 15/44] fixed meson build --- build/meson/lib/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/build/meson/lib/meson.build b/build/meson/lib/meson.build index 4ff926f9c..d086fc2d7 100644 --- a/build/meson/lib/meson.build +++ b/build/meson/lib/meson.build @@ -30,6 +30,7 @@ libzstd_sources = [join_paths(zstd_rootdir, 'lib/common/entropy_common.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_compress_literals.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_compress_sequences.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_compress_superblock.c'), + join_paths(zstd_rootdir, 'lib/compress/zstd_preSplit.c'), join_paths(zstd_rootdir, 'lib/compress/zstdmt_compress.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_fast.c'), join_paths(zstd_rootdir, 'lib/compress/zstd_double_fast.c'), From cdddcaaec9111c4ab086a55e4d0337131ca13fd0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 15:42:02 -0700 Subject: [PATCH 16/44] new Makefile target mesonbuild for easier local testing --- .github/workflows/dev-short-tests.yml | 8 ++++---- Makefile | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dev-short-tests.yml b/.github/workflows/dev-short-tests.yml index 7713a897c..99aa166c9 100644 --- a/.github/workflows/dev-short-tests.yml +++ b/.github/workflows/dev-short-tests.yml @@ -232,10 +232,10 @@ jobs: -Dbin_tests=true \ -Dbin_contrib=true \ -Ddefault_library=both \ - build/meson builddir - ninja -C builddir/ - meson test -C builddir/ --print-errorlogs - meson install -C builddir --destdir staging/ + build/meson mesonBuild + ninja -C mesonBuild/ + meson test -C mesonBuild/ --print-errorlogs + meson install -C mesonBuild --destdir staging/ meson-mingw-cross-compilation: runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index 5598cdd03..95d45afb4 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,7 @@ clean: $(Q)$(MAKE) -C contrib/largeNbDicts $@ > $(VOID) $(Q)$(MAKE) -C contrib/externalSequenceProducer $@ > $(VOID) $(Q)$(RM) zstd$(EXT) zstdmt$(EXT) tmp* - $(Q)$(RM) -r lz4 cmakebuild install + $(Q)$(RM) -r lz4 cmakebuild mesonbuild install @echo Cleaning completed #------------------------------------------------------------------------------ @@ -415,6 +415,24 @@ cmakebuild: $(CMAKE) --build cmakebuild --target install -- -j V=1 cd cmakebuild; ctest -V -L Medium +MESON ?= meson +NINJA ?= ninja + +.PHONY: mesonbuild +mesonbuild: + $(MESON) setup \ + --buildtype=debugoptimized \ + -Db_lundef=false \ + -Dauto_features=enabled \ + -Dbin_programs=true \ + -Dbin_tests=true \ + -Dbin_contrib=true \ + -Ddefault_library=both \ + build/meson mesonbuild + $(NINJA) -C mesonbuild/ + $(MESON) test -C mesonbuild/ --print-errorlogs + $(MESON) install -C mesonbuild --destdir staging/ + .PHONY: c89build gnu90build c99build gnu99build c11build bmix64build bmix32build bmi32build staticAnalyze c89build: clean $(CC) -v From 76ad1d69039c4900e5a0dca8eec7f3da2bebc050 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 15:44:51 -0700 Subject: [PATCH 17/44] fixed VS2010 solution --- build/VS2010/fullbench/fullbench.vcxproj | 1 + build/VS2010/fuzzer/fuzzer.vcxproj | 1 + build/VS2010/libzstd-dll/libzstd-dll.vcxproj | 1 + build/VS2010/libzstd/libzstd.vcxproj | 1 + build/VS2010/zstd/zstd.vcxproj | 1 + 5 files changed, 5 insertions(+) diff --git a/build/VS2010/fullbench/fullbench.vcxproj b/build/VS2010/fullbench/fullbench.vcxproj index 2e0a042b0..f60cfe726 100644 --- a/build/VS2010/fullbench/fullbench.vcxproj +++ b/build/VS2010/fullbench/fullbench.vcxproj @@ -170,6 +170,7 @@ + diff --git a/build/VS2010/fuzzer/fuzzer.vcxproj b/build/VS2010/fuzzer/fuzzer.vcxproj index 91974ec7f..ccbd2517d 100644 --- a/build/VS2010/fuzzer/fuzzer.vcxproj +++ b/build/VS2010/fuzzer/fuzzer.vcxproj @@ -170,6 +170,7 @@ + diff --git a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj index 97ad2fcb2..6925e0f9e 100644 --- a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj +++ b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj @@ -34,6 +34,7 @@ + diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj index 614e6292a..82a2d8268 100644 --- a/build/VS2010/libzstd/libzstd.vcxproj +++ b/build/VS2010/libzstd/libzstd.vcxproj @@ -34,6 +34,7 @@ + diff --git a/build/VS2010/zstd/zstd.vcxproj b/build/VS2010/zstd/zstd.vcxproj index 5a5237f0e..0558687f5 100644 --- a/build/VS2010/zstd/zstd.vcxproj +++ b/build/VS2010/zstd/zstd.vcxproj @@ -35,6 +35,7 @@ + From 31d48e9ffadde779e5fd9b290dee44f616b050fa Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 16:23:05 -0700 Subject: [PATCH 18/44] fixing minor formatting issue in 32-bit mode with logs enabled --- lib/compress/zstd_compress_internal.h | 4 ++-- lib/compress/zstd_opt.c | 18 +++++++++--------- lib/decompress/zstd_decompress.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 622903398..042b5e5ca 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -798,8 +798,8 @@ ZSTD_count_2segments(const BYTE* ip, const BYTE* match, size_t const matchLength = ZSTD_count(ip, match, vEnd); if (match + matchLength != mEnd) return matchLength; DEBUGLOG(7, "ZSTD_count_2segments: found a 2-parts match (current length==%zu)", matchLength); - DEBUGLOG(7, "distance from match beginning to end dictionary = %zi", mEnd - match); - DEBUGLOG(7, "distance from current pos to end buffer = %zi", iEnd - ip); + DEBUGLOG(7, "distance from match beginning to end dictionary = %i", (int)(mEnd - match)); + DEBUGLOG(7, "distance from current pos to end buffer = %i", (int)(iEnd - ip)); DEBUGLOG(7, "next byte : ip==%02X, istart==%02X", ip[matchLength], *iStart); DEBUGLOG(7, "final match length = %zu", matchLength + ZSTD_count(ip+matchLength, iStart, iEnd)); return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd); diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 8a4345b31..e4a8ee81e 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -1197,7 +1197,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, for (cur = 1; cur <= last_pos; cur++) { const BYTE* const inr = ip + cur; assert(cur <= ZSTD_OPT_NUM); - DEBUGLOG(7, "cPos:%zi==rPos:%u", inr-istart, cur); + DEBUGLOG(7, "cPos:%i==rPos:%u", (int)(inr-istart), cur); /* Fix current position with one literal if cheaper */ { U32 const litlen = opt[cur-1].litlen + 1; @@ -1207,8 +1207,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, assert(price < 1000000000); /* overflow check */ if (price <= opt[cur].price) { ZSTD_optimal_t const prevMatch = opt[cur]; - DEBUGLOG(7, "cPos:%zi==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)", - inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen, + DEBUGLOG(7, "cPos:%i==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)", + (int)(inr-istart), cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen, opt[cur-1].rep[0], opt[cur-1].rep[1], opt[cur-1].rep[2]); opt[cur] = opt[cur-1]; opt[cur].litlen = litlen; @@ -1240,8 +1240,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } } } else { - DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f)", - inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price)); + DEBUGLOG(7, "cPos:%i==rPos:%u : literal would cost more (%.2f>%.2f)", + (int)(inr-istart), cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price)); } } @@ -1284,8 +1284,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } { U32 const longestML = matches[nbMatches-1].len; - DEBUGLOG(7, "cPos:%zi==rPos:%u, found %u matches, of longest ML=%u", - inr-istart, cur, nbMatches, longestML); + DEBUGLOG(7, "cPos:%i==rPos:%u, found %u matches, of longest ML=%u", + (int)(inr-istart), cur, nbMatches, longestML); if ( (longestML > sufficient_len) || (cur + longestML >= ZSTD_OPT_NUM) @@ -1411,8 +1411,8 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ U32 const mlen = opt[storePos].mlen; U32 const offBase = opt[storePos].off; U32 const advance = llen + mlen; - DEBUGLOG(6, "considering seq starting at %zi, llen=%u, mlen=%u", - anchor - istart, (unsigned)llen, (unsigned)mlen); + DEBUGLOG(6, "considering seq starting at %i, llen=%u, mlen=%u", + (int)(anchor - istart), (unsigned)llen, (unsigned)mlen); if (mlen==0) { /* only literals => must be last "sequence", actually starting a new stream of sequences */ assert(storePos == storeEnd); /* must be last sequence */ diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 26c9457fb..6aac5dd3f 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1057,7 +1057,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, } ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0); /* Allow caller to get size read */ - DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr); + DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %i, consuming %i bytes of input", (int)(op-ostart), (int)(ip - (const BYTE*)*srcPtr)); *srcPtr = ip; *srcSizePtr = remainingSrcSize; return (size_t)(op-ostart); From 7f015c2fd799d3c273c5986a63059ef9536b701e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 17:05:17 -0700 Subject: [PATCH 19/44] replaced uasan32 test by asan32 test --- .github/workflows/dev-long-tests.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-long-tests.yml b/.github/workflows/dev-long-tests.yml index deb5242b0..fa603e401 100644 --- a/.github/workflows/dev-long-tests.yml +++ b/.github/workflows/dev-long-tests.yml @@ -156,15 +156,30 @@ jobs: make libc6install CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest - clang-asan-ubsan-fuzz32: + clang-asan-fuzz32: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 - - name: clang + ASan + UBSan + Fuzz Test 32bit + - name: clang + ASan + Fuzz Test 32bit run: | sudo apt-get -qqq update make libc6install - CC=clang CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest + CC=clang CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make asan-fuzztest + +# The following test seems to have issues on github CI specifically, +# it does not provide the `__mulodi4` instruction emulation +# required for signed 64-bit multiplication. +# Replaced by asan-only test (above) +# +# clang-asan-ubsan-fuzz32: +# runs-on: ubuntu-20.04 +# steps: +# - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 +# - name: clang + ASan + UBSan + Fuzz Test 32bit +# run: | +# sudo apt-get -qqq update +# make libc6install +# CC=clang CFLAGS="-O3 -m32" FUZZER_FLAGS="--long-tests" make uasan-fuzztest asan-ubsan-regression: runs-on: ubuntu-20.04 From 73a665365350668757ec542277472ca73267603a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 17 Oct 2024 18:40:47 -0700 Subject: [PATCH 20/44] ZSTD_splitBlock_4k() uses externally provided workspace ideally, this workspace would be provided from the ZSTD_CCtx* state --- lib/compress/zstd_compress.c | 9 +++++--- lib/compress/zstd_preSplit.c | 43 ++++++++++++++++++++---------------- lib/compress/zstd_preSplit.h | 8 ++++++- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d9f10f849..37b87336c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4489,8 +4489,11 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, #include "zstd_preSplit.h" -static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) + +static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { + S64 workspace[ZSTD_SLIPBLOCK_WORKSPACESIZE / 8]; + (void)cctx; /* note: we currenly only split full blocks (128 KB) * and when there is more than 128 KB input remaining */ @@ -4499,7 +4502,7 @@ static size_t ZSTD_optimalBlockSize(const void* src, size_t srcSize, size_t bloc /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for btlazy2+ strategies */ if (strat >= ZSTD_btlazy2) - return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax); + return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax, workspace, sizeof(workspace)); /* blind split strategy * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". @@ -4537,7 +4540,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; U32 const lastBlock = lastFrameChunk & (blockSizeMax >= remaining); - size_t const blockSize = ZSTD_optimalBlockSize(ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); + size_t const blockSize = ZSTD_optimalBlockSize(cctx, ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); assert(blockSize <= remaining); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 3256905df..ba9dc6487 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -10,6 +10,7 @@ #include "../common/mem.h" /* S64 */ #include "../common/zstd_deps.h" /* ZSTD_memset */ +#include "../common/zstd_internal.h" /* ZSTD_STATIC_ASSERT */ #include "zstd_preSplit.h" @@ -30,22 +31,19 @@ static unsigned hash2(const void *p) } -/* ==================================== */ -/* Global array -> for testing only !!! */ -/* ==================================== */ typedef struct { int events[HASHTABLESIZE]; S64 nbEvents; } FingerPrint; -static FingerPrint pastEvents; -static FingerPrint newEvents; +typedef struct { + FingerPrint pastEvents; + FingerPrint newEvents; +} FPStats; -static void initStats(void) +static void initStats(FPStats* fpstats) { - ZSTD_memset(&pastEvents, 0, sizeof(pastEvents)); - ZSTD_memset(&newEvents, 0, sizeof(newEvents)); + ZSTD_memset(fpstats, 0, sizeof(FPStats)); } -/* ==================================== */ static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) { @@ -103,14 +101,14 @@ static void mergeEvents(FingerPrint* acc, const FingerPrint* newfp) acc->nbEvents += newfp->nbEvents; } -static void flushEvents(void) +static void flushEvents(FPStats* fpstats) { size_t n; for (n = 0; n < HASHTABLESIZE; n++) { - pastEvents.events[n] = newEvents.events[n]; + fpstats->pastEvents.events[n] = fpstats->newEvents.events[n]; } - pastEvents.nbEvents = newEvents.nbEvents; - ZSTD_memset(&newEvents, 0, sizeof(newEvents)); + fpstats->pastEvents.nbEvents = fpstats->newEvents.nbEvents; + ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); } static void removeEvents(FingerPrint* acc, const FingerPrint* slice) @@ -125,23 +123,30 @@ static void removeEvents(FingerPrint* acc, const FingerPrint* slice) #define CHUNKSIZE (8 << 10) /* Note: technically, we use CHUNKSIZE, so that's 8 KB */ -size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax) +size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, + size_t blockSizeMax, + void* workspace, size_t wkspSize) { + FPStats* const fpstats = (FPStats*)workspace; const char* p = (const char*)src; int penalty = THRESHOLD_PENALTY; size_t pos = 0; if (srcSize <= blockSizeMax) return srcSize; assert(blockSizeMax == (128 << 10)); + assert(workspace != NULL); + assert((size_t)workspace % 8 == 0); + ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE == sizeof(FPStats)); + assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; - initStats(); + initStats(fpstats); for (pos = 0; pos < blockSizeMax;) { assert(pos <= blockSizeMax - CHUNKSIZE); - recordFingerprint(&newEvents, p + pos, CHUNKSIZE); - if (compareFingerprints(&pastEvents, &newEvents, penalty)) { + recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE); + if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { return pos; } else { - mergeEvents(&pastEvents, &newEvents); - ZSTD_memset(&newEvents, 0, sizeof(newEvents)); + mergeEvents(&fpstats->pastEvents, &fpstats->newEvents); + ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); penalty = penalty - 1 + (penalty == 0); } pos += CHUNKSIZE; diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index 148fc1936..b0b6bb762 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -17,7 +17,13 @@ extern "C" { #endif -size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax); +#define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208 + +/* note: + * @workspace must be aligned on 8-bytes boundaries + * @wkspSize must be at least >= ZSTD_SLIPBLOCK_WORKSPACESIZE + */ +size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax, void* workspace, size_t wkspSize); #if defined (__cplusplus) } From 433f4598ad96a4e661cfd877b50c9000ea174897 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Oct 2024 11:16:49 -0700 Subject: [PATCH 21/44] fixed minor conversion warnings on Visual --- tests/zstreamtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 93032d21e..8df86d985 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -441,7 +441,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) size_t const gfhError = ZSTD_getFrameHeader(&fhi, cStart, cSize); if (gfhError!=0) goto _output_error; DISPLAYLEVEL(5, " (windowSize : %u) ", (unsigned)fhi.windowSize); - { size_t const s = ZSTD_estimateDStreamSize(fhi.windowSize) + { size_t const s = ZSTD_estimateDStreamSize((size_t)fhi.windowSize) /* uses ZSTD_initDStream_usingDict() */ + ZSTD_estimateDDictSize(dictSize, ZSTD_dlm_byCopy); if (ZSTD_isError(s)) goto _output_error; @@ -1551,7 +1551,7 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests) DISPLAYLEVEL(3, "test%3i : check dictionary FSE tables can represent every code : ", testNb++); { unsigned const kMaxWindowLog = 24; unsigned value; - ZSTD_compressionParameters cParams = ZSTD_getCParams(3, 1U << kMaxWindowLog, 1024); + ZSTD_compressionParameters cParams = ZSTD_getCParams(3, 1ULL << kMaxWindowLog, 1024); ZSTD_CDict* cdict; ZSTD_DDict* ddict; SEQ_stream seq = SEQ_initStream(0x87654321); From 4685eafa81d4c31048577aeb461883043ca96c2f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Oct 2024 11:20:54 -0700 Subject: [PATCH 22/44] fix alignment test for non 64-bit systems --- lib/compress/zstd_preSplit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index ba9dc6487..ceac5c91f 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -8,6 +8,7 @@ * You may select, at your option, one of the above-listed licenses. */ +#include "../common/compiler.h" /* ZSTD_ALIGNOF */ #include "../common/mem.h" /* S64 */ #include "../common/zstd_deps.h" /* ZSTD_memset */ #include "../common/zstd_internal.h" /* ZSTD_STATIC_ASSERT */ @@ -134,7 +135,7 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, if (srcSize <= blockSizeMax) return srcSize; assert(blockSizeMax == (128 << 10)); assert(workspace != NULL); - assert((size_t)workspace % 8 == 0); + assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0); ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE == sizeof(FPStats)); assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; From cae8d13294904c0b6095a5533d0cda72d7e6a7ff Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Oct 2024 16:00:36 -0700 Subject: [PATCH 23/44] splitter workspace is now provided by ZSTD_CCtx* --- lib/compress/zstd_compress.c | 59 ++++++++++++------------- lib/compress/zstd_compress_internal.h | 5 ++- lib/compress/zstd_compress_superblock.c | 4 +- lib/compress/zstd_cwksp.h | 36 ++++++++++----- 4 files changed, 60 insertions(+), 44 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 37b87336c..40d3afaae 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -137,11 +137,12 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) ZSTD_cwksp_move(&cctx->workspace, &ws); cctx->staticSize = workspaceSize; - /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */ + /* statically sized space. tmpWorkspace never moves (but prev/next block swap places) */ if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE); + cctx->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(&cctx->workspace, TMP_WORKSPACE_SIZE, sizeof(S64)); + cctx->tmpWkspSize = TMP_WORKSPACE_SIZE; cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); return cctx; } @@ -1661,14 +1662,14 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, + hSize * sizeof(U32) + h3Size * sizeof(U32); size_t const optPotentialSpace = - ZSTD_cwksp_aligned_alloc_size((MaxML+1) * sizeof(U32)) - + ZSTD_cwksp_aligned_alloc_size((MaxLL+1) * sizeof(U32)) - + ZSTD_cwksp_aligned_alloc_size((MaxOff+1) * sizeof(U32)) - + ZSTD_cwksp_aligned_alloc_size((1<strategy, useRowMatchFinder) - ? ZSTD_cwksp_aligned_alloc_size(hSize) + ? ZSTD_cwksp_aligned64_alloc_size(hSize) : 0; size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt)) ? optPotentialSpace @@ -1706,16 +1707,16 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize); size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer); size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_aligned_alloc_size(maxNbSeq * sizeof(seqDef)) + + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(seqDef)) + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE); + size_t const tmpWorkSpace = ZSTD_cwksp_aligned_alloc_size(TMP_WORKSPACE_SIZE, sizeof(S64)); size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1); size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams); size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize); size_t const ldmSeqSpace = ldmParams->enableLdm == ZSTD_ps_enable ? - ZSTD_cwksp_aligned_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0; + ZSTD_cwksp_aligned64_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0; size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) @@ -1725,12 +1726,12 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize); size_t const externalSeqSpace = useSequenceProducer - ? ZSTD_cwksp_aligned_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence)) + ? ZSTD_cwksp_aligned64_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence)) : 0; size_t const neededSpace = cctxSpace + - entropySpace + + tmpWorkSpace + blockStateSpace + ldmSpace + ldmSeqSpace + @@ -2166,15 +2167,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, DEBUGLOG(5, "reserving object space"); /* Statically sized space. - * entropyWorkspace never moves, + * tmpWorkspace never moves, * though prev/next block swap places */ assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t))); zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock"); zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock"); - zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE); - RETURN_ERROR_IF(zc->entropyWorkspace == NULL, memory_allocation, "couldn't allocate entropyWorkspace"); + zc->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(ws, TMP_WORKSPACE_SIZE, sizeof(S64)); + RETURN_ERROR_IF(zc->tmpWorkspace == NULL, memory_allocation, "couldn't allocate tmpWorkspace"); + zc->tmpWkspSize = TMP_WORKSPACE_SIZE; } } ZSTD_cwksp_clear(ws); @@ -3894,14 +3896,14 @@ ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, ZSTD_CC &zc->blockState.nextCBlock->entropy, &zc->appliedParams, entropyMetadata, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE), ""); + zc->tmpWorkspace, zc->tmpWkspSize), ""); return ZSTD_estimateBlockSize( seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart), seqStore->ofCode, seqStore->llCode, seqStore->mlCode, (size_t)(seqStore->sequences - seqStore->sequencesStart), &zc->blockState.nextCBlock->entropy, entropyMetadata, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE, + zc->tmpWorkspace, zc->tmpWkspSize, (int)(entropyMetadata->hufMetadata.hType == set_compressed), 1); } @@ -4067,7 +4069,7 @@ ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, &zc->appliedParams, op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize, srcSize, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */, zc->bmi2); FORWARD_IF_ERROR(cSeqsSize, "ZSTD_entropyCompressSeqStore failed!"); @@ -4357,7 +4359,7 @@ ZSTD_compressBlock_internal(ZSTD_CCtx* zc, &zc->appliedParams, dst, dstCapacity, srcSize, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */, zc->bmi2); if (frame && @@ -4489,20 +4491,17 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, #include "zstd_preSplit.h" - static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { - S64 workspace[ZSTD_SLIPBLOCK_WORKSPACESIZE / 8]; - (void)cctx; - /* note: we currenly only split full blocks (128 KB) - * and when there is more than 128 KB input remaining + /* note: conservatively only split full blocks (128 KB) currently, + * and even then only if there is more than 128 KB input remaining. */ if (srcSize <= 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for btlazy2+ strategies */ if (strat >= ZSTD_btlazy2) - return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax, workspace, sizeof(workspace)); + return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". @@ -5174,11 +5173,11 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent, cdict->dictContentSize, cdict->dictContentType, dtlm, - ZSTD_tfp_forCCtx, cctx->entropyWorkspace) + ZSTD_tfp_forCCtx, cctx->tmpWorkspace) : ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize, - dictContentType, dtlm, ZSTD_tfp_forCCtx, cctx->entropyWorkspace); + dictContentType, dtlm, ZSTD_tfp_forCCtx, cctx->tmpWorkspace); FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); assert(dictID <= UINT_MAX); cctx->dictID = (U32)dictID; @@ -6876,7 +6875,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, &cctx->appliedParams, op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, blockSize, - cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */, cctx->bmi2); FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); DEBUGLOG(5, "Compressed sequences size: %zu", compressedSeqsSize); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 042b5e5ca..e76bbda71 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -24,6 +24,7 @@ # include "zstdmt_compress.h" #endif #include "../common/bits.h" /* ZSTD_highbit32, ZSTD_NbCommonBytes */ +#include "zstd_preSplit.h" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */ #if defined (__cplusplus) extern "C" { @@ -376,6 +377,7 @@ struct ZSTD_CCtx_params_s { #define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2)) #define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE) +#define TMP_WORKSPACE_SIZE (MAX(ENTROPY_WORKSPACE_SIZE, ZSTD_SLIPBLOCK_WORKSPACESIZE)) /** * Indicates whether this compression proceeds directly from user-provided @@ -432,7 +434,8 @@ struct ZSTD_CCtx_s { size_t maxNbLdmSequences; rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */ ZSTD_blockState_t blockState; - U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */ + void* tmpWorkspace; /* used as substitute of stack space - must be aligned for S64 type */ + size_t tmpWkspSize; /* Whether we are streaming or not */ ZSTD_buffered_policy_e bufferedPolicy; diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index 628a2dccd..97321bc76 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -674,7 +674,7 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, &entropyMetadata, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); + zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */), ""); return ZSTD_compressSubBlock_multi(&zc->seqStore, zc->blockState.prevCBlock, @@ -684,5 +684,5 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, dst, dstCapacity, src, srcSize, zc->bmi2, lastBlock, - zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */); + zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */); } diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index dcd485cb5..239fcf6d2 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -222,7 +222,7 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) { * to figure out how much space you need for the matchState tables. Everything * else is though. * - * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned_alloc_size(). + * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned64_alloc_size(). */ MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) { if (size == 0) @@ -234,12 +234,16 @@ MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) { #endif } +MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size, size_t alignment) { + return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, alignment)); +} + /** * Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes. * Used to determine the number of bytes required for a given "aligned". */ -MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) { - return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, ZSTD_CWKSP_ALIGNMENT_BYTES)); +MEM_STATIC size_t ZSTD_cwksp_aligned64_alloc_size(size_t size) { + return ZSTD_cwksp_aligned_alloc_size(size, ZSTD_CWKSP_ALIGNMENT_BYTES); } /** @@ -272,7 +276,7 @@ MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignByt * which we can allocate from the end of the workspace. */ MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws) { - return (void*)((size_t)ws->workspaceEnd & ~(ZSTD_CWKSP_ALIGNMENT_BYTES-1)); + return (void*)((size_t)ws->workspaceEnd & (size_t)~(ZSTD_CWKSP_ALIGNMENT_BYTES-1)); } /** @@ -426,8 +430,9 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t byt */ MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) { - void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES), - ZSTD_cwksp_alloc_aligned); + void* const ptr = ZSTD_cwksp_reserve_internal(ws, + ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES), + ZSTD_cwksp_alloc_aligned); assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); return ptr; } @@ -479,12 +484,12 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) } /** - * Aligned on sizeof(void*). * Note : should happen only once, at workspace first initialization */ -MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) +MEM_STATIC void* +ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t bytes, size_t alignment) { - size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*)); + size_t const roundedBytes = ZSTD_cwksp_align(bytes, alignment); void* alloc = ws->objectEnd; void* end = (BYTE*)alloc + roundedBytes; @@ -496,8 +501,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) DEBUGLOG(4, "cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining", alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes); - assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0); - assert(bytes % ZSTD_ALIGNOF(void*) == 0); + assert((size_t)alloc % alignment == 0); + assert(bytes % alignment == 0); ZSTD_cwksp_assert_internal_consistency(ws); /* we must be in the first phase, no advance is possible */ if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) { @@ -521,6 +526,15 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) return alloc; } +/** + * Aligned on sizeof(void*). + * Note : should happen only once, at workspace first initialization + */ +MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) +{ + return ZSTD_cwksp_reserve_object_aligned(ws, bytes, sizeof(void*)); +} + MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) { DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty"); From 4ce91cbf2bfecefcd99973a5e68711c388684d41 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 18 Oct 2024 16:47:41 -0700 Subject: [PATCH 24/44] fixed workspace alignment on non 64-bit systems --- lib/common/compiler.h | 2 ++ lib/compress/zstd_compress.c | 22 ++++++++++----------- lib/compress/zstd_cwksp.h | 37 ++++++++++++++++++++---------------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index fdf0dd18a..f4caeb5c0 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -278,6 +278,8 @@ * Alignment check *****************************************************************/ +#define ZSTD_IS_POWER_2(a) (((a) & ((a)-1)) == 0) + /* this test was initially positioned in mem.h, * but this file is removed (or replaced) for linux kernel * so it's now hosted in compiler.h, diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 40d3afaae..fcef55bf1 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2032,7 +2032,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, ZSTD_advanceHashSalt(ms); } else { /* When we are not salting we want to always memset the memory */ - ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned(ws, tagTableSize); + ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned64(ws, tagTableSize); ZSTD_memset(ms->tagTable, 0, tagTableSize); ms->hashSalt = 0; } @@ -2046,12 +2046,12 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, /* opt parser space */ if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) { DEBUGLOG(4, "reserving optimal parser space"); - ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (1<opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned)); - ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned)); - ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned)); - ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t)); - ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t)); + ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (1<opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxLL+1) * sizeof(unsigned)); + ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxML+1) * sizeof(unsigned)); + ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxOff+1) * sizeof(unsigned)); + ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t)); + ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t)); } ms->cParams = *cParams; @@ -2209,15 +2209,15 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, needsIndexReset, ZSTD_resetTarget_CCtx), ""); - zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned(ws, maxNbSeq * sizeof(seqDef)); + zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned64(ws, maxNbSeq * sizeof(seqDef)); /* ldm hash table */ if (params->ldmParams.enableLdm == ZSTD_ps_enable) { /* TODO: avoid memset? */ size_t const ldmHSize = ((size_t)1) << params->ldmParams.hashLog; - zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t)); + zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned64(ws, ldmHSize * sizeof(ldmEntry_t)); ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t)); - zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq)); + zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned64(ws, maxNbLdmSeq * sizeof(rawSeq)); zc->maxNbLdmSequences = maxNbLdmSeq; ZSTD_window_init(&zc->ldmState.window); @@ -2229,7 +2229,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize); zc->extSeqBufCapacity = maxNbExternalSeq; zc->extSeqBuf = - (ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence)); + (ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned64(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence)); } /* buffers */ diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index 239fcf6d2..dc0142098 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -206,9 +206,9 @@ MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) { /** * Align must be a power of 2. */ -MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) { +MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t align) { size_t const mask = align - 1; - assert((align & mask) == 0); + assert(ZSTD_IS_POWER_2(align)); return (size + mask) & ~mask; } @@ -266,7 +266,7 @@ MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) { MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) { size_t const alignBytesMask = alignBytes - 1; size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask; - assert((alignBytes & alignBytesMask) == 0); + assert(ZSTD_IS_POWER_2(alignBytes)); assert(bytes < alignBytes); return bytes; } @@ -408,7 +408,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t byt { size_t const alignedBytes = ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES); void* ptr = ZSTD_cwksp_reserve_internal(ws, alignedBytes, ZSTD_cwksp_alloc_aligned_init_once); - assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); if(ptr && ptr < ws->initOnceStart) { /* We assume the memory following the current allocation is either: * 1. Not usable as initOnce memory (end of workspace) @@ -428,12 +428,12 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t byt /** * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes). */ -MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) +MEM_STATIC void* ZSTD_cwksp_reserve_aligned64(ZSTD_cwksp* ws, size_t bytes) { void* const ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES), ZSTD_cwksp_alloc_aligned); - assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); return ptr; } @@ -479,17 +479,17 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) #endif assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); - assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); return alloc; } /** + * Aligned on sizeof(void*). * Note : should happen only once, at workspace first initialization */ -MEM_STATIC void* -ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t bytes, size_t alignment) +MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { - size_t const roundedBytes = ZSTD_cwksp_align(bytes, alignment); + size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*)); void* alloc = ws->objectEnd; void* end = (BYTE*)alloc + roundedBytes; @@ -501,8 +501,8 @@ ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t bytes, size_t alignment DEBUGLOG(4, "cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining", alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes); - assert((size_t)alloc % alignment == 0); - assert(bytes % alignment == 0); + assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0); + assert(bytes % ZSTD_ALIGNOF(void*) == 0); ZSTD_cwksp_assert_internal_consistency(ws); /* we must be in the first phase, no advance is possible */ if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) { @@ -525,14 +525,19 @@ ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t bytes, size_t alignment return alloc; } - /** - * Aligned on sizeof(void*). + * with alignment control * Note : should happen only once, at workspace first initialization */ -MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) +MEM_STATIC void* ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t byteSize, size_t alignment) { - return ZSTD_cwksp_reserve_object_aligned(ws, bytes, sizeof(void*)); + size_t const mask = alignment - 1; + size_t const surplus = (alignment > sizeof(void*)) ? alignment - sizeof(void*) : 0; + void* const start = ZSTD_cwksp_reserve_object(ws, byteSize + surplus); + if (start == NULL) return NULL; + if (surplus == 0) return start; + assert(ZSTD_IS_POWER_2(alignment)); + return (void*)(((size_t)start + surplus) & ~mask); } MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) From dac26eaeac5f500a3dd2ada7f51fbdbf937ce2ac Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 20 Oct 2024 17:07:43 -0700 Subject: [PATCH 25/44] updated regression test results --- tests/regression/results.csv | 914 +++++++++++++++++------------------ 1 file changed, 457 insertions(+), 457 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index e39abd66d..b32db43de 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -1,63 +1,63 @@ Data, Config, Method, Total compressed size -silesia.tar, level -5, compress simple, 6861055 -silesia.tar, level -3, compress simple, 6505483 -silesia.tar, level -1, compress simple, 6179047 -silesia.tar, level 0, compress simple, 4851407 -silesia.tar, level 1, compress simple, 5327717 -silesia.tar, level 3, compress simple, 4851407 -silesia.tar, level 4, compress simple, 4788821 -silesia.tar, level 5, compress simple, 4679004 -silesia.tar, level 6, compress simple, 4614561 -silesia.tar, level 7, compress simple, 4579828 -silesia.tar, level 9, compress simple, 4555448 -silesia.tar, level 13, compress simple, 4502956 -silesia.tar, level 16, compress simple, 4360385 -silesia.tar, level 19, compress simple, 4260939 -silesia.tar, uncompressed literals, compress simple, 4851407 -silesia.tar, uncompressed literals optimal, compress simple, 4260939 -silesia.tar, huffman literals, compress simple, 6179047 -github.tar, level -5, compress simple, 52115 -github.tar, level -3, compress simple, 45678 -github.tar, level -1, compress simple, 42560 -github.tar, level 0, compress simple, 38884 -github.tar, level 1, compress simple, 39200 -github.tar, level 3, compress simple, 38884 -github.tar, level 4, compress simple, 38880 -github.tar, level 5, compress simple, 39651 -github.tar, level 6, compress simple, 39282 -github.tar, level 7, compress simple, 38005 -github.tar, level 9, compress simple, 36723 +silesia.tar, level -5, compress simple, 6860782 +silesia.tar, level -3, compress simple, 6507448 +silesia.tar, level -1, compress simple, 6175582 +silesia.tar, level 0, compress simple, 4843429 +silesia.tar, level 1, compress simple, 5316794 +silesia.tar, level 3, compress simple, 4843429 +silesia.tar, level 4, compress simple, 4780657 +silesia.tar, level 5, compress simple, 4669650 +silesia.tar, level 6, compress simple, 4604925 +silesia.tar, level 7, compress simple, 4570873 +silesia.tar, level 9, compress simple, 4546477 +silesia.tar, level 13, compress simple, 4486256 +silesia.tar, level 16, compress simple, 4355572 +silesia.tar, level 19, compress simple, 4257629 +silesia.tar, uncompressed literals, compress simple, 4843429 +silesia.tar, uncompressed literals optimal, compress simple, 4257629 +silesia.tar, huffman literals, compress simple, 6175582 +github.tar, level -5, compress simple, 52320 +github.tar, level -3, compress simple, 45823 +github.tar, level -1, compress simple, 42740 +github.tar, level 0, compress simple, 39073 +github.tar, level 1, compress simple, 39444 +github.tar, level 3, compress simple, 39073 +github.tar, level 4, compress simple, 39068 +github.tar, level 5, compress simple, 39808 +github.tar, level 6, compress simple, 39455 +github.tar, level 7, compress simple, 38168 +github.tar, level 9, compress simple, 36897 github.tar, level 13, compress simple, 35501 github.tar, level 16, compress simple, 40466 github.tar, level 19, compress simple, 32262 -github.tar, uncompressed literals, compress simple, 38884 +github.tar, uncompressed literals, compress simple, 39073 github.tar, uncompressed literals optimal, compress simple, 32262 -github.tar, huffman literals, compress simple, 42560 -silesia, level -5, compress cctx, 6857372 -silesia, level -3, compress cctx, 6503412 -silesia, level -1, compress cctx, 6172202 -silesia, level 0, compress cctx, 4839431 -silesia, level 1, compress cctx, 5306632 -silesia, level 3, compress cctx, 4839431 -silesia, level 4, compress cctx, 4776557 -silesia, level 5, compress cctx, 4667668 -silesia, level 6, compress cctx, 4604351 -silesia, level 7, compress cctx, 4570271 -silesia, level 9, compress cctx, 4545850 -silesia, level 13, compress cctx, 4493990 -silesia, level 16, compress cctx, 4359652 -silesia, level 19, compress cctx, 4266582 -silesia, long distance mode, compress cctx, 4839431 -silesia, multithreaded, compress cctx, 4839431 -silesia, multithreaded long distance mode, compress cctx, 4839431 +github.tar, huffman literals, compress simple, 42740 +silesia, level -5, compress cctx, 6857776 +silesia, level -3, compress cctx, 6504756 +silesia, level -1, compress cctx, 6174127 +silesia, level 0, compress cctx, 4838417 +silesia, level 1, compress cctx, 5306931 +silesia, level 3, compress cctx, 4838417 +silesia, level 4, compress cctx, 4775359 +silesia, level 5, compress cctx, 4666524 +silesia, level 6, compress cctx, 4602031 +silesia, level 7, compress cctx, 4567954 +silesia, level 9, compress cctx, 4543669 +silesia, level 13, compress cctx, 4484875 +silesia, level 16, compress cctx, 4356207 +silesia, level 19, compress cctx, 4266751 +silesia, long distance mode, compress cctx, 4838417 +silesia, multithreaded, compress cctx, 4838417 +silesia, multithreaded long distance mode, compress cctx, 4838417 silesia, small window log, compress cctx, 7082907 -silesia, small hash log, compress cctx, 6526141 -silesia, small chain log, compress cctx, 4912197 -silesia, explicit params, compress cctx, 4794318 -silesia, uncompressed literals, compress cctx, 4839431 -silesia, uncompressed literals optimal, compress cctx, 4266582 -silesia, huffman literals, compress cctx, 6172202 -silesia, multithreaded with advanced params, compress cctx, 4839431 +silesia, small hash log, compress cctx, 6524931 +silesia, small chain log, compress cctx, 4912322 +silesia, explicit params, compress cctx, 4792640 +silesia, uncompressed literals, compress cctx, 4838417 +silesia, uncompressed literals optimal, compress cctx, 4266751 +silesia, huffman literals, compress cctx, 6174127 +silesia, multithreaded with advanced params, compress cctx, 4838417 github, level -5, compress cctx, 204407 github, level -5 with dict, compress cctx, 47581 github, level -3, compress cctx, 193253 @@ -97,57 +97,57 @@ github, uncompressed literals, compress github, uncompressed literals optimal, compress cctx, 132879 github, huffman literals, compress cctx, 175468 github, multithreaded with advanced params, compress cctx, 141069 -silesia, level -5, zstdcli, 6857420 -silesia, level -3, zstdcli, 6503460 -silesia, level -1, zstdcli, 6172250 -silesia, level 0, zstdcli, 4839479 -silesia, level 1, zstdcli, 5306680 -silesia, level 3, zstdcli, 4839479 -silesia, level 4, zstdcli, 4776605 -silesia, level 5, zstdcli, 4667716 -silesia, level 6, zstdcli, 4604399 -silesia, level 7, zstdcli, 4570319 -silesia, level 9, zstdcli, 4545898 -silesia, level 13, zstdcli, 4494038 -silesia, level 16, zstdcli, 4359700 -silesia, level 19, zstdcli, 4266630 -silesia, long distance mode, zstdcli, 4831224 -silesia, multithreaded, zstdcli, 4839479 -silesia, multithreaded long distance mode, zstdcli, 4831224 +silesia, level -5, zstdcli, 6856076 +silesia, level -3, zstdcli, 6505583 +silesia, level -1, zstdcli, 6172652 +silesia, level 0, zstdcli, 4838997 +silesia, level 1, zstdcli, 5306179 +silesia, level 3, zstdcli, 4838997 +silesia, level 4, zstdcli, 4775769 +silesia, level 5, zstdcli, 4666931 +silesia, level 6, zstdcli, 4602509 +silesia, level 7, zstdcli, 4568265 +silesia, level 9, zstdcli, 4544068 +silesia, level 13, zstdcli, 4484443 +silesia, level 16, zstdcli, 4357591 +silesia, level 19, zstdcli, 4266865 +silesia, long distance mode, zstdcli, 4830467 +silesia, multithreaded, zstdcli, 4838997 +silesia, multithreaded long distance mode, zstdcli, 4830467 silesia, small window log, zstdcli, 7094528 -silesia, small hash log, zstdcli, 6526189 -silesia, small chain log, zstdcli, 4912245 -silesia, explicit params, zstdcli, 4795840 -silesia, uncompressed literals, zstdcli, 5117005 -silesia, uncompressed literals optimal, zstdcli, 4316928 -silesia, huffman literals, zstdcli, 5321417 -silesia, multithreaded with advanced params, zstdcli, 5117005 -silesia.tar, level -5, zstdcli, 6862049 -silesia.tar, level -3, zstdcli, 6506509 -silesia.tar, level -1, zstdcli, 6179789 -silesia.tar, level 0, zstdcli, 4851482 -silesia.tar, level 1, zstdcli, 5329010 -silesia.tar, level 3, zstdcli, 4851482 -silesia.tar, level 4, zstdcli, 4789729 -silesia.tar, level 5, zstdcli, 4679860 -silesia.tar, level 6, zstdcli, 4615355 -silesia.tar, level 7, zstdcli, 4581791 -silesia.tar, level 9, zstdcli, 4555452 -silesia.tar, level 13, zstdcli, 4502960 -silesia.tar, level 16, zstdcli, 4360389 -silesia.tar, level 19, zstdcli, 4260943 -silesia.tar, no source size, zstdcli, 4851478 -silesia.tar, long distance mode, zstdcli, 4843159 -silesia.tar, multithreaded, zstdcli, 4851482 -silesia.tar, multithreaded long distance mode, zstdcli, 4843159 +silesia, small hash log, zstdcli, 6526639 +silesia, small chain log, zstdcli, 4911746 +silesia, explicit params, zstdcli, 4794378 +silesia, uncompressed literals, zstdcli, 5117843 +silesia, uncompressed literals optimal, zstdcli, 4317311 +silesia, huffman literals, zstdcli, 5320793 +silesia, multithreaded with advanced params, zstdcli, 5117843 +silesia.tar, level -5, zstdcli, 6860173 +silesia.tar, level -3, zstdcli, 6507196 +silesia.tar, level -1, zstdcli, 6177719 +silesia.tar, level 0, zstdcli, 4841906 +silesia.tar, level 1, zstdcli, 5313917 +silesia.tar, level 3, zstdcli, 4841906 +silesia.tar, level 4, zstdcli, 4780121 +silesia.tar, level 5, zstdcli, 4671144 +silesia.tar, level 6, zstdcli, 4606407 +silesia.tar, level 7, zstdcli, 4572666 +silesia.tar, level 9, zstdcli, 4546557 +silesia.tar, level 13, zstdcli, 4491076 +silesia.tar, level 16, zstdcli, 4356959 +silesia.tar, level 19, zstdcli, 4259787 +silesia.tar, no source size, zstdcli, 4841902 +silesia.tar, long distance mode, zstdcli, 4834266 +silesia.tar, multithreaded, zstdcli, 4841906 +silesia.tar, multithreaded long distance mode, zstdcli, 4834266 silesia.tar, small window log, zstdcli, 7100110 -silesia.tar, small hash log, zstdcli, 6529264 -silesia.tar, small chain log, zstdcli, 4917022 -silesia.tar, explicit params, zstdcli, 4821112 -silesia.tar, uncompressed literals, zstdcli, 5118944 -silesia.tar, uncompressed literals optimal, zstdcli, 4308455 -silesia.tar, huffman literals, zstdcli, 5342074 -silesia.tar, multithreaded with advanced params, zstdcli, 5118944 +silesia.tar, small hash log, zstdcli, 6530007 +silesia.tar, small chain log, zstdcli, 4916091 +silesia.tar, explicit params, zstdcli, 4809323 +silesia.tar, uncompressed literals, zstdcli, 5116446 +silesia.tar, uncompressed literals optimal, zstdcli, 4306844 +silesia.tar, huffman literals, zstdcli, 5326463 +silesia.tar, multithreaded with advanced params, zstdcli, 5116446 github, level -5, zstdcli, 206407 github, level -5 with dict, zstdcli, 47832 github, level -3, zstdcli, 195253 @@ -187,115 +187,115 @@ github, uncompressed literals, zstdcli, github, uncompressed literals optimal, zstdcli, 154667 github, huffman literals, zstdcli, 144365 github, multithreaded with advanced params, zstdcli, 167909 -github.tar, level -5, zstdcli, 52119 -github.tar, level -5 with dict, zstdcli, 51101 -github.tar, level -3, zstdcli, 45682 -github.tar, level -3 with dict, zstdcli, 44738 -github.tar, level -1, zstdcli, 42564 -github.tar, level -1 with dict, zstdcli, 41357 -github.tar, level 0, zstdcli, 38888 -github.tar, level 0 with dict, zstdcli, 37999 -github.tar, level 1, zstdcli, 39204 -github.tar, level 1 with dict, zstdcli, 38123 -github.tar, level 3, zstdcli, 38888 -github.tar, level 3 with dict, zstdcli, 37999 -github.tar, level 4, zstdcli, 38884 -github.tar, level 4 with dict, zstdcli, 37952 -github.tar, level 5, zstdcli, 39655 -github.tar, level 5 with dict, zstdcli, 39073 -github.tar, level 6, zstdcli, 39286 -github.tar, level 6 with dict, zstdcli, 38647 -github.tar, level 7, zstdcli, 38009 -github.tar, level 7 with dict, zstdcli, 37861 -github.tar, level 9, zstdcli, 36727 -github.tar, level 9 with dict, zstdcli, 36686 +github.tar, level -5, zstdcli, 52308 +github.tar, level -5 with dict, zstdcli, 51318 +github.tar, level -3, zstdcli, 45815 +github.tar, level -3 with dict, zstdcli, 44883 +github.tar, level -1, zstdcli, 42688 +github.tar, level -1 with dict, zstdcli, 41510 +github.tar, level 0, zstdcli, 39071 +github.tar, level 0 with dict, zstdcli, 38140 +github.tar, level 1, zstdcli, 39404 +github.tar, level 1 with dict, zstdcli, 38320 +github.tar, level 3, zstdcli, 39071 +github.tar, level 3 with dict, zstdcli, 38140 +github.tar, level 4, zstdcli, 39067 +github.tar, level 4 with dict, zstdcli, 38082 +github.tar, level 5, zstdcli, 39815 +github.tar, level 5 with dict, zstdcli, 39221 +github.tar, level 6, zstdcli, 39455 +github.tar, level 6 with dict, zstdcli, 38787 +github.tar, level 7, zstdcli, 38177 +github.tar, level 7 with dict, zstdcli, 38009 +github.tar, level 9, zstdcli, 36893 +github.tar, level 9 with dict, zstdcli, 36827 github.tar, level 13, zstdcli, 35505 github.tar, level 13 with dict, zstdcli, 37134 github.tar, level 16, zstdcli, 40470 github.tar, level 16 with dict, zstdcli, 33379 github.tar, level 19, zstdcli, 32266 github.tar, level 19 with dict, zstdcli, 32705 -github.tar, no source size, zstdcli, 38885 -github.tar, no source size with dict, zstdcli, 38115 -github.tar, long distance mode, zstdcli, 40227 -github.tar, multithreaded, zstdcli, 38888 -github.tar, multithreaded long distance mode, zstdcli, 40227 +github.tar, no source size, zstdcli, 39068 +github.tar, no source size with dict, zstdcli, 38274 +github.tar, long distance mode, zstdcli, 40381 +github.tar, multithreaded, zstdcli, 39071 +github.tar, multithreaded long distance mode, zstdcli, 40381 github.tar, small window log, zstdcli, 198539 github.tar, small hash log, zstdcli, 129874 github.tar, small chain log, zstdcli, 41673 -github.tar, explicit params, zstdcli, 41385 -github.tar, uncompressed literals, zstdcli, 41566 +github.tar, explicit params, zstdcli, 41588 +github.tar, uncompressed literals, zstdcli, 41704 github.tar, uncompressed literals optimal, zstdcli, 35360 -github.tar, huffman literals, zstdcli, 38857 -github.tar, multithreaded with advanced params, zstdcli, 41566 -silesia, level -5, advanced one pass, 6857372 -silesia, level -3, advanced one pass, 6503412 -silesia, level -1, advanced one pass, 6172202 -silesia, level 0, advanced one pass, 4839431 -silesia, level 1, advanced one pass, 5306632 -silesia, level 3, advanced one pass, 4839431 -silesia, level 4, advanced one pass, 4776557 -silesia, level 5 row 1, advanced one pass, 4667668 -silesia, level 5 row 2, advanced one pass, 4670326 -silesia, level 5, advanced one pass, 4667668 -silesia, level 6, advanced one pass, 4604351 -silesia, level 7 row 1, advanced one pass, 4570271 -silesia, level 7 row 2, advanced one pass, 4565169 -silesia, level 7, advanced one pass, 4570271 -silesia, level 9, advanced one pass, 4545850 -silesia, level 11 row 1, advanced one pass, 4505658 -silesia, level 11 row 2, advanced one pass, 4503429 -silesia, level 12 row 1, advanced one pass, 4505658 -silesia, level 12 row 2, advanced one pass, 4503429 -silesia, level 13, advanced one pass, 4493990 -silesia, level 16, advanced one pass, 4359652 -silesia, level 19, advanced one pass, 4266582 -silesia, no source size, advanced one pass, 4839431 -silesia, long distance mode, advanced one pass, 4831158 -silesia, multithreaded, advanced one pass, 4839431 -silesia, multithreaded long distance mode, advanced one pass, 4831176 +github.tar, huffman literals, zstdcli, 39046 +github.tar, multithreaded with advanced params, zstdcli, 41704 +silesia, level -5, advanced one pass, 6857776 +silesia, level -3, advanced one pass, 6504756 +silesia, level -1, advanced one pass, 6174127 +silesia, level 0, advanced one pass, 4838417 +silesia, level 1, advanced one pass, 5306931 +silesia, level 3, advanced one pass, 4838417 +silesia, level 4, advanced one pass, 4775359 +silesia, level 5 row 1, advanced one pass, 4666524 +silesia, level 5 row 2, advanced one pass, 4668976 +silesia, level 5, advanced one pass, 4666524 +silesia, level 6, advanced one pass, 4602031 +silesia, level 7 row 1, advanced one pass, 4567954 +silesia, level 7 row 2, advanced one pass, 4562774 +silesia, level 7, advanced one pass, 4567954 +silesia, level 9, advanced one pass, 4543669 +silesia, level 11 row 1, advanced one pass, 4503577 +silesia, level 11 row 2, advanced one pass, 4501229 +silesia, level 12 row 1, advanced one pass, 4503577 +silesia, level 12 row 2, advanced one pass, 4501229 +silesia, level 13, advanced one pass, 4484875 +silesia, level 16, advanced one pass, 4356207 +silesia, level 19, advanced one pass, 4266751 +silesia, no source size, advanced one pass, 4838417 +silesia, long distance mode, advanced one pass, 4830097 +silesia, multithreaded, advanced one pass, 4838949 +silesia, multithreaded long distance mode, advanced one pass, 4830419 silesia, small window log, advanced one pass, 7094480 -silesia, small hash log, advanced one pass, 6526141 -silesia, small chain log, advanced one pass, 4912197 -silesia, explicit params, advanced one pass, 4795840 -silesia, uncompressed literals, advanced one pass, 5116957 -silesia, uncompressed literals optimal, advanced one pass, 4316880 -silesia, huffman literals, advanced one pass, 5321369 -silesia, multithreaded with advanced params, advanced one pass, 5116957 -silesia.tar, level -5, advanced one pass, 6861055 -silesia.tar, level -3, advanced one pass, 6505483 -silesia.tar, level -1, advanced one pass, 6179047 -silesia.tar, level 0, advanced one pass, 4851407 -silesia.tar, level 1, advanced one pass, 5327717 -silesia.tar, level 3, advanced one pass, 4851407 -silesia.tar, level 4, advanced one pass, 4788821 -silesia.tar, level 5 row 1, advanced one pass, 4679004 -silesia.tar, level 5 row 2, advanced one pass, 4682334 -silesia.tar, level 5, advanced one pass, 4679004 -silesia.tar, level 6, advanced one pass, 4614561 -silesia.tar, level 7 row 1, advanced one pass, 4579828 -silesia.tar, level 7 row 2, advanced one pass, 4575602 -silesia.tar, level 7, advanced one pass, 4579828 -silesia.tar, level 9, advanced one pass, 4555448 -silesia.tar, level 11 row 1, advanced one pass, 4514962 -silesia.tar, level 11 row 2, advanced one pass, 4513816 -silesia.tar, level 12 row 1, advanced one pass, 4514517 -silesia.tar, level 12 row 2, advanced one pass, 4514007 -silesia.tar, level 13, advanced one pass, 4502956 -silesia.tar, level 16, advanced one pass, 4360385 -silesia.tar, level 19, advanced one pass, 4260939 -silesia.tar, no source size, advanced one pass, 4851407 -silesia.tar, long distance mode, advanced one pass, 4837775 -silesia.tar, multithreaded, advanced one pass, 4851478 -silesia.tar, multithreaded long distance mode, advanced one pass, 4843155 +silesia, small hash log, advanced one pass, 6524931 +silesia, small chain log, advanced one pass, 4912322 +silesia, explicit params, advanced one pass, 4794219 +silesia, uncompressed literals, advanced one pass, 5117482 +silesia, uncompressed literals optimal, advanced one pass, 4317186 +silesia, huffman literals, advanced one pass, 5321686 +silesia, multithreaded with advanced params, advanced one pass, 5117795 +silesia.tar, level -5, advanced one pass, 6860782 +silesia.tar, level -3, advanced one pass, 6507448 +silesia.tar, level -1, advanced one pass, 6175582 +silesia.tar, level 0, advanced one pass, 4843429 +silesia.tar, level 1, advanced one pass, 5316794 +silesia.tar, level 3, advanced one pass, 4843429 +silesia.tar, level 4, advanced one pass, 4780657 +silesia.tar, level 5 row 1, advanced one pass, 4669650 +silesia.tar, level 5 row 2, advanced one pass, 4673119 +silesia.tar, level 5, advanced one pass, 4669650 +silesia.tar, level 6, advanced one pass, 4604925 +silesia.tar, level 7 row 1, advanced one pass, 4570873 +silesia.tar, level 7 row 2, advanced one pass, 4566314 +silesia.tar, level 7, advanced one pass, 4570873 +silesia.tar, level 9, advanced one pass, 4546477 +silesia.tar, level 11 row 1, advanced one pass, 4505875 +silesia.tar, level 11 row 2, advanced one pass, 4504435 +silesia.tar, level 12 row 1, advanced one pass, 4505461 +silesia.tar, level 12 row 2, advanced one pass, 4504644 +silesia.tar, level 13, advanced one pass, 4486256 +silesia.tar, level 16, advanced one pass, 4355572 +silesia.tar, level 19, advanced one pass, 4257629 +silesia.tar, no source size, advanced one pass, 4843429 +silesia.tar, long distance mode, advanced one pass, 4830453 +silesia.tar, multithreaded, advanced one pass, 4841902 +silesia.tar, multithreaded long distance mode, advanced one pass, 4834262 silesia.tar, small window log, advanced one pass, 7100064 -silesia.tar, small hash log, advanced one pass, 6529206 -silesia.tar, small chain log, advanced one pass, 4917041 -silesia.tar, explicit params, advanced one pass, 4807274 -silesia.tar, uncompressed literals, advanced one pass, 5118848 -silesia.tar, uncompressed literals optimal, advanced one pass, 4308451 -silesia.tar, huffman literals, advanced one pass, 5341705 -silesia.tar, multithreaded with advanced params, advanced one pass, 5118940 +silesia.tar, small hash log, advanced one pass, 6530222 +silesia.tar, small chain log, advanced one pass, 4915689 +silesia.tar, explicit params, advanced one pass, 4797958 +silesia.tar, uncompressed literals, advanced one pass, 5116329 +silesia.tar, uncompressed literals optimal, advanced one pass, 4306289 +silesia.tar, huffman literals, advanced one pass, 5331382 +silesia.tar, multithreaded with advanced params, advanced one pass, 5116442 github, level -5, advanced one pass, 204407 github, level -5 with dict, advanced one pass, 45832 github, level -3, advanced one pass, 193253 @@ -421,100 +421,100 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced one pass, 152667 github, huffman literals, advanced one pass, 142365 github, multithreaded with advanced params, advanced one pass, 165909 -github.tar, level -5, advanced one pass, 52115 -github.tar, level -5 with dict, advanced one pass, 51097 -github.tar, level -3, advanced one pass, 45678 -github.tar, level -3 with dict, advanced one pass, 44734 -github.tar, level -1, advanced one pass, 42560 -github.tar, level -1 with dict, advanced one pass, 41353 -github.tar, level 0, advanced one pass, 38884 -github.tar, level 0 with dict, advanced one pass, 37995 -github.tar, level 0 with dict dms, advanced one pass, 38114 -github.tar, level 0 with dict dds, advanced one pass, 38114 -github.tar, level 0 with dict copy, advanced one pass, 37995 -github.tar, level 0 with dict load, advanced one pass, 37956 -github.tar, level 1, advanced one pass, 39200 -github.tar, level 1 with dict, advanced one pass, 38119 -github.tar, level 1 with dict dms, advanced one pass, 38406 -github.tar, level 1 with dict dds, advanced one pass, 38406 -github.tar, level 1 with dict copy, advanced one pass, 38119 -github.tar, level 1 with dict load, advanced one pass, 38364 -github.tar, level 3, advanced one pass, 38884 -github.tar, level 3 with dict, advanced one pass, 37995 -github.tar, level 3 with dict dms, advanced one pass, 38114 -github.tar, level 3 with dict dds, advanced one pass, 38114 -github.tar, level 3 with dict copy, advanced one pass, 37995 -github.tar, level 3 with dict load, advanced one pass, 37956 -github.tar, level 4, advanced one pass, 38880 -github.tar, level 4 with dict, advanced one pass, 37948 -github.tar, level 4 with dict dms, advanced one pass, 37995 -github.tar, level 4 with dict dds, advanced one pass, 37995 -github.tar, level 4 with dict copy, advanced one pass, 37948 -github.tar, level 4 with dict load, advanced one pass, 37927 -github.tar, level 5 row 1, advanced one pass, 39651 -github.tar, level 5 row 1 with dict dms, advanced one pass, 39043 -github.tar, level 5 row 1 with dict dds, advanced one pass, 39069 -github.tar, level 5 row 1 with dict copy, advanced one pass, 39145 -github.tar, level 5 row 1 with dict load, advanced one pass, 39000 -github.tar, level 5 row 2, advanced one pass, 39701 -github.tar, level 5 row 2 with dict dms, advanced one pass, 39365 -github.tar, level 5 row 2 with dict dds, advanced one pass, 39233 -github.tar, level 5 row 2 with dict copy, advanced one pass, 39715 -github.tar, level 5 row 2 with dict load, advanced one pass, 39158 -github.tar, level 5, advanced one pass, 39651 -github.tar, level 5 with dict, advanced one pass, 39145 -github.tar, level 5 with dict dms, advanced one pass, 39043 -github.tar, level 5 with dict dds, advanced one pass, 39069 -github.tar, level 5 with dict copy, advanced one pass, 39145 -github.tar, level 5 with dict load, advanced one pass, 39000 -github.tar, level 6, advanced one pass, 39282 -github.tar, level 6 with dict, advanced one pass, 38656 -github.tar, level 6 with dict dms, advanced one pass, 38640 -github.tar, level 6 with dict dds, advanced one pass, 38643 -github.tar, level 6 with dict copy, advanced one pass, 38656 -github.tar, level 6 with dict load, advanced one pass, 38647 -github.tar, level 7 row 1, advanced one pass, 38005 -github.tar, level 7 row 1 with dict dms, advanced one pass, 37832 -github.tar, level 7 row 1 with dict dds, advanced one pass, 37857 -github.tar, level 7 row 1 with dict copy, advanced one pass, 37839 -github.tar, level 7 row 1 with dict load, advanced one pass, 37286 -github.tar, level 7 row 2, advanced one pass, 38077 -github.tar, level 7 row 2 with dict dms, advanced one pass, 38012 -github.tar, level 7 row 2 with dict dds, advanced one pass, 38014 -github.tar, level 7 row 2 with dict copy, advanced one pass, 38101 -github.tar, level 7 row 2 with dict load, advanced one pass, 37402 -github.tar, level 7, advanced one pass, 38005 -github.tar, level 7 with dict, advanced one pass, 37839 -github.tar, level 7 with dict dms, advanced one pass, 37832 -github.tar, level 7 with dict dds, advanced one pass, 37857 -github.tar, level 7 with dict copy, advanced one pass, 37839 -github.tar, level 7 with dict load, advanced one pass, 37286 -github.tar, level 9, advanced one pass, 36723 -github.tar, level 9 with dict, advanced one pass, 36531 -github.tar, level 9 with dict dms, advanced one pass, 36615 -github.tar, level 9 with dict dds, advanced one pass, 36682 -github.tar, level 9 with dict copy, advanced one pass, 36531 -github.tar, level 9 with dict load, advanced one pass, 36322 -github.tar, level 11 row 1, advanced one pass, 36085 +github.tar, level -5, advanced one pass, 52320 +github.tar, level -5 with dict, advanced one pass, 51321 +github.tar, level -3, advanced one pass, 45823 +github.tar, level -3 with dict, advanced one pass, 44882 +github.tar, level -1, advanced one pass, 42740 +github.tar, level -1 with dict, advanced one pass, 41506 +github.tar, level 0, advanced one pass, 39073 +github.tar, level 0 with dict, advanced one pass, 38146 +github.tar, level 0 with dict dms, advanced one pass, 38262 +github.tar, level 0 with dict dds, advanced one pass, 38262 +github.tar, level 0 with dict copy, advanced one pass, 38146 +github.tar, level 0 with dict load, advanced one pass, 38107 +github.tar, level 1, advanced one pass, 39444 +github.tar, level 1 with dict, advanced one pass, 38338 +github.tar, level 1 with dict dms, advanced one pass, 38641 +github.tar, level 1 with dict dds, advanced one pass, 38641 +github.tar, level 1 with dict copy, advanced one pass, 38338 +github.tar, level 1 with dict load, advanced one pass, 38592 +github.tar, level 3, advanced one pass, 39073 +github.tar, level 3 with dict, advanced one pass, 38146 +github.tar, level 3 with dict dms, advanced one pass, 38262 +github.tar, level 3 with dict dds, advanced one pass, 38262 +github.tar, level 3 with dict copy, advanced one pass, 38146 +github.tar, level 3 with dict load, advanced one pass, 38107 +github.tar, level 4, advanced one pass, 39068 +github.tar, level 4 with dict, advanced one pass, 38081 +github.tar, level 4 with dict dms, advanced one pass, 38135 +github.tar, level 4 with dict dds, advanced one pass, 38135 +github.tar, level 4 with dict copy, advanced one pass, 38081 +github.tar, level 4 with dict load, advanced one pass, 38088 +github.tar, level 5 row 1, advanced one pass, 39808 +github.tar, level 5 row 1 with dict dms, advanced one pass, 39185 +github.tar, level 5 row 1 with dict dds, advanced one pass, 39213 +github.tar, level 5 row 1 with dict copy, advanced one pass, 39284 +github.tar, level 5 row 1 with dict load, advanced one pass, 39155 +github.tar, level 5 row 2, advanced one pass, 39851 +github.tar, level 5 row 2 with dict dms, advanced one pass, 39498 +github.tar, level 5 row 2 with dict dds, advanced one pass, 39364 +github.tar, level 5 row 2 with dict copy, advanced one pass, 39843 +github.tar, level 5 row 2 with dict load, advanced one pass, 39312 +github.tar, level 5, advanced one pass, 39808 +github.tar, level 5 with dict, advanced one pass, 39284 +github.tar, level 5 with dict dms, advanced one pass, 39185 +github.tar, level 5 with dict dds, advanced one pass, 39213 +github.tar, level 5 with dict copy, advanced one pass, 39284 +github.tar, level 5 with dict load, advanced one pass, 39155 +github.tar, level 6, advanced one pass, 39455 +github.tar, level 6 with dict, advanced one pass, 38808 +github.tar, level 6 with dict dms, advanced one pass, 38792 +github.tar, level 6 with dict dds, advanced one pass, 38790 +github.tar, level 6 with dict copy, advanced one pass, 38808 +github.tar, level 6 with dict load, advanced one pass, 38796 +github.tar, level 7 row 1, advanced one pass, 38168 +github.tar, level 7 row 1 with dict dms, advanced one pass, 38001 +github.tar, level 7 row 1 with dict dds, advanced one pass, 38008 +github.tar, level 7 row 1 with dict copy, advanced one pass, 37975 +github.tar, level 7 row 1 with dict load, advanced one pass, 37445 +github.tar, level 7 row 2, advanced one pass, 38235 +github.tar, level 7 row 2 with dict dms, advanced one pass, 38164 +github.tar, level 7 row 2 with dict dds, advanced one pass, 38169 +github.tar, level 7 row 2 with dict copy, advanced one pass, 38294 +github.tar, level 7 row 2 with dict load, advanced one pass, 37552 +github.tar, level 7, advanced one pass, 38168 +github.tar, level 7 with dict, advanced one pass, 37975 +github.tar, level 7 with dict dms, advanced one pass, 38001 +github.tar, level 7 with dict dds, advanced one pass, 38008 +github.tar, level 7 with dict copy, advanced one pass, 37975 +github.tar, level 7 with dict load, advanced one pass, 37445 +github.tar, level 9, advanced one pass, 36897 +github.tar, level 9 with dict, advanced one pass, 36689 +github.tar, level 9 with dict dms, advanced one pass, 36756 +github.tar, level 9 with dict dds, advanced one pass, 36817 +github.tar, level 9 with dict copy, advanced one pass, 36689 +github.tar, level 9 with dict load, advanced one pass, 36484 +github.tar, level 11 row 1, advanced one pass, 36234 github.tar, level 11 row 1 with dict dms, advanced one pass, 36963 github.tar, level 11 row 1 with dict dds, advanced one pass, 36963 github.tar, level 11 row 1 with dict copy, advanced one pass, 36557 -github.tar, level 11 row 1 with dict load, advanced one pass, 36423 -github.tar, level 11 row 2, advanced one pass, 36110 +github.tar, level 11 row 1 with dict load, advanced one pass, 36567 +github.tar, level 11 row 2, advanced one pass, 36217 github.tar, level 11 row 2 with dict dms, advanced one pass, 36963 github.tar, level 11 row 2 with dict dds, advanced one pass, 36963 github.tar, level 11 row 2 with dict copy, advanced one pass, 36557 -github.tar, level 11 row 2 with dict load, advanced one pass, 36459 -github.tar, level 12 row 1, advanced one pass, 36085 +github.tar, level 11 row 2 with dict load, advanced one pass, 36586 +github.tar, level 12 row 1, advanced one pass, 36234 github.tar, level 12 row 1 with dict dms, advanced one pass, 36986 github.tar, level 12 row 1 with dict dds, advanced one pass, 36986 github.tar, level 12 row 1 with dict copy, advanced one pass, 36609 -github.tar, level 12 row 1 with dict load, advanced one pass, 36423 -github.tar, level 12 row 2, advanced one pass, 36110 +github.tar, level 12 row 1 with dict load, advanced one pass, 36567 +github.tar, level 12 row 2, advanced one pass, 36217 github.tar, level 12 row 2 with dict dms, advanced one pass, 36986 github.tar, level 12 row 2 with dict dds, advanced one pass, 36986 github.tar, level 12 row 2 with dict copy, advanced one pass, 36609 -github.tar, level 12 row 2 with dict load, advanced one pass, 36459 +github.tar, level 12 row 2 with dict load, advanced one pass, 36586 github.tar, level 13, advanced one pass, 35501 github.tar, level 13 with dict, advanced one pass, 37130 github.tar, level 13 with dict dms, advanced one pass, 37220 @@ -533,87 +533,87 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced one pass, 32565 github.tar, level 19 with dict copy, advanced one pass, 32701 github.tar, level 19 with dict load, advanced one pass, 32428 -github.tar, no source size, advanced one pass, 38884 -github.tar, no source size with dict, advanced one pass, 37995 -github.tar, long distance mode, advanced one pass, 40242 -github.tar, multithreaded, advanced one pass, 38884 -github.tar, multithreaded long distance mode, advanced one pass, 40223 +github.tar, no source size, advanced one pass, 39073 +github.tar, no source size with dict, advanced one pass, 38146 +github.tar, long distance mode, advanced one pass, 40402 +github.tar, multithreaded, advanced one pass, 39067 +github.tar, multithreaded long distance mode, advanced one pass, 40377 github.tar, small window log, advanced one pass, 198535 github.tar, small hash log, advanced one pass, 129870 github.tar, small chain log, advanced one pass, 41669 -github.tar, explicit params, advanced one pass, 41385 -github.tar, uncompressed literals, advanced one pass, 41562 +github.tar, explicit params, advanced one pass, 41605 +github.tar, uncompressed literals, advanced one pass, 41709 github.tar, uncompressed literals optimal, advanced one pass, 35356 -github.tar, huffman literals, advanced one pass, 38853 -github.tar, multithreaded with advanced params, advanced one pass, 41562 -silesia, level -5, advanced one pass small out, 6857372 -silesia, level -3, advanced one pass small out, 6503412 -silesia, level -1, advanced one pass small out, 6172202 -silesia, level 0, advanced one pass small out, 4839431 -silesia, level 1, advanced one pass small out, 5306632 -silesia, level 3, advanced one pass small out, 4839431 -silesia, level 4, advanced one pass small out, 4776557 -silesia, level 5 row 1, advanced one pass small out, 4667668 -silesia, level 5 row 2, advanced one pass small out, 4670326 -silesia, level 5, advanced one pass small out, 4667668 -silesia, level 6, advanced one pass small out, 4604351 -silesia, level 7 row 1, advanced one pass small out, 4570271 -silesia, level 7 row 2, advanced one pass small out, 4565169 -silesia, level 7, advanced one pass small out, 4570271 -silesia, level 9, advanced one pass small out, 4545850 -silesia, level 11 row 1, advanced one pass small out, 4505658 -silesia, level 11 row 2, advanced one pass small out, 4503429 -silesia, level 12 row 1, advanced one pass small out, 4505658 -silesia, level 12 row 2, advanced one pass small out, 4503429 -silesia, level 13, advanced one pass small out, 4493990 -silesia, level 16, advanced one pass small out, 4359652 -silesia, level 19, advanced one pass small out, 4266582 -silesia, no source size, advanced one pass small out, 4839431 -silesia, long distance mode, advanced one pass small out, 4831158 -silesia, multithreaded, advanced one pass small out, 4839431 -silesia, multithreaded long distance mode, advanced one pass small out, 4831176 +github.tar, huffman literals, advanced one pass, 39099 +github.tar, multithreaded with advanced params, advanced one pass, 41700 +silesia, level -5, advanced one pass small out, 6857776 +silesia, level -3, advanced one pass small out, 6504756 +silesia, level -1, advanced one pass small out, 6174127 +silesia, level 0, advanced one pass small out, 4838417 +silesia, level 1, advanced one pass small out, 5306931 +silesia, level 3, advanced one pass small out, 4838417 +silesia, level 4, advanced one pass small out, 4775359 +silesia, level 5 row 1, advanced one pass small out, 4666524 +silesia, level 5 row 2, advanced one pass small out, 4668976 +silesia, level 5, advanced one pass small out, 4666524 +silesia, level 6, advanced one pass small out, 4602031 +silesia, level 7 row 1, advanced one pass small out, 4567954 +silesia, level 7 row 2, advanced one pass small out, 4562774 +silesia, level 7, advanced one pass small out, 4567954 +silesia, level 9, advanced one pass small out, 4543669 +silesia, level 11 row 1, advanced one pass small out, 4503577 +silesia, level 11 row 2, advanced one pass small out, 4501229 +silesia, level 12 row 1, advanced one pass small out, 4503577 +silesia, level 12 row 2, advanced one pass small out, 4501229 +silesia, level 13, advanced one pass small out, 4484875 +silesia, level 16, advanced one pass small out, 4356207 +silesia, level 19, advanced one pass small out, 4266751 +silesia, no source size, advanced one pass small out, 4838417 +silesia, long distance mode, advanced one pass small out, 4830097 +silesia, multithreaded, advanced one pass small out, 4838949 +silesia, multithreaded long distance mode, advanced one pass small out, 4830419 silesia, small window log, advanced one pass small out, 7094480 -silesia, small hash log, advanced one pass small out, 6526141 -silesia, small chain log, advanced one pass small out, 4912197 -silesia, explicit params, advanced one pass small out, 4795840 -silesia, uncompressed literals, advanced one pass small out, 5116957 -silesia, uncompressed literals optimal, advanced one pass small out, 4316880 -silesia, huffman literals, advanced one pass small out, 5321369 -silesia, multithreaded with advanced params, advanced one pass small out, 5116957 -silesia.tar, level -5, advanced one pass small out, 6861055 -silesia.tar, level -3, advanced one pass small out, 6505483 -silesia.tar, level -1, advanced one pass small out, 6179047 -silesia.tar, level 0, advanced one pass small out, 4851407 -silesia.tar, level 1, advanced one pass small out, 5327717 -silesia.tar, level 3, advanced one pass small out, 4851407 -silesia.tar, level 4, advanced one pass small out, 4788821 -silesia.tar, level 5 row 1, advanced one pass small out, 4679004 -silesia.tar, level 5 row 2, advanced one pass small out, 4682334 -silesia.tar, level 5, advanced one pass small out, 4679004 -silesia.tar, level 6, advanced one pass small out, 4614561 -silesia.tar, level 7 row 1, advanced one pass small out, 4579828 -silesia.tar, level 7 row 2, advanced one pass small out, 4575602 -silesia.tar, level 7, advanced one pass small out, 4579828 -silesia.tar, level 9, advanced one pass small out, 4555448 -silesia.tar, level 11 row 1, advanced one pass small out, 4514962 -silesia.tar, level 11 row 2, advanced one pass small out, 4513816 -silesia.tar, level 12 row 1, advanced one pass small out, 4514517 -silesia.tar, level 12 row 2, advanced one pass small out, 4514007 -silesia.tar, level 13, advanced one pass small out, 4502956 -silesia.tar, level 16, advanced one pass small out, 4360385 -silesia.tar, level 19, advanced one pass small out, 4260939 -silesia.tar, no source size, advanced one pass small out, 4851407 -silesia.tar, long distance mode, advanced one pass small out, 4837775 -silesia.tar, multithreaded, advanced one pass small out, 4851478 -silesia.tar, multithreaded long distance mode, advanced one pass small out, 4843155 +silesia, small hash log, advanced one pass small out, 6524931 +silesia, small chain log, advanced one pass small out, 4912322 +silesia, explicit params, advanced one pass small out, 4794219 +silesia, uncompressed literals, advanced one pass small out, 5117482 +silesia, uncompressed literals optimal, advanced one pass small out, 4317186 +silesia, huffman literals, advanced one pass small out, 5321686 +silesia, multithreaded with advanced params, advanced one pass small out, 5117795 +silesia.tar, level -5, advanced one pass small out, 6860782 +silesia.tar, level -3, advanced one pass small out, 6507448 +silesia.tar, level -1, advanced one pass small out, 6175582 +silesia.tar, level 0, advanced one pass small out, 4843429 +silesia.tar, level 1, advanced one pass small out, 5316794 +silesia.tar, level 3, advanced one pass small out, 4843429 +silesia.tar, level 4, advanced one pass small out, 4780657 +silesia.tar, level 5 row 1, advanced one pass small out, 4669650 +silesia.tar, level 5 row 2, advanced one pass small out, 4673119 +silesia.tar, level 5, advanced one pass small out, 4669650 +silesia.tar, level 6, advanced one pass small out, 4604925 +silesia.tar, level 7 row 1, advanced one pass small out, 4570873 +silesia.tar, level 7 row 2, advanced one pass small out, 4566314 +silesia.tar, level 7, advanced one pass small out, 4570873 +silesia.tar, level 9, advanced one pass small out, 4546477 +silesia.tar, level 11 row 1, advanced one pass small out, 4505875 +silesia.tar, level 11 row 2, advanced one pass small out, 4504435 +silesia.tar, level 12 row 1, advanced one pass small out, 4505461 +silesia.tar, level 12 row 2, advanced one pass small out, 4504644 +silesia.tar, level 13, advanced one pass small out, 4486256 +silesia.tar, level 16, advanced one pass small out, 4355572 +silesia.tar, level 19, advanced one pass small out, 4257629 +silesia.tar, no source size, advanced one pass small out, 4843429 +silesia.tar, long distance mode, advanced one pass small out, 4830453 +silesia.tar, multithreaded, advanced one pass small out, 4841902 +silesia.tar, multithreaded long distance mode, advanced one pass small out, 4834262 silesia.tar, small window log, advanced one pass small out, 7100064 -silesia.tar, small hash log, advanced one pass small out, 6529206 -silesia.tar, small chain log, advanced one pass small out, 4917041 -silesia.tar, explicit params, advanced one pass small out, 4807274 -silesia.tar, uncompressed literals, advanced one pass small out, 5118848 -silesia.tar, uncompressed literals optimal, advanced one pass small out, 4308451 -silesia.tar, huffman literals, advanced one pass small out, 5341705 -silesia.tar, multithreaded with advanced params, advanced one pass small out, 5118940 +silesia.tar, small hash log, advanced one pass small out, 6530222 +silesia.tar, small chain log, advanced one pass small out, 4915689 +silesia.tar, explicit params, advanced one pass small out, 4797958 +silesia.tar, uncompressed literals, advanced one pass small out, 5116329 +silesia.tar, uncompressed literals optimal, advanced one pass small out, 4306289 +silesia.tar, huffman literals, advanced one pass small out, 5331382 +silesia.tar, multithreaded with advanced params, advanced one pass small out, 5116442 github, level -5, advanced one pass small out, 204407 github, level -5 with dict, advanced one pass small out, 45832 github, level -3, advanced one pass small out, 193253 @@ -739,100 +739,100 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced one pass small out, 152667 github, huffman literals, advanced one pass small out, 142365 github, multithreaded with advanced params, advanced one pass small out, 165909 -github.tar, level -5, advanced one pass small out, 52115 -github.tar, level -5 with dict, advanced one pass small out, 51097 -github.tar, level -3, advanced one pass small out, 45678 -github.tar, level -3 with dict, advanced one pass small out, 44734 -github.tar, level -1, advanced one pass small out, 42560 -github.tar, level -1 with dict, advanced one pass small out, 41353 -github.tar, level 0, advanced one pass small out, 38884 -github.tar, level 0 with dict, advanced one pass small out, 37995 -github.tar, level 0 with dict dms, advanced one pass small out, 38114 -github.tar, level 0 with dict dds, advanced one pass small out, 38114 -github.tar, level 0 with dict copy, advanced one pass small out, 37995 -github.tar, level 0 with dict load, advanced one pass small out, 37956 -github.tar, level 1, advanced one pass small out, 39200 -github.tar, level 1 with dict, advanced one pass small out, 38119 -github.tar, level 1 with dict dms, advanced one pass small out, 38406 -github.tar, level 1 with dict dds, advanced one pass small out, 38406 -github.tar, level 1 with dict copy, advanced one pass small out, 38119 -github.tar, level 1 with dict load, advanced one pass small out, 38364 -github.tar, level 3, advanced one pass small out, 38884 -github.tar, level 3 with dict, advanced one pass small out, 37995 -github.tar, level 3 with dict dms, advanced one pass small out, 38114 -github.tar, level 3 with dict dds, advanced one pass small out, 38114 -github.tar, level 3 with dict copy, advanced one pass small out, 37995 -github.tar, level 3 with dict load, advanced one pass small out, 37956 -github.tar, level 4, advanced one pass small out, 38880 -github.tar, level 4 with dict, advanced one pass small out, 37948 -github.tar, level 4 with dict dms, advanced one pass small out, 37995 -github.tar, level 4 with dict dds, advanced one pass small out, 37995 -github.tar, level 4 with dict copy, advanced one pass small out, 37948 -github.tar, level 4 with dict load, advanced one pass small out, 37927 -github.tar, level 5 row 1, advanced one pass small out, 39651 -github.tar, level 5 row 1 with dict dms, advanced one pass small out, 39043 -github.tar, level 5 row 1 with dict dds, advanced one pass small out, 39069 -github.tar, level 5 row 1 with dict copy, advanced one pass small out, 39145 -github.tar, level 5 row 1 with dict load, advanced one pass small out, 39000 -github.tar, level 5 row 2, advanced one pass small out, 39701 -github.tar, level 5 row 2 with dict dms, advanced one pass small out, 39365 -github.tar, level 5 row 2 with dict dds, advanced one pass small out, 39233 -github.tar, level 5 row 2 with dict copy, advanced one pass small out, 39715 -github.tar, level 5 row 2 with dict load, advanced one pass small out, 39158 -github.tar, level 5, advanced one pass small out, 39651 -github.tar, level 5 with dict, advanced one pass small out, 39145 -github.tar, level 5 with dict dms, advanced one pass small out, 39043 -github.tar, level 5 with dict dds, advanced one pass small out, 39069 -github.tar, level 5 with dict copy, advanced one pass small out, 39145 -github.tar, level 5 with dict load, advanced one pass small out, 39000 -github.tar, level 6, advanced one pass small out, 39282 -github.tar, level 6 with dict, advanced one pass small out, 38656 -github.tar, level 6 with dict dms, advanced one pass small out, 38640 -github.tar, level 6 with dict dds, advanced one pass small out, 38643 -github.tar, level 6 with dict copy, advanced one pass small out, 38656 -github.tar, level 6 with dict load, advanced one pass small out, 38647 -github.tar, level 7 row 1, advanced one pass small out, 38005 -github.tar, level 7 row 1 with dict dms, advanced one pass small out, 37832 -github.tar, level 7 row 1 with dict dds, advanced one pass small out, 37857 -github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37839 -github.tar, level 7 row 1 with dict load, advanced one pass small out, 37286 -github.tar, level 7 row 2, advanced one pass small out, 38077 -github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38012 -github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38014 -github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38101 -github.tar, level 7 row 2 with dict load, advanced one pass small out, 37402 -github.tar, level 7, advanced one pass small out, 38005 -github.tar, level 7 with dict, advanced one pass small out, 37839 -github.tar, level 7 with dict dms, advanced one pass small out, 37832 -github.tar, level 7 with dict dds, advanced one pass small out, 37857 -github.tar, level 7 with dict copy, advanced one pass small out, 37839 -github.tar, level 7 with dict load, advanced one pass small out, 37286 -github.tar, level 9, advanced one pass small out, 36723 -github.tar, level 9 with dict, advanced one pass small out, 36531 -github.tar, level 9 with dict dms, advanced one pass small out, 36615 -github.tar, level 9 with dict dds, advanced one pass small out, 36682 -github.tar, level 9 with dict copy, advanced one pass small out, 36531 -github.tar, level 9 with dict load, advanced one pass small out, 36322 -github.tar, level 11 row 1, advanced one pass small out, 36085 +github.tar, level -5, advanced one pass small out, 52320 +github.tar, level -5 with dict, advanced one pass small out, 51321 +github.tar, level -3, advanced one pass small out, 45823 +github.tar, level -3 with dict, advanced one pass small out, 44882 +github.tar, level -1, advanced one pass small out, 42740 +github.tar, level -1 with dict, advanced one pass small out, 41506 +github.tar, level 0, advanced one pass small out, 39073 +github.tar, level 0 with dict, advanced one pass small out, 38146 +github.tar, level 0 with dict dms, advanced one pass small out, 38262 +github.tar, level 0 with dict dds, advanced one pass small out, 38262 +github.tar, level 0 with dict copy, advanced one pass small out, 38146 +github.tar, level 0 with dict load, advanced one pass small out, 38107 +github.tar, level 1, advanced one pass small out, 39444 +github.tar, level 1 with dict, advanced one pass small out, 38338 +github.tar, level 1 with dict dms, advanced one pass small out, 38641 +github.tar, level 1 with dict dds, advanced one pass small out, 38641 +github.tar, level 1 with dict copy, advanced one pass small out, 38338 +github.tar, level 1 with dict load, advanced one pass small out, 38592 +github.tar, level 3, advanced one pass small out, 39073 +github.tar, level 3 with dict, advanced one pass small out, 38146 +github.tar, level 3 with dict dms, advanced one pass small out, 38262 +github.tar, level 3 with dict dds, advanced one pass small out, 38262 +github.tar, level 3 with dict copy, advanced one pass small out, 38146 +github.tar, level 3 with dict load, advanced one pass small out, 38107 +github.tar, level 4, advanced one pass small out, 39068 +github.tar, level 4 with dict, advanced one pass small out, 38081 +github.tar, level 4 with dict dms, advanced one pass small out, 38135 +github.tar, level 4 with dict dds, advanced one pass small out, 38135 +github.tar, level 4 with dict copy, advanced one pass small out, 38081 +github.tar, level 4 with dict load, advanced one pass small out, 38088 +github.tar, level 5 row 1, advanced one pass small out, 39808 +github.tar, level 5 row 1 with dict dms, advanced one pass small out, 39185 +github.tar, level 5 row 1 with dict dds, advanced one pass small out, 39213 +github.tar, level 5 row 1 with dict copy, advanced one pass small out, 39284 +github.tar, level 5 row 1 with dict load, advanced one pass small out, 39155 +github.tar, level 5 row 2, advanced one pass small out, 39851 +github.tar, level 5 row 2 with dict dms, advanced one pass small out, 39498 +github.tar, level 5 row 2 with dict dds, advanced one pass small out, 39364 +github.tar, level 5 row 2 with dict copy, advanced one pass small out, 39843 +github.tar, level 5 row 2 with dict load, advanced one pass small out, 39312 +github.tar, level 5, advanced one pass small out, 39808 +github.tar, level 5 with dict, advanced one pass small out, 39284 +github.tar, level 5 with dict dms, advanced one pass small out, 39185 +github.tar, level 5 with dict dds, advanced one pass small out, 39213 +github.tar, level 5 with dict copy, advanced one pass small out, 39284 +github.tar, level 5 with dict load, advanced one pass small out, 39155 +github.tar, level 6, advanced one pass small out, 39455 +github.tar, level 6 with dict, advanced one pass small out, 38808 +github.tar, level 6 with dict dms, advanced one pass small out, 38792 +github.tar, level 6 with dict dds, advanced one pass small out, 38790 +github.tar, level 6 with dict copy, advanced one pass small out, 38808 +github.tar, level 6 with dict load, advanced one pass small out, 38796 +github.tar, level 7 row 1, advanced one pass small out, 38168 +github.tar, level 7 row 1 with dict dms, advanced one pass small out, 38001 +github.tar, level 7 row 1 with dict dds, advanced one pass small out, 38008 +github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37975 +github.tar, level 7 row 1 with dict load, advanced one pass small out, 37445 +github.tar, level 7 row 2, advanced one pass small out, 38235 +github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38164 +github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38169 +github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38294 +github.tar, level 7 row 2 with dict load, advanced one pass small out, 37552 +github.tar, level 7, advanced one pass small out, 38168 +github.tar, level 7 with dict, advanced one pass small out, 37975 +github.tar, level 7 with dict dms, advanced one pass small out, 38001 +github.tar, level 7 with dict dds, advanced one pass small out, 38008 +github.tar, level 7 with dict copy, advanced one pass small out, 37975 +github.tar, level 7 with dict load, advanced one pass small out, 37445 +github.tar, level 9, advanced one pass small out, 36897 +github.tar, level 9 with dict, advanced one pass small out, 36689 +github.tar, level 9 with dict dms, advanced one pass small out, 36756 +github.tar, level 9 with dict dds, advanced one pass small out, 36817 +github.tar, level 9 with dict copy, advanced one pass small out, 36689 +github.tar, level 9 with dict load, advanced one pass small out, 36484 +github.tar, level 11 row 1, advanced one pass small out, 36234 github.tar, level 11 row 1 with dict dms, advanced one pass small out, 36963 github.tar, level 11 row 1 with dict dds, advanced one pass small out, 36963 github.tar, level 11 row 1 with dict copy, advanced one pass small out, 36557 -github.tar, level 11 row 1 with dict load, advanced one pass small out, 36423 -github.tar, level 11 row 2, advanced one pass small out, 36110 +github.tar, level 11 row 1 with dict load, advanced one pass small out, 36567 +github.tar, level 11 row 2, advanced one pass small out, 36217 github.tar, level 11 row 2 with dict dms, advanced one pass small out, 36963 github.tar, level 11 row 2 with dict dds, advanced one pass small out, 36963 github.tar, level 11 row 2 with dict copy, advanced one pass small out, 36557 -github.tar, level 11 row 2 with dict load, advanced one pass small out, 36459 -github.tar, level 12 row 1, advanced one pass small out, 36085 +github.tar, level 11 row 2 with dict load, advanced one pass small out, 36586 +github.tar, level 12 row 1, advanced one pass small out, 36234 github.tar, level 12 row 1 with dict dms, advanced one pass small out, 36986 github.tar, level 12 row 1 with dict dds, advanced one pass small out, 36986 github.tar, level 12 row 1 with dict copy, advanced one pass small out, 36609 -github.tar, level 12 row 1 with dict load, advanced one pass small out, 36423 -github.tar, level 12 row 2, advanced one pass small out, 36110 +github.tar, level 12 row 1 with dict load, advanced one pass small out, 36567 +github.tar, level 12 row 2, advanced one pass small out, 36217 github.tar, level 12 row 2 with dict dms, advanced one pass small out, 36986 github.tar, level 12 row 2 with dict dds, advanced one pass small out, 36986 github.tar, level 12 row 2 with dict copy, advanced one pass small out, 36609 -github.tar, level 12 row 2 with dict load, advanced one pass small out, 36459 +github.tar, level 12 row 2 with dict load, advanced one pass small out, 36586 github.tar, level 13, advanced one pass small out, 35501 github.tar, level 13 with dict, advanced one pass small out, 37130 github.tar, level 13 with dict dms, advanced one pass small out, 37220 @@ -851,19 +851,19 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced one pass small out, 32565 github.tar, level 19 with dict copy, advanced one pass small out, 32701 github.tar, level 19 with dict load, advanced one pass small out, 32428 -github.tar, no source size, advanced one pass small out, 38884 -github.tar, no source size with dict, advanced one pass small out, 37995 -github.tar, long distance mode, advanced one pass small out, 40242 -github.tar, multithreaded, advanced one pass small out, 38884 -github.tar, multithreaded long distance mode, advanced one pass small out, 40223 +github.tar, no source size, advanced one pass small out, 39073 +github.tar, no source size with dict, advanced one pass small out, 38146 +github.tar, long distance mode, advanced one pass small out, 40402 +github.tar, multithreaded, advanced one pass small out, 39067 +github.tar, multithreaded long distance mode, advanced one pass small out, 40377 github.tar, small window log, advanced one pass small out, 198535 github.tar, small hash log, advanced one pass small out, 129870 github.tar, small chain log, advanced one pass small out, 41669 -github.tar, explicit params, advanced one pass small out, 41385 -github.tar, uncompressed literals, advanced one pass small out, 41562 +github.tar, explicit params, advanced one pass small out, 41605 +github.tar, uncompressed literals, advanced one pass small out, 41709 github.tar, uncompressed literals optimal, advanced one pass small out, 35356 -github.tar, huffman literals, advanced one pass small out, 38853 -github.tar, multithreaded with advanced params, advanced one pass small out, 41562 +github.tar, huffman literals, advanced one pass small out, 39099 +github.tar, multithreaded with advanced params, advanced one pass small out, 41700 silesia, level -5, advanced streaming, 6854744 silesia, level -3, advanced streaming, 6503319 silesia, level -1, advanced streaming, 6172207 @@ -888,8 +888,8 @@ silesia, level 16, advanced silesia, level 19, advanced streaming, 4266582 silesia, no source size, advanced streaming, 4839395 silesia, long distance mode, advanced streaming, 4831158 -silesia, multithreaded, advanced streaming, 4839431 -silesia, multithreaded long distance mode, advanced streaming, 4831176 +silesia, multithreaded, advanced streaming, 4838949 +silesia, multithreaded long distance mode, advanced streaming, 4830419 silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6526141 silesia, small chain log, advanced streaming, 4912197 @@ -897,7 +897,7 @@ silesia, explicit params, advanced silesia, uncompressed literals, advanced streaming, 5116957 silesia, uncompressed literals optimal, advanced streaming, 4316880 silesia, huffman literals, advanced streaming, 5321370 -silesia, multithreaded with advanced params, advanced streaming, 5116957 +silesia, multithreaded with advanced params, advanced streaming, 5117795 silesia.tar, level -5, advanced streaming, 6856523 silesia.tar, level -3, advanced streaming, 6505954 silesia.tar, level -1, advanced streaming, 6179056 @@ -922,8 +922,8 @@ silesia.tar, level 16, advanced silesia.tar, level 19, advanced streaming, 4260939 silesia.tar, no source size, advanced streaming, 4858628 silesia.tar, long distance mode, advanced streaming, 4837775 -silesia.tar, multithreaded, advanced streaming, 4851478 -silesia.tar, multithreaded long distance mode, advanced streaming, 4843155 +silesia.tar, multithreaded, advanced streaming, 4841902 +silesia.tar, multithreaded long distance mode, advanced streaming, 4834262 silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529209 silesia.tar, small chain log, advanced streaming, 4917021 @@ -931,7 +931,7 @@ silesia.tar, explicit params, advanced silesia.tar, uncompressed literals, advanced streaming, 5126542 silesia.tar, uncompressed literals optimal, advanced streaming, 4308451 silesia.tar, huffman literals, advanced streaming, 5341712 -silesia.tar, multithreaded with advanced params, advanced streaming, 5118940 +silesia.tar, multithreaded with advanced params, advanced streaming, 5116442 github, level -5, advanced streaming, 204407 github, level -5 with dict, advanced streaming, 45832 github, level -3, advanced streaming, 193253 @@ -1172,8 +1172,8 @@ github.tar, level 19 with dict load, advanced github.tar, no source size, advanced streaming, 38881 github.tar, no source size with dict, advanced streaming, 38111 github.tar, long distance mode, advanced streaming, 40242 -github.tar, multithreaded, advanced streaming, 38884 -github.tar, multithreaded long distance mode, advanced streaming, 40223 +github.tar, multithreaded, advanced streaming, 39067 +github.tar, multithreaded long distance mode, advanced streaming, 40377 github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 @@ -1181,7 +1181,7 @@ github.tar, explicit params, advanced github.tar, uncompressed literals, advanced streaming, 41562 github.tar, uncompressed literals optimal, advanced streaming, 35356 github.tar, huffman literals, advanced streaming, 38853 -github.tar, multithreaded with advanced params, advanced streaming, 41562 +github.tar, multithreaded with advanced params, advanced streaming, 41700 silesia, level -5, old streaming, 6854744 silesia, level -3, old streaming, 6503319 silesia, level -1, old streaming, 6172207 From 1c62e714ab9f53aefd6478e033ce448597b68fab Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 20 Oct 2024 17:16:17 -0700 Subject: [PATCH 26/44] minor split optimization let's fill the initial stats directly into target fingerprint --- lib/compress/zstd_preSplit.c | 10 +++++----- lib/compress/zstd_preSplit.h | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index ceac5c91f..f831dabde 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -18,7 +18,7 @@ #define BLOCKSIZE_MIN 3500 #define THRESHOLD_PENALTY_RATE 16 #define THRESHOLD_BASE (THRESHOLD_PENALTY_RATE - 2) -#define THRESHOLD_PENALTY 4 +#define THRESHOLD_PENALTY 3 #define HASHLENGTH 2 #define HASHLOG 10 @@ -84,8 +84,8 @@ static int compareFingerprints(const FingerPrint* ref, const FingerPrint* newfp, int penalty) { - if (ref->nbEvents <= BLOCKSIZE_MIN) - return 0; + assert(ref->nbEvents > 0); + assert(newfp->nbEvents > 0); { S64 p50 = ref->nbEvents * newfp->nbEvents; S64 deviation = fpDistance(ref, newfp); S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; @@ -140,7 +140,8 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; initStats(fpstats); - for (pos = 0; pos < blockSizeMax;) { + recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE); + for (pos = CHUNKSIZE; pos < blockSizeMax; pos += CHUNKSIZE) { assert(pos <= blockSizeMax - CHUNKSIZE); recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE); if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { @@ -150,7 +151,6 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); penalty = penalty - 1 + (penalty == 0); } - pos += CHUNKSIZE; } return blockSizeMax; (void)flushEvents; (void)removeEvents; diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index b0b6bb762..7b6aadd0b 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -22,6 +22,10 @@ extern "C" { /* note: * @workspace must be aligned on 8-bytes boundaries * @wkspSize must be at least >= ZSTD_SLIPBLOCK_WORKSPACESIZE + * note2: + * for the time being, this function only accepts full 128 KB blocks, + * therefore @blockSizeMax must be == 128 KB. + * This could be extended to smaller sizes in the future. */ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax, void* workspace, size_t wkspSize); From a167571db535377070c43098932a7747d859177c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 21 Oct 2024 14:56:43 -0700 Subject: [PATCH 27/44] added a faster block splitter variant that samples 1 in 5 positions. This variant is fast enough for lazy2 and btlazy2, but it's less good in combination with post-splitter at higher levels (>= btopt). --- lib/compress/zstd_compress.c | 6 +++-- lib/compress/zstd_preSplit.c | 50 ++++++++++++++++++++++++++---------- lib/compress/zstd_preSplit.h | 6 ++++- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index fcef55bf1..e7a07a484 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4500,8 +4500,10 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src return MIN(srcSize, blockSizeMax); /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for btlazy2+ strategies */ - if (strat >= ZSTD_btlazy2) - return ZSTD_splitBlock_4k(src, srcSize, blockSizeMax, cctx->tmpWorkspace, cctx->tmpWkspSize); + if (strat >= ZSTD_btopt) + return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); + if (strat >= ZSTD_lazy2) + return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index f831dabde..721a52deb 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -46,22 +46,36 @@ static void initStats(FPStats* fpstats) ZSTD_memset(fpstats, 0, sizeof(FPStats)); } -static void addToFingerprint(FingerPrint* fp, const void* src, size_t s) +FORCE_INLINE_TEMPLATE void addEvents_generic(FingerPrint* fp, const void* src, size_t srcSize, size_t samplingRate) { const char* p = (const char*)src; - size_t limit = s - HASHLENGTH + 1; + size_t limit = srcSize - HASHLENGTH + 1; size_t n; - assert(s >= HASHLENGTH); - for (n = 0; n < limit; n++) { - fp->events[hash2(p++)]++; + assert(srcSize >= HASHLENGTH); + for (n = 0; n < limit; n+=samplingRate) { + fp->events[hash2(p+n)]++; } - fp->nbEvents += limit; + fp->nbEvents += limit/samplingRate; } -static void recordFingerprint(FingerPrint* fp, const void* src, size_t s) +#define ADDEVENTS_RATE(_rate) ZSTD_addEvents_##_rate + +#define ZSTD_GEN_ADDEVENTS_SAMPLE(_rate) \ + static void ADDEVENTS_RATE(_rate)(FingerPrint* fp, const void* src, size_t srcSize) \ + { \ + return addEvents_generic(fp, src, srcSize, _rate); \ + } + +ZSTD_GEN_ADDEVENTS_SAMPLE(1); +ZSTD_GEN_ADDEVENTS_SAMPLE(5); + + +typedef void (*addEvents_f)(FingerPrint* fp, const void* src, size_t srcSize); + +static void recordFingerprint(FingerPrint* fp, const void* src, size_t s, addEvents_f addEvents) { ZSTD_memset(fp, 0, sizeof(*fp)); - addToFingerprint(fp, src, s); + addEvents(fp, src, s); } static S64 abs64(S64 i) { return (i < 0) ? -i : i; } @@ -124,8 +138,8 @@ static void removeEvents(FingerPrint* acc, const FingerPrint* slice) #define CHUNKSIZE (8 << 10) /* Note: technically, we use CHUNKSIZE, so that's 8 KB */ -size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, - size_t blockSizeMax, +static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, + size_t blockSizeMax, addEvents_f f, void* workspace, size_t wkspSize) { FPStats* const fpstats = (FPStats*)workspace; @@ -140,18 +154,28 @@ size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; initStats(fpstats); - recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE); + recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE, f); for (pos = CHUNKSIZE; pos < blockSizeMax; pos += CHUNKSIZE) { assert(pos <= blockSizeMax - CHUNKSIZE); - recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE); + recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE, f); if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { return pos; } else { mergeEvents(&fpstats->pastEvents, &fpstats->newEvents); - ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); penalty = penalty - 1 + (penalty == 0); } } return blockSizeMax; (void)flushEvents; (void)removeEvents; } + +size_t ZSTD_splitBlock(const void* src, size_t srcSize, + size_t blockSizeMax, ZSTD_SplitBlock_strategy_e splitStrat, + void* workspace, size_t wkspSize) +{ + if (splitStrat == split_lvl2) + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(1), workspace, wkspSize); + + assert(splitStrat == split_lvl1); + return ZSTD_splitBlock_byChunks(src, srcSize, blockSizeMax, ADDEVENTS_RATE(5), workspace, wkspSize); +} diff --git a/lib/compress/zstd_preSplit.h b/lib/compress/zstd_preSplit.h index 7b6aadd0b..2c87d34a6 100644 --- a/lib/compress/zstd_preSplit.h +++ b/lib/compress/zstd_preSplit.h @@ -17,6 +17,8 @@ extern "C" { #endif +typedef enum { split_lvl1, split_lvl2 } ZSTD_SplitBlock_strategy_e; + #define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208 /* note: @@ -27,7 +29,9 @@ extern "C" { * therefore @blockSizeMax must be == 128 KB. * This could be extended to smaller sizes in the future. */ -size_t ZSTD_splitBlock_4k(const void* src, size_t srcSize, size_t blockSizeMax, void* workspace, size_t wkspSize); +size_t ZSTD_splitBlock(const void* src, size_t srcSize, + size_t blockSizeMax, ZSTD_SplitBlock_strategy_e splitStrat, + void* workspace, size_t wkspSize); #if defined (__cplusplus) } From 7bad787d8bcae57cf0bdcbca00b3f106ae557b75 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 15:12:46 -0700 Subject: [PATCH 28/44] made ZSTD_isPower2() an inline function --- lib/common/compiler.h | 6 +++++- lib/compress/zstd_cwksp.h | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index f4caeb5c0..b6cbcee03 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -278,7 +278,11 @@ * Alignment check *****************************************************************/ -#define ZSTD_IS_POWER_2(a) (((a) & ((a)-1)) == 0) +/* @return 1 if @u is a 2^n value, 0 otherwise + * useful to check a value is valid for alignment restrictions */ +MEM_STATIC int ZSTD_isPower2(size_t u) { + return (u & (u-1)) == 0; +} /* this test was initially positioned in mem.h, * but this file is removed (or replaced) for linux kernel diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index dc0142098..77715e22e 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -208,7 +208,7 @@ MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) { */ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t align) { size_t const mask = align - 1; - assert(ZSTD_IS_POWER_2(align)); + assert(ZSTD_isPower2(align)); return (size + mask) & ~mask; } @@ -266,7 +266,7 @@ MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) { MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) { size_t const alignBytesMask = alignBytes - 1; size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask; - assert(ZSTD_IS_POWER_2(alignBytes)); + assert(ZSTD_isPower2(alignBytes)); assert(bytes < alignBytes); return bytes; } @@ -536,7 +536,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t byteSi void* const start = ZSTD_cwksp_reserve_object(ws, byteSize + surplus); if (start == NULL) return NULL; if (surplus == 0) return start; - assert(ZSTD_IS_POWER_2(alignment)); + assert(ZSTD_isPower2(alignment)); return (void*)(((size_t)start + surplus) & ~mask); } From 5ae34e4c96265f1face970f3458836b3edf2e76d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 15:19:06 -0700 Subject: [PATCH 29/44] ensure `lastBlock` is correctly determined reported by @terrelln --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e7a07a484..edb71ae50 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4540,8 +4540,8 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, while (remaining) { ZSTD_matchState_t* const ms = &cctx->blockState.matchState; - U32 const lastBlock = lastFrameChunk & (blockSizeMax >= remaining); size_t const blockSize = ZSTD_optimalBlockSize(cctx, ip, remaining, blockSizeMax, cctx->appliedParams.cParams.strategy, savings); + U32 const lastBlock = lastFrameChunk & (blockSize == remaining); assert(blockSize <= remaining); /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding From ea85dc7af6f97cbfc7fd1e6ff1515660e58501a3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 15:25:45 -0700 Subject: [PATCH 30/44] conservatively estimate over-splitting in presence of incompressible loss ensure data can never be expanded by more than 3 bytes per full block. --- lib/compress/zstd_compress.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index edb71ae50..85966d888 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4587,6 +4587,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ if (cSize < blockSize) savings += (blockSize - cSize); + else if (savings) savings--; ip += blockSize; assert(remaining >= blockSize); remaining -= blockSize; From 4662f6e646395b3f1902bc280991b82aefc1ba5d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 15:32:11 -0700 Subject: [PATCH 31/44] renamed: FingerPrint => Fingerprint suggested by @terrelln --- lib/compress/zstd_preSplit.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 721a52deb..e0ac9a9e9 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -35,10 +35,10 @@ static unsigned hash2(const void *p) typedef struct { int events[HASHTABLESIZE]; S64 nbEvents; -} FingerPrint; +} Fingerprint; typedef struct { - FingerPrint pastEvents; - FingerPrint newEvents; + Fingerprint pastEvents; + Fingerprint newEvents; } FPStats; static void initStats(FPStats* fpstats) @@ -46,7 +46,7 @@ static void initStats(FPStats* fpstats) ZSTD_memset(fpstats, 0, sizeof(FPStats)); } -FORCE_INLINE_TEMPLATE void addEvents_generic(FingerPrint* fp, const void* src, size_t srcSize, size_t samplingRate) +FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate) { const char* p = (const char*)src; size_t limit = srcSize - HASHLENGTH + 1; @@ -61,7 +61,7 @@ FORCE_INLINE_TEMPLATE void addEvents_generic(FingerPrint* fp, const void* src, s #define ADDEVENTS_RATE(_rate) ZSTD_addEvents_##_rate #define ZSTD_GEN_ADDEVENTS_SAMPLE(_rate) \ - static void ADDEVENTS_RATE(_rate)(FingerPrint* fp, const void* src, size_t srcSize) \ + static void ADDEVENTS_RATE(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ { \ return addEvents_generic(fp, src, srcSize, _rate); \ } @@ -70,9 +70,9 @@ ZSTD_GEN_ADDEVENTS_SAMPLE(1); ZSTD_GEN_ADDEVENTS_SAMPLE(5); -typedef void (*addEvents_f)(FingerPrint* fp, const void* src, size_t srcSize); +typedef void (*addEvents_f)(Fingerprint* fp, const void* src, size_t srcSize); -static void recordFingerprint(FingerPrint* fp, const void* src, size_t s, addEvents_f addEvents) +static void recordFingerprint(Fingerprint* fp, const void* src, size_t s, addEvents_f addEvents) { ZSTD_memset(fp, 0, sizeof(*fp)); addEvents(fp, src, s); @@ -80,7 +80,7 @@ static void recordFingerprint(FingerPrint* fp, const void* src, size_t s, addEve static S64 abs64(S64 i) { return (i < 0) ? -i : i; } -static S64 fpDistance(const FingerPrint* fp1, const FingerPrint* fp2) +static S64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) { S64 distance = 0; size_t n; @@ -94,8 +94,8 @@ static S64 fpDistance(const FingerPrint* fp1, const FingerPrint* fp2) /* Compare newEvents with pastEvents * return 1 when considered "too different" */ -static int compareFingerprints(const FingerPrint* ref, - const FingerPrint* newfp, +static int compareFingerprints(const Fingerprint* ref, + const Fingerprint* newfp, int penalty) { assert(ref->nbEvents > 0); @@ -107,7 +107,7 @@ static int compareFingerprints(const FingerPrint* ref, } } -static void mergeEvents(FingerPrint* acc, const FingerPrint* newfp) +static void mergeEvents(Fingerprint* acc, const Fingerprint* newfp) { size_t n; for (n = 0; n < HASHTABLESIZE; n++) { @@ -126,7 +126,7 @@ static void flushEvents(FPStats* fpstats) ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents)); } -static void removeEvents(FingerPrint* acc, const FingerPrint* slice) +static void removeEvents(Fingerprint* acc, const Fingerprint* slice) { size_t n; for (n = 0; n < HASHTABLESIZE; n++) { From 1ec5f9f1f6b187095d996248471a6c6f128e9001 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:03:19 -0700 Subject: [PATCH 32/44] changed loop exit condition so that there is no need to assert() within the loop. --- lib/compress/zstd_preSplit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index e0ac9a9e9..02751a0d4 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -155,8 +155,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, initStats(fpstats); recordFingerprint(&fpstats->pastEvents, p, CHUNKSIZE, f); - for (pos = CHUNKSIZE; pos < blockSizeMax; pos += CHUNKSIZE) { - assert(pos <= blockSizeMax - CHUNKSIZE); + for (pos = CHUNKSIZE; pos <= blockSizeMax - CHUNKSIZE; pos += CHUNKSIZE) { recordFingerprint(&fpstats->newEvents, p + pos, CHUNKSIZE, f); if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty)) { return pos; @@ -165,6 +164,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, penalty = penalty - 1 + (penalty == 0); } } + assert(pos == blockSizeMax); return blockSizeMax; (void)flushEvents; (void)removeEvents; } From 16450d0732ff84e3ad367f616d84cee1567cfb8e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:06:07 -0700 Subject: [PATCH 33/44] rewrite penalty update suggested by @terrelln --- lib/compress/zstd_preSplit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 02751a0d4..2e65f88d9 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -161,7 +161,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, return pos; } else { mergeEvents(&fpstats->pastEvents, &fpstats->newEvents); - penalty = penalty - 1 + (penalty == 0); + if (penalty > 0) penalty--; } } assert(pos == blockSizeMax); From 06b7cfabf8f5f3ba48694758cf85aaf7671504d2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:22:17 -0700 Subject: [PATCH 34/44] rewrote ZSTD_cwksp_initialAllocStart() to be easier to read following a discussion with @felixhandte --- lib/compress/zstd_cwksp.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index 77715e22e..aa4c3e49e 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -17,6 +17,7 @@ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customFree */ #include "../common/zstd_internal.h" #include "../common/portability_macros.h" +#include "../common/compiler.h" /* ZS2_isPower2 */ #if defined (__cplusplus) extern "C" { @@ -275,8 +276,12 @@ MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignByt * Returns the initial value for allocStart which is used to determine the position from * which we can allocate from the end of the workspace. */ -MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws) { - return (void*)((size_t)ws->workspaceEnd & (size_t)~(ZSTD_CWKSP_ALIGNMENT_BYTES-1)); +MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws) +{ + char* endPtr = (char*)ws->workspaceEnd; + assert(ZSTD_isPower2(ZSTD_CWKSP_ALIGNMENT_BYTES)); + endPtr = endPtr - ((size_t)endPtr % ZSTD_CWKSP_ALIGNMENT_BYTES); + return (void*)endPtr; } /** From 0be334d208b9fadd805a401ebcfdf6f253adae2a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:25:44 -0700 Subject: [PATCH 35/44] fixes static state allocation check detected by @felixhandte --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 85966d888..05c1faa9f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -138,7 +138,7 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) cctx->staticSize = workspaceSize; /* statically sized space. tmpWorkspace never moves (but prev/next block swap places) */ - if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; + if (!ZSTD_cwksp_check_available(&cctx->workspace, TMP_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(&cctx->workspace, TMP_WORKSPACE_SIZE, sizeof(S64)); From d2eeed53dc8782be8dff36e1ff20e1e41e1d4199 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:33:55 -0700 Subject: [PATCH 36/44] updated compression results due to integration of `sample5` strategy, leading to better compression ratios on a range of levels --- tests/regression/results.csv | 168 +++++++++++++++++------------------ 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index b32db43de..3a14793dd 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -9,8 +9,8 @@ silesia.tar, level 4, compress silesia.tar, level 5, compress simple, 4669650 silesia.tar, level 6, compress simple, 4604925 silesia.tar, level 7, compress simple, 4570873 -silesia.tar, level 9, compress simple, 4546477 -silesia.tar, level 13, compress simple, 4486256 +silesia.tar, level 9, compress simple, 4537558 +silesia.tar, level 13, compress simple, 4484732 silesia.tar, level 16, compress simple, 4355572 silesia.tar, level 19, compress simple, 4257629 silesia.tar, uncompressed literals, compress simple, 4843429 @@ -26,7 +26,7 @@ github.tar, level 4, compress github.tar, level 5, compress simple, 39808 github.tar, level 6, compress simple, 39455 github.tar, level 7, compress simple, 38168 -github.tar, level 9, compress simple, 36897 +github.tar, level 9, compress simple, 36723 github.tar, level 13, compress simple, 35501 github.tar, level 16, compress simple, 40466 github.tar, level 19, compress simple, 32262 @@ -43,8 +43,8 @@ silesia, level 4, compress silesia, level 5, compress cctx, 4666524 silesia, level 6, compress cctx, 4602031 silesia, level 7, compress cctx, 4567954 -silesia, level 9, compress cctx, 4543669 -silesia, level 13, compress cctx, 4484875 +silesia, level 9, compress cctx, 4535624 +silesia, level 13, compress cctx, 4484013 silesia, level 16, compress cctx, 4356207 silesia, level 19, compress cctx, 4266751 silesia, long distance mode, compress cctx, 4838417 @@ -107,8 +107,8 @@ silesia, level 4, zstdcli, silesia, level 5, zstdcli, 4666931 silesia, level 6, zstdcli, 4602509 silesia, level 7, zstdcli, 4568265 -silesia, level 9, zstdcli, 4544068 -silesia, level 13, zstdcli, 4484443 +silesia, level 9, zstdcli, 4535309 +silesia, level 13, zstdcli, 4483601 silesia, level 16, zstdcli, 4357591 silesia, level 19, zstdcli, 4266865 silesia, long distance mode, zstdcli, 4830467 @@ -132,8 +132,8 @@ silesia.tar, level 4, zstdcli, silesia.tar, level 5, zstdcli, 4671144 silesia.tar, level 6, zstdcli, 4606407 silesia.tar, level 7, zstdcli, 4572666 -silesia.tar, level 9, zstdcli, 4546557 -silesia.tar, level 13, zstdcli, 4491076 +silesia.tar, level 9, zstdcli, 4542599 +silesia.tar, level 13, zstdcli, 4489976 silesia.tar, level 16, zstdcli, 4356959 silesia.tar, level 19, zstdcli, 4259787 silesia.tar, no source size, zstdcli, 4841902 @@ -206,9 +206,9 @@ github.tar, level 5 with dict, zstdcli, github.tar, level 6, zstdcli, 39455 github.tar, level 6 with dict, zstdcli, 38787 github.tar, level 7, zstdcli, 38177 -github.tar, level 7 with dict, zstdcli, 38009 -github.tar, level 9, zstdcli, 36893 -github.tar, level 9 with dict, zstdcli, 36827 +github.tar, level 7 with dict, zstdcli, 37861 +github.tar, level 9, zstdcli, 36727 +github.tar, level 9 with dict, zstdcli, 36686 github.tar, level 13, zstdcli, 35505 github.tar, level 13 with dict, zstdcli, 37134 github.tar, level 16, zstdcli, 40470 @@ -242,12 +242,12 @@ silesia, level 6, advanced silesia, level 7 row 1, advanced one pass, 4567954 silesia, level 7 row 2, advanced one pass, 4562774 silesia, level 7, advanced one pass, 4567954 -silesia, level 9, advanced one pass, 4543669 -silesia, level 11 row 1, advanced one pass, 4503577 -silesia, level 11 row 2, advanced one pass, 4501229 -silesia, level 12 row 1, advanced one pass, 4503577 -silesia, level 12 row 2, advanced one pass, 4501229 -silesia, level 13, advanced one pass, 4484875 +silesia, level 9, advanced one pass, 4535624 +silesia, level 11 row 1, advanced one pass, 4495623 +silesia, level 11 row 2, advanced one pass, 4493258 +silesia, level 12 row 1, advanced one pass, 4495623 +silesia, level 12 row 2, advanced one pass, 4493258 +silesia, level 13, advanced one pass, 4484013 silesia, level 16, advanced one pass, 4356207 silesia, level 19, advanced one pass, 4266751 silesia, no source size, advanced one pass, 4838417 @@ -276,12 +276,12 @@ silesia.tar, level 6, advanced silesia.tar, level 7 row 1, advanced one pass, 4570873 silesia.tar, level 7 row 2, advanced one pass, 4566314 silesia.tar, level 7, advanced one pass, 4570873 -silesia.tar, level 9, advanced one pass, 4546477 -silesia.tar, level 11 row 1, advanced one pass, 4505875 -silesia.tar, level 11 row 2, advanced one pass, 4504435 -silesia.tar, level 12 row 1, advanced one pass, 4505461 -silesia.tar, level 12 row 2, advanced one pass, 4504644 -silesia.tar, level 13, advanced one pass, 4486256 +silesia.tar, level 9, advanced one pass, 4537558 +silesia.tar, level 11 row 1, advanced one pass, 4496590 +silesia.tar, level 11 row 2, advanced one pass, 4495225 +silesia.tar, level 12 row 1, advanced one pass, 4496084 +silesia.tar, level 12 row 2, advanced one pass, 4495434 +silesia.tar, level 13, advanced one pass, 4484732 silesia.tar, level 16, advanced one pass, 4355572 silesia.tar, level 19, advanced one pass, 4257629 silesia.tar, no source size, advanced one pass, 4843429 @@ -474,47 +474,47 @@ github.tar, level 6 with dict dds, advanced github.tar, level 6 with dict copy, advanced one pass, 38808 github.tar, level 6 with dict load, advanced one pass, 38796 github.tar, level 7 row 1, advanced one pass, 38168 -github.tar, level 7 row 1 with dict dms, advanced one pass, 38001 -github.tar, level 7 row 1 with dict dds, advanced one pass, 38008 -github.tar, level 7 row 1 with dict copy, advanced one pass, 37975 +github.tar, level 7 row 1 with dict dms, advanced one pass, 37832 +github.tar, level 7 row 1 with dict dds, advanced one pass, 37857 +github.tar, level 7 row 1 with dict copy, advanced one pass, 37839 github.tar, level 7 row 1 with dict load, advanced one pass, 37445 github.tar, level 7 row 2, advanced one pass, 38235 -github.tar, level 7 row 2 with dict dms, advanced one pass, 38164 -github.tar, level 7 row 2 with dict dds, advanced one pass, 38169 -github.tar, level 7 row 2 with dict copy, advanced one pass, 38294 +github.tar, level 7 row 2 with dict dms, advanced one pass, 38012 +github.tar, level 7 row 2 with dict dds, advanced one pass, 38014 +github.tar, level 7 row 2 with dict copy, advanced one pass, 38101 github.tar, level 7 row 2 with dict load, advanced one pass, 37552 github.tar, level 7, advanced one pass, 38168 -github.tar, level 7 with dict, advanced one pass, 37975 -github.tar, level 7 with dict dms, advanced one pass, 38001 -github.tar, level 7 with dict dds, advanced one pass, 38008 -github.tar, level 7 with dict copy, advanced one pass, 37975 +github.tar, level 7 with dict, advanced one pass, 37839 +github.tar, level 7 with dict dms, advanced one pass, 37832 +github.tar, level 7 with dict dds, advanced one pass, 37857 +github.tar, level 7 with dict copy, advanced one pass, 37839 github.tar, level 7 with dict load, advanced one pass, 37445 -github.tar, level 9, advanced one pass, 36897 -github.tar, level 9 with dict, advanced one pass, 36689 -github.tar, level 9 with dict dms, advanced one pass, 36756 -github.tar, level 9 with dict dds, advanced one pass, 36817 -github.tar, level 9 with dict copy, advanced one pass, 36689 -github.tar, level 9 with dict load, advanced one pass, 36484 -github.tar, level 11 row 1, advanced one pass, 36234 +github.tar, level 9, advanced one pass, 36723 +github.tar, level 9 with dict, advanced one pass, 36531 +github.tar, level 9 with dict dms, advanced one pass, 36615 +github.tar, level 9 with dict dds, advanced one pass, 36682 +github.tar, level 9 with dict copy, advanced one pass, 36531 +github.tar, level 9 with dict load, advanced one pass, 36322 +github.tar, level 11 row 1, advanced one pass, 36085 github.tar, level 11 row 1 with dict dms, advanced one pass, 36963 github.tar, level 11 row 1 with dict dds, advanced one pass, 36963 github.tar, level 11 row 1 with dict copy, advanced one pass, 36557 -github.tar, level 11 row 1 with dict load, advanced one pass, 36567 -github.tar, level 11 row 2, advanced one pass, 36217 +github.tar, level 11 row 1 with dict load, advanced one pass, 36423 +github.tar, level 11 row 2, advanced one pass, 36110 github.tar, level 11 row 2 with dict dms, advanced one pass, 36963 github.tar, level 11 row 2 with dict dds, advanced one pass, 36963 github.tar, level 11 row 2 with dict copy, advanced one pass, 36557 -github.tar, level 11 row 2 with dict load, advanced one pass, 36586 -github.tar, level 12 row 1, advanced one pass, 36234 +github.tar, level 11 row 2 with dict load, advanced one pass, 36459 +github.tar, level 12 row 1, advanced one pass, 36085 github.tar, level 12 row 1 with dict dms, advanced one pass, 36986 github.tar, level 12 row 1 with dict dds, advanced one pass, 36986 github.tar, level 12 row 1 with dict copy, advanced one pass, 36609 -github.tar, level 12 row 1 with dict load, advanced one pass, 36567 -github.tar, level 12 row 2, advanced one pass, 36217 +github.tar, level 12 row 1 with dict load, advanced one pass, 36423 +github.tar, level 12 row 2, advanced one pass, 36110 github.tar, level 12 row 2 with dict dms, advanced one pass, 36986 github.tar, level 12 row 2 with dict dds, advanced one pass, 36986 github.tar, level 12 row 2 with dict copy, advanced one pass, 36609 -github.tar, level 12 row 2 with dict load, advanced one pass, 36586 +github.tar, level 12 row 2 with dict load, advanced one pass, 36459 github.tar, level 13, advanced one pass, 35501 github.tar, level 13 with dict, advanced one pass, 37130 github.tar, level 13 with dict dms, advanced one pass, 37220 @@ -560,12 +560,12 @@ silesia, level 6, advanced silesia, level 7 row 1, advanced one pass small out, 4567954 silesia, level 7 row 2, advanced one pass small out, 4562774 silesia, level 7, advanced one pass small out, 4567954 -silesia, level 9, advanced one pass small out, 4543669 -silesia, level 11 row 1, advanced one pass small out, 4503577 -silesia, level 11 row 2, advanced one pass small out, 4501229 -silesia, level 12 row 1, advanced one pass small out, 4503577 -silesia, level 12 row 2, advanced one pass small out, 4501229 -silesia, level 13, advanced one pass small out, 4484875 +silesia, level 9, advanced one pass small out, 4535624 +silesia, level 11 row 1, advanced one pass small out, 4495623 +silesia, level 11 row 2, advanced one pass small out, 4493258 +silesia, level 12 row 1, advanced one pass small out, 4495623 +silesia, level 12 row 2, advanced one pass small out, 4493258 +silesia, level 13, advanced one pass small out, 4484013 silesia, level 16, advanced one pass small out, 4356207 silesia, level 19, advanced one pass small out, 4266751 silesia, no source size, advanced one pass small out, 4838417 @@ -594,12 +594,12 @@ silesia.tar, level 6, advanced silesia.tar, level 7 row 1, advanced one pass small out, 4570873 silesia.tar, level 7 row 2, advanced one pass small out, 4566314 silesia.tar, level 7, advanced one pass small out, 4570873 -silesia.tar, level 9, advanced one pass small out, 4546477 -silesia.tar, level 11 row 1, advanced one pass small out, 4505875 -silesia.tar, level 11 row 2, advanced one pass small out, 4504435 -silesia.tar, level 12 row 1, advanced one pass small out, 4505461 -silesia.tar, level 12 row 2, advanced one pass small out, 4504644 -silesia.tar, level 13, advanced one pass small out, 4486256 +silesia.tar, level 9, advanced one pass small out, 4537558 +silesia.tar, level 11 row 1, advanced one pass small out, 4496590 +silesia.tar, level 11 row 2, advanced one pass small out, 4495225 +silesia.tar, level 12 row 1, advanced one pass small out, 4496084 +silesia.tar, level 12 row 2, advanced one pass small out, 4495434 +silesia.tar, level 13, advanced one pass small out, 4484732 silesia.tar, level 16, advanced one pass small out, 4355572 silesia.tar, level 19, advanced one pass small out, 4257629 silesia.tar, no source size, advanced one pass small out, 4843429 @@ -792,47 +792,47 @@ github.tar, level 6 with dict dds, advanced github.tar, level 6 with dict copy, advanced one pass small out, 38808 github.tar, level 6 with dict load, advanced one pass small out, 38796 github.tar, level 7 row 1, advanced one pass small out, 38168 -github.tar, level 7 row 1 with dict dms, advanced one pass small out, 38001 -github.tar, level 7 row 1 with dict dds, advanced one pass small out, 38008 -github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37975 +github.tar, level 7 row 1 with dict dms, advanced one pass small out, 37832 +github.tar, level 7 row 1 with dict dds, advanced one pass small out, 37857 +github.tar, level 7 row 1 with dict copy, advanced one pass small out, 37839 github.tar, level 7 row 1 with dict load, advanced one pass small out, 37445 github.tar, level 7 row 2, advanced one pass small out, 38235 -github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38164 -github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38169 -github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38294 +github.tar, level 7 row 2 with dict dms, advanced one pass small out, 38012 +github.tar, level 7 row 2 with dict dds, advanced one pass small out, 38014 +github.tar, level 7 row 2 with dict copy, advanced one pass small out, 38101 github.tar, level 7 row 2 with dict load, advanced one pass small out, 37552 github.tar, level 7, advanced one pass small out, 38168 -github.tar, level 7 with dict, advanced one pass small out, 37975 -github.tar, level 7 with dict dms, advanced one pass small out, 38001 -github.tar, level 7 with dict dds, advanced one pass small out, 38008 -github.tar, level 7 with dict copy, advanced one pass small out, 37975 +github.tar, level 7 with dict, advanced one pass small out, 37839 +github.tar, level 7 with dict dms, advanced one pass small out, 37832 +github.tar, level 7 with dict dds, advanced one pass small out, 37857 +github.tar, level 7 with dict copy, advanced one pass small out, 37839 github.tar, level 7 with dict load, advanced one pass small out, 37445 -github.tar, level 9, advanced one pass small out, 36897 -github.tar, level 9 with dict, advanced one pass small out, 36689 -github.tar, level 9 with dict dms, advanced one pass small out, 36756 -github.tar, level 9 with dict dds, advanced one pass small out, 36817 -github.tar, level 9 with dict copy, advanced one pass small out, 36689 -github.tar, level 9 with dict load, advanced one pass small out, 36484 -github.tar, level 11 row 1, advanced one pass small out, 36234 +github.tar, level 9, advanced one pass small out, 36723 +github.tar, level 9 with dict, advanced one pass small out, 36531 +github.tar, level 9 with dict dms, advanced one pass small out, 36615 +github.tar, level 9 with dict dds, advanced one pass small out, 36682 +github.tar, level 9 with dict copy, advanced one pass small out, 36531 +github.tar, level 9 with dict load, advanced one pass small out, 36322 +github.tar, level 11 row 1, advanced one pass small out, 36085 github.tar, level 11 row 1 with dict dms, advanced one pass small out, 36963 github.tar, level 11 row 1 with dict dds, advanced one pass small out, 36963 github.tar, level 11 row 1 with dict copy, advanced one pass small out, 36557 -github.tar, level 11 row 1 with dict load, advanced one pass small out, 36567 -github.tar, level 11 row 2, advanced one pass small out, 36217 +github.tar, level 11 row 1 with dict load, advanced one pass small out, 36423 +github.tar, level 11 row 2, advanced one pass small out, 36110 github.tar, level 11 row 2 with dict dms, advanced one pass small out, 36963 github.tar, level 11 row 2 with dict dds, advanced one pass small out, 36963 github.tar, level 11 row 2 with dict copy, advanced one pass small out, 36557 -github.tar, level 11 row 2 with dict load, advanced one pass small out, 36586 -github.tar, level 12 row 1, advanced one pass small out, 36234 +github.tar, level 11 row 2 with dict load, advanced one pass small out, 36459 +github.tar, level 12 row 1, advanced one pass small out, 36085 github.tar, level 12 row 1 with dict dms, advanced one pass small out, 36986 github.tar, level 12 row 1 with dict dds, advanced one pass small out, 36986 github.tar, level 12 row 1 with dict copy, advanced one pass small out, 36609 -github.tar, level 12 row 1 with dict load, advanced one pass small out, 36567 -github.tar, level 12 row 2, advanced one pass small out, 36217 +github.tar, level 12 row 1 with dict load, advanced one pass small out, 36423 +github.tar, level 12 row 2, advanced one pass small out, 36110 github.tar, level 12 row 2 with dict dms, advanced one pass small out, 36986 github.tar, level 12 row 2 with dict dds, advanced one pass small out, 36986 github.tar, level 12 row 2 with dict copy, advanced one pass small out, 36609 -github.tar, level 12 row 2 with dict load, advanced one pass small out, 36586 +github.tar, level 12 row 2 with dict load, advanced one pass small out, 36459 github.tar, level 13, advanced one pass small out, 35501 github.tar, level 13 with dict, advanced one pass small out, 37130 github.tar, level 13 with dict dms, advanced one pass small out, 37220 From 18b1e67223823e48a96ed9f2ae489e8989802e42 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 16:51:52 -0700 Subject: [PATCH 37/44] fixed extraneous return strict C90 compliance test --- lib/compress/zstd_preSplit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 2e65f88d9..4ca30dfce 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -63,7 +63,7 @@ FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, s #define ZSTD_GEN_ADDEVENTS_SAMPLE(_rate) \ static void ADDEVENTS_RATE(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \ { \ - return addEvents_generic(fp, src, srcSize, _rate); \ + addEvents_generic(fp, src, srcSize, _rate); \ } ZSTD_GEN_ADDEVENTS_SAMPLE(1); From 57239c4d3b5a21529ade206241f3f0a4815f2295 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 22 Oct 2024 21:49:35 -0700 Subject: [PATCH 38/44] fixed minor strict pedantic C90 issue --- lib/compress/zstd_preSplit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index 4ca30dfce..e8994dcde 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -66,8 +66,8 @@ FORCE_INLINE_TEMPLATE void addEvents_generic(Fingerprint* fp, const void* src, s addEvents_generic(fp, src, srcSize, _rate); \ } -ZSTD_GEN_ADDEVENTS_SAMPLE(1); -ZSTD_GEN_ADDEVENTS_SAMPLE(5); +ZSTD_GEN_ADDEVENTS_SAMPLE(1) +ZSTD_GEN_ADDEVENTS_SAMPLE(5) typedef void (*addEvents_f)(Fingerprint* fp, const void* src, size_t srcSize); From b68ddce818c274b9651ba47d45e46f7ffb4592ae Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 11:10:07 -0700 Subject: [PATCH 39/44] rewrite fingerprint storage to no longer need 64-bit members so that it can be stored using standard alignment requirement (sizeof(void*)). Distance function still requires 64-bit signed multiplication though, so it won't change the issue regarding the bug in ubsan for clang 32-bit on github ci. --- lib/compress/zstd_compress.c | 6 +++--- lib/compress/zstd_preSplit.c | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 05c1faa9f..b064e382c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -141,7 +141,7 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) if (!ZSTD_cwksp_check_available(&cctx->workspace, TMP_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(&cctx->workspace, TMP_WORKSPACE_SIZE, sizeof(S64)); + cctx->tmpWorkspace = ZSTD_cwksp_reserve_object(&cctx->workspace, TMP_WORKSPACE_SIZE); cctx->tmpWkspSize = TMP_WORKSPACE_SIZE; cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); return cctx; @@ -1709,7 +1709,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(seqDef)) + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const tmpWorkSpace = ZSTD_cwksp_aligned_alloc_size(TMP_WORKSPACE_SIZE, sizeof(S64)); + size_t const tmpWorkSpace = ZSTD_cwksp_alloc_size(TMP_WORKSPACE_SIZE); size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1); @@ -2174,7 +2174,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock"); zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock"); - zc->tmpWorkspace = ZSTD_cwksp_reserve_object_aligned(ws, TMP_WORKSPACE_SIZE, sizeof(S64)); + zc->tmpWorkspace = ZSTD_cwksp_reserve_object(ws, TMP_WORKSPACE_SIZE); RETURN_ERROR_IF(zc->tmpWorkspace == NULL, memory_allocation, "couldn't allocate tmpWorkspace"); zc->tmpWkspSize = TMP_WORKSPACE_SIZE; } } diff --git a/lib/compress/zstd_preSplit.c b/lib/compress/zstd_preSplit.c index e8994dcde..c658f6fe5 100644 --- a/lib/compress/zstd_preSplit.c +++ b/lib/compress/zstd_preSplit.c @@ -33,8 +33,8 @@ static unsigned hash2(const void *p) typedef struct { - int events[HASHTABLESIZE]; - S64 nbEvents; + unsigned events[HASHTABLESIZE]; + size_t nbEvents; } Fingerprint; typedef struct { Fingerprint pastEvents; @@ -78,15 +78,15 @@ static void recordFingerprint(Fingerprint* fp, const void* src, size_t s, addEve addEvents(fp, src, s); } -static S64 abs64(S64 i) { return (i < 0) ? -i : i; } +static U64 abs64(S64 s64) { return (U64)((s64 < 0) ? -s64 : s64); } -static S64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) +static U64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2) { - S64 distance = 0; + U64 distance = 0; size_t n; for (n = 0; n < HASHTABLESIZE; n++) { distance += - abs64(fp1->events[n] * fp2->nbEvents - fp2->events[n] * fp1->nbEvents); + abs64((S64)fp1->events[n] * (S64)fp2->nbEvents - (S64)fp2->events[n] * (S64)fp1->nbEvents); } return distance; } @@ -100,9 +100,9 @@ static int compareFingerprints(const Fingerprint* ref, { assert(ref->nbEvents > 0); assert(newfp->nbEvents > 0); - { S64 p50 = ref->nbEvents * newfp->nbEvents; - S64 deviation = fpDistance(ref, newfp); - S64 threshold = p50 * (THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; + { U64 p50 = (U64)ref->nbEvents * (U64)newfp->nbEvents; + U64 deviation = fpDistance(ref, newfp); + U64 threshold = p50 * (U64)(THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE; return deviation >= threshold; } } @@ -150,7 +150,7 @@ static size_t ZSTD_splitBlock_byChunks(const void* src, size_t srcSize, assert(blockSizeMax == (128 << 10)); assert(workspace != NULL); assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0); - ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE == sizeof(FPStats)); + ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE >= sizeof(FPStats)); assert(wkspSize >= sizeof(FPStats)); (void)wkspSize; initStats(fpstats); From 7d3e5e3ba1007635fc991a3b208353463cb2712d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 14:11:49 -0700 Subject: [PATCH 40/44] split all full 128 KB blocks this helps make the streaming behavior more consistent, since it does no longer depend on having more data presented on the input. suggested by @terrelln --- lib/compress/zstd_compress.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b064e382c..9de92cef2 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4493,20 +4493,21 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, ZSTD_strategy strat, S64 savings) { - /* note: conservatively only split full blocks (128 KB) currently, - * and even then only if there is more than 128 KB input remaining. + /* note: conservatively only split full blocks (128 KB) currently. + * While it's possible to go lower, let's keep it simple for a first implementation. + * Besides, benefits of splitting are reduced when blocks are already small. */ - if (srcSize <= 128 KB || blockSizeMax < 128 KB) + if (srcSize < 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); /* dynamic splitting has a cpu cost for analysis, - * due to that cost it's only used for btlazy2+ strategies */ + * due to that cost it's only used for higher levels */ if (strat >= ZSTD_btopt) return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl2, cctx->tmpWorkspace, cctx->tmpWkspSize); if (strat >= ZSTD_lazy2) return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy - * no cpu cost, but can over-split homegeneous data. * heuristic, tested as being "generally better". + * no cpu cost, but can over-split homegeneous data. * do not split incompressible data though: respect the 3 bytes per block overhead limit. */ return savings ? 92 KB : 128 KB; From c80645a055d19f7e77cff3c268d818f811b9e1bb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 14:55:10 -0700 Subject: [PATCH 41/44] stricter limits to ensure expansion factor with blind-split strategy issue reported by @terrelln --- lib/compress/zstd_compress.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9de92cef2..3ab7414d4 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4506,11 +4506,11 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src if (strat >= ZSTD_lazy2) return ZSTD_splitBlock(src, srcSize, blockSizeMax, split_lvl1, cctx->tmpWorkspace, cctx->tmpWkspSize); /* blind split strategy - * heuristic, tested as being "generally better". + * heuristic value, tested as being "generally better". * no cpu cost, but can over-split homegeneous data. * do not split incompressible data though: respect the 3 bytes per block overhead limit. */ - return savings ? 92 KB : 128 KB; + return (savings > 3) ? 92 KB : 128 KB; } /*! ZSTD_compress_frameChunk() : @@ -4587,8 +4587,22 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ + /* @savings is employed by the blind-split strategy, + * to authorize splitting into less-than-full blocks, + * and thus avoid oversplitting blocks in case of incompressible data: + * when @savings is not large enough, blind split is disactivated, and full block is used instead. + * If data is incompressible, it's allowed to expand it by 3-bytes per full block. + * For large data, a full block is 128 KB. + * blind-split will instead use 92 KB as block size. + * So it expands incompressible data by 3-bytes per 92 KB block. + * That's an over-expansion of ((128*3) - (92*3)) / 128 = 0.84 bytes per block. + * Therefore, when data doesn't shrink, we subtract a 1 byte malus from @savings. + * This is a conservative estimate, especially as we don't count the 3-bytes header when there are savings, + * but it doesn't matter, the goal is not accuracy, + * the goal is to ensure the 3-bytes expansion limit per 128 KB input can never be breached */ if (cSize < blockSize) savings += (blockSize - cSize); - else if (savings) savings--; + else savings--; + ip += blockSize; assert(remaining >= blockSize); remaining -= blockSize; From bbda1acf85d8e2f4045156e14943817c0a389503 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 23 Oct 2024 15:56:56 -0700 Subject: [PATCH 42/44] update regression results --- tests/regression/results.csv | 482 +++++++++++++++++------------------ 1 file changed, 241 insertions(+), 241 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 3a14793dd..2ac686962 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -97,9 +97,9 @@ github, uncompressed literals, compress github, uncompressed literals optimal, compress cctx, 132879 github, huffman literals, compress cctx, 175468 github, multithreaded with advanced params, compress cctx, 141069 -silesia, level -5, zstdcli, 6856076 -silesia, level -3, zstdcli, 6505583 -silesia, level -1, zstdcli, 6172652 +silesia, level -5, zstdcli, 6856073 +silesia, level -3, zstdcli, 6505580 +silesia, level -1, zstdcli, 6172649 silesia, level 0, zstdcli, 4838997 silesia, level 1, zstdcli, 5306179 silesia, level 3, zstdcli, 4838997 @@ -864,20 +864,20 @@ github.tar, uncompressed literals, advanced github.tar, uncompressed literals optimal, advanced one pass small out, 35356 github.tar, huffman literals, advanced one pass small out, 39099 github.tar, multithreaded with advanced params, advanced one pass small out, 41700 -silesia, level -5, advanced streaming, 6854744 -silesia, level -3, advanced streaming, 6503319 -silesia, level -1, advanced streaming, 6172207 -silesia, level 0, advanced streaming, 4839431 -silesia, level 1, advanced streaming, 5306388 -silesia, level 3, advanced streaming, 4839431 -silesia, level 4, advanced streaming, 4776557 -silesia, level 5 row 1, advanced streaming, 4667668 -silesia, level 5 row 2, advanced streaming, 4670326 -silesia, level 5, advanced streaming, 4667668 -silesia, level 6, advanced streaming, 4604351 -silesia, level 7 row 1, advanced streaming, 4570271 -silesia, level 7 row 2, advanced streaming, 4565169 -silesia, level 7, advanced streaming, 4570271 +silesia, level -5, advanced streaming, 6856699 +silesia, level -3, advanced streaming, 6505694 +silesia, level -1, advanced streaming, 6174139 +silesia, level 0, advanced streaming, 4839173 +silesia, level 1, advanced streaming, 5305682 +silesia, level 3, advanced streaming, 4839173 +silesia, level 4, advanced streaming, 4776074 +silesia, level 5 row 1, advanced streaming, 4667049 +silesia, level 5 row 2, advanced streaming, 4669474 +silesia, level 5, advanced streaming, 4667049 +silesia, level 6, advanced streaming, 4602956 +silesia, level 7 row 1, advanced streaming, 4568785 +silesia, level 7 row 2, advanced streaming, 4563722 +silesia, level 7, advanced streaming, 4568785 silesia, level 9, advanced streaming, 4545850 silesia, level 11 row 1, advanced streaming, 4505658 silesia, level 11 row 2, advanced streaming, 4503429 @@ -886,32 +886,32 @@ silesia, level 12 row 2, advanced silesia, level 13, advanced streaming, 4493990 silesia, level 16, advanced streaming, 4359652 silesia, level 19, advanced streaming, 4266582 -silesia, no source size, advanced streaming, 4839395 -silesia, long distance mode, advanced streaming, 4831158 +silesia, no source size, advanced streaming, 4839137 +silesia, long distance mode, advanced streaming, 4831125 silesia, multithreaded, advanced streaming, 4838949 silesia, multithreaded long distance mode, advanced streaming, 4830419 silesia, small window log, advanced streaming, 7110591 silesia, small hash log, advanced streaming, 6526141 silesia, small chain log, advanced streaming, 4912197 -silesia, explicit params, advanced streaming, 4795857 -silesia, uncompressed literals, advanced streaming, 5116957 +silesia, explicit params, advanced streaming, 4795053 +silesia, uncompressed literals, advanced streaming, 5117625 silesia, uncompressed literals optimal, advanced streaming, 4316880 -silesia, huffman literals, advanced streaming, 5321370 +silesia, huffman literals, advanced streaming, 5321812 silesia, multithreaded with advanced params, advanced streaming, 5117795 -silesia.tar, level -5, advanced streaming, 6856523 -silesia.tar, level -3, advanced streaming, 6505954 -silesia.tar, level -1, advanced streaming, 6179056 -silesia.tar, level 0, advanced streaming, 4858632 -silesia.tar, level 1, advanced streaming, 5327708 -silesia.tar, level 3, advanced streaming, 4858632 -silesia.tar, level 4, advanced streaming, 4796895 -silesia.tar, level 5 row 1, advanced streaming, 4679020 -silesia.tar, level 5 row 2, advanced streaming, 4682355 -silesia.tar, level 5, advanced streaming, 4679020 -silesia.tar, level 6, advanced streaming, 4614558 -silesia.tar, level 7 row 1, advanced streaming, 4579823 -silesia.tar, level 7 row 2, advanced streaming, 4575601 -silesia.tar, level 7, advanced streaming, 4579823 +silesia.tar, level -5, advanced streaming, 6857458 +silesia.tar, level -3, advanced streaming, 6508562 +silesia.tar, level -1, advanced streaming, 6178057 +silesia.tar, level 0, advanced streaming, 4849720 +silesia.tar, level 1, advanced streaming, 5311452 +silesia.tar, level 3, advanced streaming, 4849720 +silesia.tar, level 4, advanced streaming, 4787534 +silesia.tar, level 5 row 1, advanced streaming, 4669420 +silesia.tar, level 5 row 2, advanced streaming, 4673610 +silesia.tar, level 5, advanced streaming, 4669420 +silesia.tar, level 6, advanced streaming, 4604125 +silesia.tar, level 7 row 1, advanced streaming, 4570206 +silesia.tar, level 7 row 2, advanced streaming, 4565792 +silesia.tar, level 7, advanced streaming, 4570206 silesia.tar, level 9, advanced streaming, 4555445 silesia.tar, level 11 row 1, advanced streaming, 4514959 silesia.tar, level 11 row 2, advanced streaming, 4513810 @@ -920,17 +920,17 @@ silesia.tar, level 12 row 2, advanced silesia.tar, level 13, advanced streaming, 4502956 silesia.tar, level 16, advanced streaming, 4360385 silesia.tar, level 19, advanced streaming, 4260939 -silesia.tar, no source size, advanced streaming, 4858628 -silesia.tar, long distance mode, advanced streaming, 4837775 +silesia.tar, no source size, advanced streaming, 4849716 +silesia.tar, long distance mode, advanced streaming, 4829339 silesia.tar, multithreaded, advanced streaming, 4841902 silesia.tar, multithreaded long distance mode, advanced streaming, 4834262 silesia.tar, small window log, advanced streaming, 7117024 silesia.tar, small hash log, advanced streaming, 6529209 silesia.tar, small chain log, advanced streaming, 4917021 -silesia.tar, explicit params, advanced streaming, 4807288 -silesia.tar, uncompressed literals, advanced streaming, 5126542 +silesia.tar, explicit params, advanced streaming, 4797673 +silesia.tar, uncompressed literals, advanced streaming, 5124811 silesia.tar, uncompressed literals optimal, advanced streaming, 4308451 -silesia.tar, huffman literals, advanced streaming, 5341712 +silesia.tar, huffman literals, advanced streaming, 5326278 silesia.tar, multithreaded with advanced params, advanced streaming, 5116442 github, level -5, advanced streaming, 204407 github, level -5 with dict, advanced streaming, 45832 @@ -1057,74 +1057,74 @@ github, uncompressed literals, advanced github, uncompressed literals optimal, advanced streaming, 152667 github, huffman literals, advanced streaming, 142365 github, multithreaded with advanced params, advanced streaming, 165909 -github.tar, level -5, advanced streaming, 52152 -github.tar, level -5 with dict, advanced streaming, 51181 -github.tar, level -3, advanced streaming, 45678 -github.tar, level -3 with dict, advanced streaming, 44734 -github.tar, level -1, advanced streaming, 42560 -github.tar, level -1 with dict, advanced streaming, 41353 -github.tar, level 0, advanced streaming, 38884 -github.tar, level 0 with dict, advanced streaming, 37995 -github.tar, level 0 with dict dms, advanced streaming, 38114 -github.tar, level 0 with dict dds, advanced streaming, 38114 -github.tar, level 0 with dict copy, advanced streaming, 37995 -github.tar, level 0 with dict load, advanced streaming, 37956 -github.tar, level 1, advanced streaming, 39200 -github.tar, level 1 with dict, advanced streaming, 38119 -github.tar, level 1 with dict dms, advanced streaming, 38406 -github.tar, level 1 with dict dds, advanced streaming, 38406 -github.tar, level 1 with dict copy, advanced streaming, 38119 -github.tar, level 1 with dict load, advanced streaming, 38364 -github.tar, level 3, advanced streaming, 38884 -github.tar, level 3 with dict, advanced streaming, 37995 -github.tar, level 3 with dict dms, advanced streaming, 38114 -github.tar, level 3 with dict dds, advanced streaming, 38114 -github.tar, level 3 with dict copy, advanced streaming, 37995 -github.tar, level 3 with dict load, advanced streaming, 37956 -github.tar, level 4, advanced streaming, 38880 -github.tar, level 4 with dict, advanced streaming, 37948 -github.tar, level 4 with dict dms, advanced streaming, 37995 -github.tar, level 4 with dict dds, advanced streaming, 37995 -github.tar, level 4 with dict copy, advanced streaming, 37948 -github.tar, level 4 with dict load, advanced streaming, 37927 -github.tar, level 5 row 1, advanced streaming, 39651 -github.tar, level 5 row 1 with dict dms, advanced streaming, 39043 -github.tar, level 5 row 1 with dict dds, advanced streaming, 39069 -github.tar, level 5 row 1 with dict copy, advanced streaming, 39145 -github.tar, level 5 row 1 with dict load, advanced streaming, 39000 -github.tar, level 5 row 2, advanced streaming, 39701 -github.tar, level 5 row 2 with dict dms, advanced streaming, 39365 -github.tar, level 5 row 2 with dict dds, advanced streaming, 39233 -github.tar, level 5 row 2 with dict copy, advanced streaming, 39715 -github.tar, level 5 row 2 with dict load, advanced streaming, 39158 -github.tar, level 5, advanced streaming, 39651 -github.tar, level 5 with dict, advanced streaming, 39145 -github.tar, level 5 with dict dms, advanced streaming, 39043 -github.tar, level 5 with dict dds, advanced streaming, 39069 -github.tar, level 5 with dict copy, advanced streaming, 39145 -github.tar, level 5 with dict load, advanced streaming, 39000 -github.tar, level 6, advanced streaming, 39282 -github.tar, level 6 with dict, advanced streaming, 38656 -github.tar, level 6 with dict dms, advanced streaming, 38640 -github.tar, level 6 with dict dds, advanced streaming, 38643 -github.tar, level 6 with dict copy, advanced streaming, 38656 -github.tar, level 6 with dict load, advanced streaming, 38647 -github.tar, level 7 row 1, advanced streaming, 38005 +github.tar, level -5, advanced streaming, 52384 +github.tar, level -5 with dict, advanced streaming, 51420 +github.tar, level -3, advanced streaming, 45907 +github.tar, level -3 with dict, advanced streaming, 44973 +github.tar, level -1, advanced streaming, 42777 +github.tar, level -1 with dict, advanced streaming, 41603 +github.tar, level 0, advanced streaming, 39249 +github.tar, level 0 with dict, advanced streaming, 38309 +github.tar, level 0 with dict dms, advanced streaming, 38445 +github.tar, level 0 with dict dds, advanced streaming, 38445 +github.tar, level 0 with dict copy, advanced streaming, 38309 +github.tar, level 0 with dict load, advanced streaming, 38281 +github.tar, level 1, advanced streaming, 39550 +github.tar, level 1 with dict, advanced streaming, 38502 +github.tar, level 1 with dict dms, advanced streaming, 38770 +github.tar, level 1 with dict dds, advanced streaming, 38770 +github.tar, level 1 with dict copy, advanced streaming, 38502 +github.tar, level 1 with dict load, advanced streaming, 38716 +github.tar, level 3, advanced streaming, 39249 +github.tar, level 3 with dict, advanced streaming, 38309 +github.tar, level 3 with dict dms, advanced streaming, 38445 +github.tar, level 3 with dict dds, advanced streaming, 38445 +github.tar, level 3 with dict copy, advanced streaming, 38309 +github.tar, level 3 with dict load, advanced streaming, 38281 +github.tar, level 4, advanced streaming, 39247 +github.tar, level 4 with dict, advanced streaming, 38270 +github.tar, level 4 with dict dms, advanced streaming, 38317 +github.tar, level 4 with dict dds, advanced streaming, 38317 +github.tar, level 4 with dict copy, advanced streaming, 38270 +github.tar, level 4 with dict load, advanced streaming, 38259 +github.tar, level 5 row 1, advanced streaming, 39986 +github.tar, level 5 row 1 with dict dms, advanced streaming, 39370 +github.tar, level 5 row 1 with dict dds, advanced streaming, 39396 +github.tar, level 5 row 1 with dict copy, advanced streaming, 39465 +github.tar, level 5 row 1 with dict load, advanced streaming, 39332 +github.tar, level 5 row 2, advanced streaming, 40038 +github.tar, level 5 row 2 with dict dms, advanced streaming, 39690 +github.tar, level 5 row 2 with dict dds, advanced streaming, 39555 +github.tar, level 5 row 2 with dict copy, advanced streaming, 40036 +github.tar, level 5 row 2 with dict load, advanced streaming, 39498 +github.tar, level 5, advanced streaming, 39986 +github.tar, level 5 with dict, advanced streaming, 39465 +github.tar, level 5 with dict dms, advanced streaming, 39370 +github.tar, level 5 with dict dds, advanced streaming, 39396 +github.tar, level 5 with dict copy, advanced streaming, 39465 +github.tar, level 5 with dict load, advanced streaming, 39332 +github.tar, level 6, advanced streaming, 39565 +github.tar, level 6 with dict, advanced streaming, 38894 +github.tar, level 6 with dict dms, advanced streaming, 38901 +github.tar, level 6 with dict dds, advanced streaming, 38903 +github.tar, level 6 with dict copy, advanced streaming, 38894 +github.tar, level 6 with dict load, advanced streaming, 38906 +github.tar, level 7 row 1, advanced streaming, 38295 github.tar, level 7 row 1 with dict dms, advanced streaming, 37832 github.tar, level 7 row 1 with dict dds, advanced streaming, 37857 github.tar, level 7 row 1 with dict copy, advanced streaming, 37839 -github.tar, level 7 row 1 with dict load, advanced streaming, 37286 -github.tar, level 7 row 2, advanced streaming, 38077 +github.tar, level 7 row 1 with dict load, advanced streaming, 37565 +github.tar, level 7 row 2, advanced streaming, 38369 github.tar, level 7 row 2 with dict dms, advanced streaming, 38012 github.tar, level 7 row 2 with dict dds, advanced streaming, 38014 github.tar, level 7 row 2 with dict copy, advanced streaming, 38101 -github.tar, level 7 row 2 with dict load, advanced streaming, 37402 -github.tar, level 7, advanced streaming, 38005 +github.tar, level 7 row 2 with dict load, advanced streaming, 37688 +github.tar, level 7, advanced streaming, 38295 github.tar, level 7 with dict, advanced streaming, 37839 github.tar, level 7 with dict dms, advanced streaming, 37832 github.tar, level 7 with dict dds, advanced streaming, 37857 github.tar, level 7 with dict copy, advanced streaming, 37839 -github.tar, level 7 with dict load, advanced streaming, 37286 +github.tar, level 7 with dict load, advanced streaming, 37565 github.tar, level 9, advanced streaming, 36723 github.tar, level 9 with dict, advanced streaming, 36531 github.tar, level 9 with dict dms, advanced streaming, 36615 @@ -1169,55 +1169,55 @@ github.tar, level 19 with dict dms, advanced github.tar, level 19 with dict dds, advanced streaming, 32565 github.tar, level 19 with dict copy, advanced streaming, 32701 github.tar, level 19 with dict load, advanced streaming, 32428 -github.tar, no source size, advanced streaming, 38881 -github.tar, no source size with dict, advanced streaming, 38111 -github.tar, long distance mode, advanced streaming, 40242 +github.tar, no source size, advanced streaming, 39246 +github.tar, no source size with dict, advanced streaming, 38442 +github.tar, long distance mode, advanced streaming, 40569 github.tar, multithreaded, advanced streaming, 39067 github.tar, multithreaded long distance mode, advanced streaming, 40377 github.tar, small window log, advanced streaming, 199553 github.tar, small hash log, advanced streaming, 129870 github.tar, small chain log, advanced streaming, 41669 -github.tar, explicit params, advanced streaming, 41385 -github.tar, uncompressed literals, advanced streaming, 41562 +github.tar, explicit params, advanced streaming, 41768 +github.tar, uncompressed literals, advanced streaming, 41784 github.tar, uncompressed literals optimal, advanced streaming, 35356 -github.tar, huffman literals, advanced streaming, 38853 +github.tar, huffman literals, advanced streaming, 39226 github.tar, multithreaded with advanced params, advanced streaming, 41700 -silesia, level -5, old streaming, 6854744 -silesia, level -3, old streaming, 6503319 -silesia, level -1, old streaming, 6172207 -silesia, level 0, old streaming, 4839431 -silesia, level 1, old streaming, 5306388 -silesia, level 3, old streaming, 4839431 -silesia, level 4, old streaming, 4776557 -silesia, level 5, old streaming, 4667668 -silesia, level 6, old streaming, 4604351 -silesia, level 7, old streaming, 4570271 +silesia, level -5, old streaming, 6856699 +silesia, level -3, old streaming, 6505694 +silesia, level -1, old streaming, 6174139 +silesia, level 0, old streaming, 4839173 +silesia, level 1, old streaming, 5305682 +silesia, level 3, old streaming, 4839173 +silesia, level 4, old streaming, 4776074 +silesia, level 5, old streaming, 4667049 +silesia, level 6, old streaming, 4602956 +silesia, level 7, old streaming, 4568785 silesia, level 9, old streaming, 4545850 silesia, level 13, old streaming, 4493990 silesia, level 16, old streaming, 4359652 silesia, level 19, old streaming, 4266582 -silesia, no source size, old streaming, 4839395 -silesia, uncompressed literals, old streaming, 4839431 +silesia, no source size, old streaming, 4839137 +silesia, uncompressed literals, old streaming, 4839173 silesia, uncompressed literals optimal, old streaming, 4266582 -silesia, huffman literals, old streaming, 6172207 -silesia.tar, level -5, old streaming, 6856523 -silesia.tar, level -3, old streaming, 6505954 -silesia.tar, level -1, old streaming, 6179056 -silesia.tar, level 0, old streaming, 4858632 -silesia.tar, level 1, old streaming, 5327708 -silesia.tar, level 3, old streaming, 4858632 -silesia.tar, level 4, old streaming, 4796895 -silesia.tar, level 5, old streaming, 4679020 -silesia.tar, level 6, old streaming, 4614558 -silesia.tar, level 7, old streaming, 4579823 +silesia, huffman literals, old streaming, 6174139 +silesia.tar, level -5, old streaming, 6857458 +silesia.tar, level -3, old streaming, 6508562 +silesia.tar, level -1, old streaming, 6178057 +silesia.tar, level 0, old streaming, 4849720 +silesia.tar, level 1, old streaming, 5311452 +silesia.tar, level 3, old streaming, 4849720 +silesia.tar, level 4, old streaming, 4787534 +silesia.tar, level 5, old streaming, 4669420 +silesia.tar, level 6, old streaming, 4604125 +silesia.tar, level 7, old streaming, 4570206 silesia.tar, level 9, old streaming, 4555445 silesia.tar, level 13, old streaming, 4502956 silesia.tar, level 16, old streaming, 4360385 silesia.tar, level 19, old streaming, 4260939 -silesia.tar, no source size, old streaming, 4858628 -silesia.tar, uncompressed literals, old streaming, 4858632 +silesia.tar, no source size, old streaming, 4849716 +silesia.tar, uncompressed literals, old streaming, 4849720 silesia.tar, uncompressed literals optimal, old streaming, 4260939 -silesia.tar, huffman literals, old streaming, 6179056 +silesia.tar, huffman literals, old streaming, 6178057 github, level -5, old streaming, 204407 github, level -5 with dict, old streaming, 45832 github, level -3, old streaming, 193253 @@ -1251,25 +1251,25 @@ github, no source size with dict, old stre github, uncompressed literals, old streaming, 136331 github, uncompressed literals optimal, old streaming, 132879 github, huffman literals, old streaming, 175468 -github.tar, level -5, old streaming, 52152 -github.tar, level -5 with dict, old streaming, 51181 -github.tar, level -3, old streaming, 45678 -github.tar, level -3 with dict, old streaming, 44734 -github.tar, level -1, old streaming, 42560 -github.tar, level -1 with dict, old streaming, 41353 -github.tar, level 0, old streaming, 38884 -github.tar, level 0 with dict, old streaming, 37995 -github.tar, level 1, old streaming, 39200 -github.tar, level 1 with dict, old streaming, 38119 -github.tar, level 3, old streaming, 38884 -github.tar, level 3 with dict, old streaming, 37995 -github.tar, level 4, old streaming, 38880 -github.tar, level 4 with dict, old streaming, 37948 -github.tar, level 5, old streaming, 39651 -github.tar, level 5 with dict, old streaming, 39145 -github.tar, level 6, old streaming, 39282 -github.tar, level 6 with dict, old streaming, 38656 -github.tar, level 7, old streaming, 38005 +github.tar, level -5, old streaming, 52384 +github.tar, level -5 with dict, old streaming, 51420 +github.tar, level -3, old streaming, 45907 +github.tar, level -3 with dict, old streaming, 44973 +github.tar, level -1, old streaming, 42777 +github.tar, level -1 with dict, old streaming, 41603 +github.tar, level 0, old streaming, 39249 +github.tar, level 0 with dict, old streaming, 38309 +github.tar, level 1, old streaming, 39550 +github.tar, level 1 with dict, old streaming, 38502 +github.tar, level 3, old streaming, 39249 +github.tar, level 3 with dict, old streaming, 38309 +github.tar, level 4, old streaming, 39247 +github.tar, level 4 with dict, old streaming, 38270 +github.tar, level 5, old streaming, 39986 +github.tar, level 5 with dict, old streaming, 39465 +github.tar, level 6, old streaming, 39565 +github.tar, level 6 with dict, old streaming, 38894 +github.tar, level 7, old streaming, 38295 github.tar, level 7 with dict, old streaming, 37839 github.tar, level 9, old streaming, 36723 github.tar, level 9 with dict, old streaming, 36531 @@ -1279,63 +1279,63 @@ github.tar, level 16, old stre github.tar, level 16 with dict, old streaming, 33375 github.tar, level 19, old streaming, 32262 github.tar, level 19 with dict, old streaming, 32701 -github.tar, no source size, old streaming, 38881 -github.tar, no source size with dict, old streaming, 38111 -github.tar, uncompressed literals, old streaming, 38884 +github.tar, no source size, old streaming, 39246 +github.tar, no source size with dict, old streaming, 38442 +github.tar, uncompressed literals, old streaming, 39249 github.tar, uncompressed literals optimal, old streaming, 32262 -github.tar, huffman literals, old streaming, 42560 -silesia, level -5, old streaming advanced, 6854744 -silesia, level -3, old streaming advanced, 6503319 -silesia, level -1, old streaming advanced, 6172207 -silesia, level 0, old streaming advanced, 4839431 -silesia, level 1, old streaming advanced, 5306388 -silesia, level 3, old streaming advanced, 4839431 -silesia, level 4, old streaming advanced, 4776557 -silesia, level 5, old streaming advanced, 4667668 -silesia, level 6, old streaming advanced, 4604351 -silesia, level 7, old streaming advanced, 4570271 +github.tar, huffman literals, old streaming, 42777 +silesia, level -5, old streaming advanced, 6856699 +silesia, level -3, old streaming advanced, 6505694 +silesia, level -1, old streaming advanced, 6174139 +silesia, level 0, old streaming advanced, 4839173 +silesia, level 1, old streaming advanced, 5305682 +silesia, level 3, old streaming advanced, 4839173 +silesia, level 4, old streaming advanced, 4776074 +silesia, level 5, old streaming advanced, 4667049 +silesia, level 6, old streaming advanced, 4602956 +silesia, level 7, old streaming advanced, 4568785 silesia, level 9, old streaming advanced, 4545850 silesia, level 13, old streaming advanced, 4493990 silesia, level 16, old streaming advanced, 4359652 silesia, level 19, old streaming advanced, 4266582 -silesia, no source size, old streaming advanced, 4839395 -silesia, long distance mode, old streaming advanced, 4839431 -silesia, multithreaded, old streaming advanced, 4839431 -silesia, multithreaded long distance mode, old streaming advanced, 4839431 +silesia, no source size, old streaming advanced, 4839137 +silesia, long distance mode, old streaming advanced, 4839173 +silesia, multithreaded, old streaming advanced, 4839173 +silesia, multithreaded long distance mode, old streaming advanced, 4839173 silesia, small window log, old streaming advanced, 7110591 silesia, small hash log, old streaming advanced, 6526141 silesia, small chain log, old streaming advanced, 4912197 -silesia, explicit params, old streaming advanced, 4795857 -silesia, uncompressed literals, old streaming advanced, 4839431 +silesia, explicit params, old streaming advanced, 4795053 +silesia, uncompressed literals, old streaming advanced, 4839173 silesia, uncompressed literals optimal, old streaming advanced, 4266582 -silesia, huffman literals, old streaming advanced, 6172207 -silesia, multithreaded with advanced params, old streaming advanced, 4839431 -silesia.tar, level -5, old streaming advanced, 6856523 -silesia.tar, level -3, old streaming advanced, 6505954 -silesia.tar, level -1, old streaming advanced, 6179056 -silesia.tar, level 0, old streaming advanced, 4858632 -silesia.tar, level 1, old streaming advanced, 5327708 -silesia.tar, level 3, old streaming advanced, 4858632 -silesia.tar, level 4, old streaming advanced, 4796895 -silesia.tar, level 5, old streaming advanced, 4679020 -silesia.tar, level 6, old streaming advanced, 4614558 -silesia.tar, level 7, old streaming advanced, 4579823 +silesia, huffman literals, old streaming advanced, 6174139 +silesia, multithreaded with advanced params, old streaming advanced, 4839173 +silesia.tar, level -5, old streaming advanced, 6857458 +silesia.tar, level -3, old streaming advanced, 6508562 +silesia.tar, level -1, old streaming advanced, 6178057 +silesia.tar, level 0, old streaming advanced, 4849720 +silesia.tar, level 1, old streaming advanced, 5311452 +silesia.tar, level 3, old streaming advanced, 4849720 +silesia.tar, level 4, old streaming advanced, 4787534 +silesia.tar, level 5, old streaming advanced, 4669420 +silesia.tar, level 6, old streaming advanced, 4604125 +silesia.tar, level 7, old streaming advanced, 4570206 silesia.tar, level 9, old streaming advanced, 4555445 silesia.tar, level 13, old streaming advanced, 4502956 silesia.tar, level 16, old streaming advanced, 4360385 silesia.tar, level 19, old streaming advanced, 4260939 -silesia.tar, no source size, old streaming advanced, 4858628 -silesia.tar, long distance mode, old streaming advanced, 4858632 -silesia.tar, multithreaded, old streaming advanced, 4858632 -silesia.tar, multithreaded long distance mode, old streaming advanced, 4858632 +silesia.tar, no source size, old streaming advanced, 4849716 +silesia.tar, long distance mode, old streaming advanced, 4849720 +silesia.tar, multithreaded, old streaming advanced, 4849720 +silesia.tar, multithreaded long distance mode, old streaming advanced, 4849720 silesia.tar, small window log, old streaming advanced, 7117027 silesia.tar, small hash log, old streaming advanced, 6529209 silesia.tar, small chain log, old streaming advanced, 4917021 -silesia.tar, explicit params, old streaming advanced, 4807288 -silesia.tar, uncompressed literals, old streaming advanced, 4858632 +silesia.tar, explicit params, old streaming advanced, 4797673 +silesia.tar, uncompressed literals, old streaming advanced, 4849720 silesia.tar, uncompressed literals optimal, old streaming advanced, 4260939 -silesia.tar, huffman literals, old streaming advanced, 6179056 -silesia.tar, multithreaded with advanced params, old streaming advanced, 4858632 +silesia.tar, huffman literals, old streaming advanced, 6178057 +silesia.tar, multithreaded with advanced params, old streaming advanced, 4849720 github, level -5, old streaming advanced, 213265 github, level -5 with dict, old streaming advanced, 46708 github, level -3, old streaming advanced, 196126 @@ -1377,26 +1377,26 @@ github, uncompressed literals, old stre github, uncompressed literals optimal, old streaming advanced, 132879 github, huffman literals, old streaming advanced, 181107 github, multithreaded with advanced params, old streaming advanced, 141101 -github.tar, level -5, old streaming advanced, 52152 -github.tar, level -5 with dict, old streaming advanced, 51129 -github.tar, level -3, old streaming advanced, 45678 -github.tar, level -3 with dict, old streaming advanced, 44986 -github.tar, level -1, old streaming advanced, 42560 -github.tar, level -1 with dict, old streaming advanced, 41650 -github.tar, level 0, old streaming advanced, 38884 -github.tar, level 0 with dict, old streaming advanced, 38013 -github.tar, level 1, old streaming advanced, 39200 -github.tar, level 1 with dict, old streaming advanced, 38359 -github.tar, level 3, old streaming advanced, 38884 -github.tar, level 3 with dict, old streaming advanced, 38013 -github.tar, level 4, old streaming advanced, 38880 -github.tar, level 4 with dict, old streaming advanced, 38063 -github.tar, level 5, old streaming advanced, 39651 -github.tar, level 5 with dict, old streaming advanced, 39018 -github.tar, level 6, old streaming advanced, 39282 -github.tar, level 6 with dict, old streaming advanced, 38635 -github.tar, level 7, old streaming advanced, 38005 -github.tar, level 7 with dict, old streaming advanced, 37264 +github.tar, level -5, old streaming advanced, 52384 +github.tar, level -5 with dict, old streaming advanced, 51359 +github.tar, level -3, old streaming advanced, 45907 +github.tar, level -3 with dict, old streaming advanced, 45211 +github.tar, level -1, old streaming advanced, 42777 +github.tar, level -1 with dict, old streaming advanced, 41865 +github.tar, level 0, old streaming advanced, 39249 +github.tar, level 0 with dict, old streaming advanced, 38327 +github.tar, level 1, old streaming advanced, 39550 +github.tar, level 1 with dict, old streaming advanced, 38714 +github.tar, level 3, old streaming advanced, 39249 +github.tar, level 3 with dict, old streaming advanced, 38327 +github.tar, level 4, old streaming advanced, 39247 +github.tar, level 4 with dict, old streaming advanced, 38382 +github.tar, level 5, old streaming advanced, 39986 +github.tar, level 5 with dict, old streaming advanced, 39347 +github.tar, level 6, old streaming advanced, 39565 +github.tar, level 6 with dict, old streaming advanced, 38889 +github.tar, level 7, old streaming advanced, 38295 +github.tar, level 7 with dict, old streaming advanced, 37534 github.tar, level 9, old streaming advanced, 36723 github.tar, level 9 with dict, old streaming advanced, 36241 github.tar, level 13, old streaming advanced, 35501 @@ -1405,19 +1405,19 @@ github.tar, level 16, old stre github.tar, level 16 with dict, old streaming advanced, 38578 github.tar, level 19, old streaming advanced, 32262 github.tar, level 19 with dict, old streaming advanced, 32678 -github.tar, no source size, old streaming advanced, 38881 -github.tar, no source size with dict, old streaming advanced, 38076 -github.tar, long distance mode, old streaming advanced, 38884 -github.tar, multithreaded, old streaming advanced, 38884 -github.tar, multithreaded long distance mode, old streaming advanced, 38884 +github.tar, no source size, old streaming advanced, 39246 +github.tar, no source size with dict, old streaming advanced, 38399 +github.tar, long distance mode, old streaming advanced, 39249 +github.tar, multithreaded, old streaming advanced, 39249 +github.tar, multithreaded long distance mode, old streaming advanced, 39249 github.tar, small window log, old streaming advanced, 199556 github.tar, small hash log, old streaming advanced, 129870 github.tar, small chain log, old streaming advanced, 41669 -github.tar, explicit params, old streaming advanced, 41385 -github.tar, uncompressed literals, old streaming advanced, 38884 +github.tar, explicit params, old streaming advanced, 41768 +github.tar, uncompressed literals, old streaming advanced, 39249 github.tar, uncompressed literals optimal, old streaming advanced, 32262 -github.tar, huffman literals, old streaming advanced, 42560 -github.tar, multithreaded with advanced params, old streaming advanced, 38884 +github.tar, huffman literals, old streaming advanced, 42777 +github.tar, multithreaded with advanced params, old streaming advanced, 39249 github, level -5 with dict, old streaming cdict, 45832 github, level -3 with dict, old streaming cdict, 44671 github, level -1 with dict, old streaming cdict, 41825 @@ -1433,21 +1433,21 @@ github, level 13 with dict, old stre github, level 16 with dict, old streaming cdict, 37902 github, level 19 with dict, old streaming cdict, 37916 github, no source size with dict, old streaming cdict, 40652 -github.tar, level -5 with dict, old streaming cdict, 51286 -github.tar, level -3 with dict, old streaming cdict, 45147 -github.tar, level -1 with dict, old streaming cdict, 41865 -github.tar, level 0 with dict, old streaming cdict, 37956 -github.tar, level 1 with dict, old streaming cdict, 38364 -github.tar, level 3 with dict, old streaming cdict, 37956 -github.tar, level 4 with dict, old streaming cdict, 37927 -github.tar, level 5 with dict, old streaming cdict, 39000 -github.tar, level 6 with dict, old streaming cdict, 38647 -github.tar, level 7 with dict, old streaming cdict, 37286 +github.tar, level -5 with dict, old streaming cdict, 51512 +github.tar, level -3 with dict, old streaming cdict, 45379 +github.tar, level -1 with dict, old streaming cdict, 42084 +github.tar, level 0 with dict, old streaming cdict, 38281 +github.tar, level 1 with dict, old streaming cdict, 38716 +github.tar, level 3 with dict, old streaming cdict, 38281 +github.tar, level 4 with dict, old streaming cdict, 38259 +github.tar, level 5 with dict, old streaming cdict, 39332 +github.tar, level 6 with dict, old streaming cdict, 38906 +github.tar, level 7 with dict, old streaming cdict, 37565 github.tar, level 9 with dict, old streaming cdict, 36322 github.tar, level 13 with dict, old streaming cdict, 36010 github.tar, level 16 with dict, old streaming cdict, 39081 github.tar, level 19 with dict, old streaming cdict, 32428 -github.tar, no source size with dict, old streaming cdict, 38111 +github.tar, no source size with dict, old streaming cdict, 38442 github, level -5 with dict, old streaming advanced cdict, 46708 github, level -3 with dict, old streaming advanced cdict, 45476 github, level -1 with dict, old streaming advanced cdict, 42060 @@ -1463,18 +1463,18 @@ github, level 13 with dict, old stre github, level 16 with dict, old streaming advanced cdict, 40804 github, level 19 with dict, old streaming advanced cdict, 37916 github, no source size with dict, old streaming advanced cdict, 40608 -github.tar, level -5 with dict, old streaming advanced cdict, 50791 -github.tar, level -3 with dict, old streaming advanced cdict, 44926 -github.tar, level -1 with dict, old streaming advanced cdict, 41482 -github.tar, level 0 with dict, old streaming advanced cdict, 38013 -github.tar, level 1 with dict, old streaming advanced cdict, 38168 -github.tar, level 3 with dict, old streaming advanced cdict, 38013 -github.tar, level 4 with dict, old streaming advanced cdict, 38063 -github.tar, level 5 with dict, old streaming advanced cdict, 39018 -github.tar, level 6 with dict, old streaming advanced cdict, 38635 -github.tar, level 7 with dict, old streaming advanced cdict, 37264 +github.tar, level -5 with dict, old streaming advanced cdict, 51019 +github.tar, level -3 with dict, old streaming advanced cdict, 45149 +github.tar, level -1 with dict, old streaming advanced cdict, 41694 +github.tar, level 0 with dict, old streaming advanced cdict, 38327 +github.tar, level 1 with dict, old streaming advanced cdict, 38513 +github.tar, level 3 with dict, old streaming advanced cdict, 38327 +github.tar, level 4 with dict, old streaming advanced cdict, 38382 +github.tar, level 5 with dict, old streaming advanced cdict, 39347 +github.tar, level 6 with dict, old streaming advanced cdict, 38889 +github.tar, level 7 with dict, old streaming advanced cdict, 37534 github.tar, level 9 with dict, old streaming advanced cdict, 36241 github.tar, level 13 with dict, old streaming advanced cdict, 35807 github.tar, level 16 with dict, old streaming advanced cdict, 38578 github.tar, level 19 with dict, old streaming advanced cdict, 32678 -github.tar, no source size with dict, old streaming advanced cdict, 38076 +github.tar, no source size with dict, old streaming advanced cdict, 38399 From 90095f056d4ccb8e0ed0942b2e30a664f0489932 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 11:36:56 -0700 Subject: [PATCH 43/44] apply limit conditions for all splitting strategies instead of just for blind split. This is in anticipation of adversarial input, that would intentionally target the sampling pattern of the split detector. Note that, even without this protection, splitting can never expand beyond ZSTD_COMPRESSBOUND(), because this upper limit uses a 1KB block size worst case scenario, and splitting never creates blocks thath small. The protection is more to ensure that data is not expanded by more than 3-bytes per 128 KB full block, which is a much stricter limit. --- lib/compress/zstd_compress.c | 38 ++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3ab7414d4..437bd1fbe 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4499,6 +4499,11 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src */ if (srcSize < 128 KB || blockSizeMax < 128 KB) return MIN(srcSize, blockSizeMax); + /* do not split incompressible data though: + * ensure a 3 bytes per full block overhead limit. + * Note: as a consequence, the first full block skips the splitting detector. + */ + if (savings < 3) return 128 KB; /* dynamic splitting has a cpu cost for analysis, * due to that cost it's only used for higher levels */ if (strat >= ZSTD_btopt) @@ -4508,9 +4513,8 @@ static size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t src /* blind split strategy * heuristic value, tested as being "generally better". * no cpu cost, but can over-split homegeneous data. - * do not split incompressible data though: respect the 3 bytes per block overhead limit. */ - return (savings > 3) ? 92 KB : 128 KB; + return 92 KB; } /*! ZSTD_compress_frameChunk() : @@ -4587,21 +4591,21 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ - /* @savings is employed by the blind-split strategy, - * to authorize splitting into less-than-full blocks, - * and thus avoid oversplitting blocks in case of incompressible data: - * when @savings is not large enough, blind split is disactivated, and full block is used instead. - * If data is incompressible, it's allowed to expand it by 3-bytes per full block. - * For large data, a full block is 128 KB. - * blind-split will instead use 92 KB as block size. - * So it expands incompressible data by 3-bytes per 92 KB block. - * That's an over-expansion of ((128*3) - (92*3)) / 128 = 0.84 bytes per block. - * Therefore, when data doesn't shrink, we subtract a 1 byte malus from @savings. - * This is a conservative estimate, especially as we don't count the 3-bytes header when there are savings, - * but it doesn't matter, the goal is not accuracy, - * the goal is to ensure the 3-bytes expansion limit per 128 KB input can never be breached */ - if (cSize < blockSize) savings += (blockSize - cSize); - else savings--; + /* @savings is employed to ensure that splitting doesn't worsen expansion of incompressible data. + * Without splitting, the maximum expansion is 3 bytes per full block. + * An adversarial input could attempt to fudge the split detector, + * and make it split incompressible data, resulting in more block headers. + * Note that, since ZSTD_COMPRESSBOUND() assumes a worst case scenario of 1KB per block, + * and the splitter never creates blocks that small (current lower limit is 8 KB), + * there is already no risk to expand beyond ZSTD_COMPRESSBOUND() limit. + * But if the goal is to not expand by more than 3-bytes per 128 KB full block, + * then yes, it becomes possible to make the block splitter oversplit incompressible data. + * Using @savings, we enforce an even more conservative condition, + * requiring the presence of enough savings (at least 3 bytes) to authorize splitting, + * otherwise only full blocks are used. + * But being conservative is fine, + * since splitting barely compressible blocks is not fruitful anyway */ + savings += (S64)blockSize - (S64)cSize; ip += blockSize; assert(remaining >= blockSize); From 70c77d20d63454b58e220c235e215147a357220c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 24 Oct 2024 11:43:16 -0700 Subject: [PATCH 44/44] update regression results first block is no longer splitted since adding the @savings over-split protection --- tests/regression/results.csv | 72 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/regression/results.csv b/tests/regression/results.csv index 2ac686962..ea5ed58d5 100644 --- a/tests/regression/results.csv +++ b/tests/regression/results.csv @@ -43,19 +43,19 @@ silesia, level 4, compress silesia, level 5, compress cctx, 4666524 silesia, level 6, compress cctx, 4602031 silesia, level 7, compress cctx, 4567954 -silesia, level 9, compress cctx, 4535624 -silesia, level 13, compress cctx, 4484013 -silesia, level 16, compress cctx, 4356207 -silesia, level 19, compress cctx, 4266751 +silesia, level 9, compress cctx, 4540520 +silesia, level 13, compress cctx, 4488969 +silesia, level 16, compress cctx, 4356799 +silesia, level 19, compress cctx, 4265851 silesia, long distance mode, compress cctx, 4838417 silesia, multithreaded, compress cctx, 4838417 silesia, multithreaded long distance mode, compress cctx, 4838417 silesia, small window log, compress cctx, 7082907 -silesia, small hash log, compress cctx, 6524931 -silesia, small chain log, compress cctx, 4912322 +silesia, small hash log, compress cctx, 6525510 +silesia, small chain log, compress cctx, 4912248 silesia, explicit params, compress cctx, 4792640 silesia, uncompressed literals, compress cctx, 4838417 -silesia, uncompressed literals optimal, compress cctx, 4266751 +silesia, uncompressed literals optimal, compress cctx, 4265851 silesia, huffman literals, compress cctx, 6174127 silesia, multithreaded with advanced params, compress cctx, 4838417 github, level -5, compress cctx, 204407 @@ -107,19 +107,19 @@ silesia, level 4, zstdcli, silesia, level 5, zstdcli, 4666931 silesia, level 6, zstdcli, 4602509 silesia, level 7, zstdcli, 4568265 -silesia, level 9, zstdcli, 4535309 -silesia, level 13, zstdcli, 4483601 -silesia, level 16, zstdcli, 4357591 -silesia, level 19, zstdcli, 4266865 +silesia, level 9, zstdcli, 4540123 +silesia, level 13, zstdcli, 4488478 +silesia, level 16, zstdcli, 4358150 +silesia, level 19, zstdcli, 4265929 silesia, long distance mode, zstdcli, 4830467 silesia, multithreaded, zstdcli, 4838997 silesia, multithreaded long distance mode, zstdcli, 4830467 silesia, small window log, zstdcli, 7094528 -silesia, small hash log, zstdcli, 6526639 -silesia, small chain log, zstdcli, 4911746 +silesia, small hash log, zstdcli, 6527214 +silesia, small chain log, zstdcli, 4911647 silesia, explicit params, zstdcli, 4794378 silesia, uncompressed literals, zstdcli, 5117843 -silesia, uncompressed literals optimal, zstdcli, 4317311 +silesia, uncompressed literals optimal, zstdcli, 4316761 silesia, huffman literals, zstdcli, 5320793 silesia, multithreaded with advanced params, zstdcli, 5117843 silesia.tar, level -5, zstdcli, 6860173 @@ -242,24 +242,24 @@ silesia, level 6, advanced silesia, level 7 row 1, advanced one pass, 4567954 silesia, level 7 row 2, advanced one pass, 4562774 silesia, level 7, advanced one pass, 4567954 -silesia, level 9, advanced one pass, 4535624 -silesia, level 11 row 1, advanced one pass, 4495623 -silesia, level 11 row 2, advanced one pass, 4493258 -silesia, level 12 row 1, advanced one pass, 4495623 -silesia, level 12 row 2, advanced one pass, 4493258 -silesia, level 13, advanced one pass, 4484013 -silesia, level 16, advanced one pass, 4356207 -silesia, level 19, advanced one pass, 4266751 +silesia, level 9, advanced one pass, 4540520 +silesia, level 11 row 1, advanced one pass, 4500472 +silesia, level 11 row 2, advanced one pass, 4498174 +silesia, level 12 row 1, advanced one pass, 4500472 +silesia, level 12 row 2, advanced one pass, 4498174 +silesia, level 13, advanced one pass, 4488969 +silesia, level 16, advanced one pass, 4356799 +silesia, level 19, advanced one pass, 4265851 silesia, no source size, advanced one pass, 4838417 silesia, long distance mode, advanced one pass, 4830097 silesia, multithreaded, advanced one pass, 4838949 silesia, multithreaded long distance mode, advanced one pass, 4830419 silesia, small window log, advanced one pass, 7094480 -silesia, small hash log, advanced one pass, 6524931 -silesia, small chain log, advanced one pass, 4912322 +silesia, small hash log, advanced one pass, 6525510 +silesia, small chain log, advanced one pass, 4912248 silesia, explicit params, advanced one pass, 4794219 silesia, uncompressed literals, advanced one pass, 5117482 -silesia, uncompressed literals optimal, advanced one pass, 4317186 +silesia, uncompressed literals optimal, advanced one pass, 4316644 silesia, huffman literals, advanced one pass, 5321686 silesia, multithreaded with advanced params, advanced one pass, 5117795 silesia.tar, level -5, advanced one pass, 6860782 @@ -560,24 +560,24 @@ silesia, level 6, advanced silesia, level 7 row 1, advanced one pass small out, 4567954 silesia, level 7 row 2, advanced one pass small out, 4562774 silesia, level 7, advanced one pass small out, 4567954 -silesia, level 9, advanced one pass small out, 4535624 -silesia, level 11 row 1, advanced one pass small out, 4495623 -silesia, level 11 row 2, advanced one pass small out, 4493258 -silesia, level 12 row 1, advanced one pass small out, 4495623 -silesia, level 12 row 2, advanced one pass small out, 4493258 -silesia, level 13, advanced one pass small out, 4484013 -silesia, level 16, advanced one pass small out, 4356207 -silesia, level 19, advanced one pass small out, 4266751 +silesia, level 9, advanced one pass small out, 4540520 +silesia, level 11 row 1, advanced one pass small out, 4500472 +silesia, level 11 row 2, advanced one pass small out, 4498174 +silesia, level 12 row 1, advanced one pass small out, 4500472 +silesia, level 12 row 2, advanced one pass small out, 4498174 +silesia, level 13, advanced one pass small out, 4488969 +silesia, level 16, advanced one pass small out, 4356799 +silesia, level 19, advanced one pass small out, 4265851 silesia, no source size, advanced one pass small out, 4838417 silesia, long distance mode, advanced one pass small out, 4830097 silesia, multithreaded, advanced one pass small out, 4838949 silesia, multithreaded long distance mode, advanced one pass small out, 4830419 silesia, small window log, advanced one pass small out, 7094480 -silesia, small hash log, advanced one pass small out, 6524931 -silesia, small chain log, advanced one pass small out, 4912322 +silesia, small hash log, advanced one pass small out, 6525510 +silesia, small chain log, advanced one pass small out, 4912248 silesia, explicit params, advanced one pass small out, 4794219 silesia, uncompressed literals, advanced one pass small out, 5117482 -silesia, uncompressed literals optimal, advanced one pass small out, 4317186 +silesia, uncompressed literals optimal, advanced one pass small out, 4316644 silesia, huffman literals, advanced one pass small out, 5321686 silesia, multithreaded with advanced params, advanced one pass small out, 5117795 silesia.tar, level -5, advanced one pass small out, 6860782