From 3564487614491f5a1e799e64616f7c50d8ab5746 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 2 Nov 2015 16:14:46 +0100 Subject: [PATCH 01/14] lazydeep --- Makefile | 2 +- NEWS | 3 + lib/zstd.h | 2 +- lib/zstdhc.c | 150 +++++++++++++++++++++++++++++++++++++++--- lib/zstdhc_static.h | 2 +- programs/Makefile | 2 +- programs/paramgrill.c | 16 ++--- programs/zstdcli.c | 2 +- 8 files changed, 156 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 7f90fd295f5..34d425e0995 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ # ################################################################ # Version number -export VERSION := 0.3.2 +export VERSION := 0.3.3 PRGDIR = programs ZSTDDIR = lib diff --git a/NEWS b/NEWS index 9693d779390..ee8c47bea62 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +v0.3.3 +Small compression ratio improvement + v0.3.2 Fixed Visual Studio diff --git a/lib/zstd.h b/lib/zstd.h index d17bc4a333f..d79410d1517 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -48,7 +48,7 @@ extern "C" { ***************************************/ #define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */ #define ZSTD_VERSION_MINOR 3 /* for new (non-breaking) interface capabilities */ -#define ZSTD_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */ +#define ZSTD_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) unsigned ZSTD_versionNumber (void); diff --git a/lib/zstdhc.c b/lib/zstdhc.c index 58615f8ccdb..e6de28d4dbc 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -289,6 +289,127 @@ FORCE_INLINE size_t ZSTD_HC_insertAndFindBestMatch_selectMLS ( } +size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + seqStore_t* seqStorePtr = &(ctx->seqStore); + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip = istart; + const BYTE* anchor = istart; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - 8; + const BYTE* match = istart; + + size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; + const U32 maxSearches = 1 << ctx->params.searchLog; + const U32 mls = ctx->params.searchLength; + + /* init */ + ZSTD_resetSeqStore(seqStorePtr); + if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE; + + /* Match Loop */ + while (ip <= ilimit) + { + size_t matchLength; + size_t offset; + const BYTE* start; + + /* try to find a first match */ + if (MEM_read32(ip) == MEM_read32(ip - offset_2)) + { + /* repcode : we take it*/ + size_t offtmp = offset_2; + size_t litLength = ip - anchor; + matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend); + offset_2 = offset_1; + offset_1 = offtmp; + ZSTD_storeSeq(seqStorePtr, litLength, anchor, 0, matchLength); + ip += matchLength+MINMATCH; + anchor = ip; + continue; + } + + offset_2 = offset_1; + matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + if (!matchLength) { ip++; continue; } + + /* let's try to find a better solution */ + offset = ip - match; + start = ip; + + while (ip gain1) + matchLength = ml2, offset = 0, start = ip; + } + { + size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + size_t offset2 = ip - match; + int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4); + if (gain2 > gain1) + { + matchLength = ml2, offset = offset2, start = ip; + continue; /* search a better one */ + } + } + + if (ip gain1) + matchLength = ml2, offset = 0, start = ip; + } + { + size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + size_t offset2 = ip - match; + int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 8); + if (gain2 > gain1) + { + matchLength = ml2, offset = offset2, start = ip; + continue; + } + } + } + break; /* nothing found : store previous one */ + } + + /* store sequence */ + { + size_t litLength = start - anchor; + if (offset) offset_1 = offset; + ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH); + ip = start + matchLength; + anchor = ip; + } + + } + + /* Last Literals */ + { + size_t lastLLSize = iend - anchor; + memcpy(seqStorePtr->lit, anchor, lastLLSize); + seqStorePtr->lit += lastLLSize; + } + + /* Final compression stage */ + return ZSTD_compressSequences((BYTE*)dst, maxDstSize, + seqStorePtr, srcSize); +} + + size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) { seqStore_t* seqStorePtr = &(ctx->seqStore); @@ -343,19 +464,19 @@ size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSiz if (MEM_read32(ip) == MEM_read32(ip - offset_1)) { size_t ml2 = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH; - int gain2 = (int)(ml2 * 4); - int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset)); + int gain2 = (int)(ml2 * 3); + int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1); if (gain2 > gain1) { matchLength = ml2, offset = 0, start = ip; - break; + } } { size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); size_t offset2 = ip - match; - int gain2 = (int)(ml2*5 - ZSTD_highbit((U32)offset2)); /* raw approx */ - int gain1 = (int)(matchLength*5 - ZSTD_highbit((U32)offset)); + int gain2 = (int)(ml2*3 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 3); if (gain2 > gain1) { matchLength = ml2, offset = offset2, start = ip; @@ -488,11 +609,20 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, BYTE* const oend = op + maxDstSize; size_t (*blockCompressor) (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); - if (ctxPtr->params.strategy == ZSTD_HC_greedy) - blockCompressor = ZSTD_HC_compressBlock_greedy; - else - blockCompressor = ZSTD_HC_compressBlock_lazy; - + switch(ctxPtr->params.strategy) + { + case ZSTD_HC_greedy: + blockCompressor = ZSTD_HC_compressBlock_greedy; + break; + case ZSTD_HC_lazy: + blockCompressor = ZSTD_HC_compressBlock_lazy; + break; + case ZSTD_HC_lazydeep: + blockCompressor = ZSTD_HC_compressBlock_lazydeep; + break; + default : + return ERROR(GENERIC); /* unknown block compressor */ + } while (remaining > blockSize) { diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index cbc9385403b..40d0b60c8a9 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -45,7 +45,7 @@ extern "C" { /* ************************************* * Types ***************************************/ -typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy } ZSTD_HC_strategy; +typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy, ZSTD_HC_lazydeep } ZSTD_HC_strategy; typedef struct { U32 windowLog; /* largest match distance : impact decompression buffer size */ diff --git a/programs/Makefile b/programs/Makefile index 82125c9941f..8c700323235 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -30,7 +30,7 @@ # fullbench32: Same as fullbench, but forced to compile in 32-bits mode # ########################################################################## -VERSION?= 0.3.2 +VERSION?= 0.3.3 DESTDIR?= PREFIX ?= /usr/local diff --git a/programs/paramgrill.c b/programs/paramgrill.c index 4e84d80ae81..d27a22b5f39 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -425,16 +425,16 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, return 0; } -const char* g_stratName[2] = { "ZSTD_HC_greedy", "ZSTD_HC_lazy " }; +const char* g_stratName[] = { "ZSTD_HC_greedy ", "ZSTD_HC_lazy ", "ZSTD_HC_lazydeep" }; static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_HC_parameters params, size_t srcSize) { DISPLAY("\r%79s\r", ""); - fprintf(f," {%3u,%3u,%3u,%3u,%3u, %s }, ", + fprintf(f," {%3u,%3u,%3u,%3u,%3u, %s }, ", params.windowLog, params.chainLog, params.hashLog, params.searchLog, params.searchLength, g_stratName[params.strategy]); fprintf(f, - "/* level %2u */ /* R:%5.3f at %5.1f MB/s - %5.1f MB/s */ \n", + "/* level %2u */ /* R:%5.3f at %5.1f MB/s - %5.1f MB/s */\n", cLevel, (double)srcSize / result.cSize, (double)result.cSpeed / 1000., (double)result.dSpeed / 1000.); } @@ -576,7 +576,7 @@ static BYTE g_alreadyTested[ZSTD_HC_WINDOWLOG_MAX+1-ZSTD_HC_WINDOWLOG_MIN] [ZSTD_HC_HASHLOG_MAX+1-ZSTD_HC_HASHLOG_MIN] [ZSTD_HC_SEARCHLOG_MAX+1-ZSTD_HC_SEARCHLOG_MIN] [ZSTD_HC_SEARCHLENGTH_MAX+1-ZSTD_HC_SEARCHLENGTH_MIN] - [2 /* strategy */ ] = {}; /* init to zero */ + [3 /* strategy */ ] = {}; /* init to zero */ #define NB_TESTS_PLAYED(p) \ g_alreadyTested[p.windowLog-ZSTD_HC_WINDOWLOG_MIN] \ @@ -628,9 +628,9 @@ static void playAround(FILE* f, winnerInfo_t* winners, case 9: p.searchLength--; break; case 10: - p.strategy = ZSTD_HC_lazy; break; + p.strategy = (ZSTD_HC_strategy)(((U32)p.strategy)+1); break; case 11: - p.strategy = ZSTD_HC_greedy; break; + p.strategy = (ZSTD_HC_strategy)(((U32)p.strategy)-1); break; } } @@ -647,7 +647,7 @@ static void playAround(FILE* f, winnerInfo_t* winners, if (p.searchLength > ZSTD_HC_SEARCHLENGTH_MAX) continue; if (p.searchLength < ZSTD_HC_SEARCHLENGTH_MIN) continue; if (p.strategy < ZSTD_HC_greedy) continue; - if (p.strategy > ZSTD_HC_lazy) continue; + if (p.strategy > ZSTD_HC_lazydeep) continue; /* exclude faster if already played params */ if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(p))-1)) @@ -680,7 +680,7 @@ static void BMK_selectRandomStart( p.searchLog = FUZ_rand(&g_rand) % (ZSTD_HC_SEARCHLOG_MAX+1 - ZSTD_HC_SEARCHLOG_MIN) + ZSTD_HC_SEARCHLOG_MIN; p.windowLog = FUZ_rand(&g_rand) % (ZSTD_HC_WINDOWLOG_MAX+1 - ZSTD_HC_WINDOWLOG_MIN) + ZSTD_HC_WINDOWLOG_MIN; p.searchLength=FUZ_rand(&g_rand) % (ZSTD_HC_SEARCHLENGTH_MAX+1 - ZSTD_HC_SEARCHLENGTH_MIN) + ZSTD_HC_SEARCHLENGTH_MIN; - p.strategy = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) & 1); + p.strategy = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) % 3); playAround(f, winners, p, srcBuffer, srcSize, ctx); } else diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 5bfe25b6214..b22095983fe 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -70,7 +70,7 @@ **************************************/ #define COMPRESSOR_NAME "zstd command line interface" #ifndef ZSTD_VERSION -# define ZSTD_VERSION "v0.3.0" +# define ZSTD_VERSION "v0.3.3" #endif #define AUTHOR "Yann Collet" #define WELCOME_MESSAGE "*** %s %i-bits %s, by %s (%s) ***\n", COMPRESSOR_NAME, (int)(sizeof(void*)*8), ZSTD_VERSION, AUTHOR, __DATE__ From 050efba81b862f790670f72fdd92aa6d98539b14 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Nov 2015 09:49:30 +0100 Subject: [PATCH 02/14] level tuning --- lib/zstdhc.c | 84 +++++++++++++++++++++++++-------------------- lib/zstdhc_static.h | 59 +++++++++++++++---------------- programs/bench.c | 4 +-- 3 files changed, 79 insertions(+), 68 deletions(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index e6de28d4dbc..693c713b2a0 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -184,7 +184,7 @@ static size_t ZSTD_HC_hashPtr(const void* p, U32 h, U32 mls) } } -#define NEXT_IN_CHAIN(d) chainTable[(d) & chainMask] /* flexible, CHAINSIZE dependent */ +#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask] /* ************************************* @@ -204,7 +204,7 @@ static U32 ZSTD_HC_insertAndFindFirstIndex (ZSTD_HC_CCtx* zc, const BYTE* ip, U while(idx < target) { size_t h = ZSTD_HC_hashPtr(base+idx, hashLog, mls); - NEXT_IN_CHAIN(idx) = hashTable[h]; + NEXT_IN_CHAIN(idx, chainMask) = hashTable[h]; hashTable[h] = idx; idx++; } @@ -217,8 +217,8 @@ static U32 ZSTD_HC_insertAndFindFirstIndex (ZSTD_HC_CCtx* zc, const BYTE* ip, U FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */ size_t ZSTD_HC_insertAndFindBestMatch ( ZSTD_HC_CCtx* zc, /* Index table will be updated */ - const BYTE* ip, const BYTE* const iLimit, - const BYTE** matchpos, + const BYTE* const ip, const BYTE* const iLimit, + size_t* offsetPtr, const U32 maxNbAttempts, const U32 matchLengthSearch) { U32* const chainTable = zc->chainTable; @@ -237,17 +237,22 @@ size_t ZSTD_HC_insertAndFindBestMatch ( /* HC4 match finder */ matchIndex = ZSTD_HC_insertAndFindFirstIndex (zc, ip, matchLengthSearch); - while ((matchIndex>=lowLimit) && (nbAttempts)) + while ((matchIndex>lowLimit) && (nbAttempts)) { nbAttempts--; if (matchIndex >= dictLimit) { match = base + matchIndex; - if (*(match+ml) == *(ip+ml) - && (MEM_read32(match) == MEM_read32(ip))) + if ( (match[ml] == ip[ml]) + && (MEM_read32(match) == MEM_read32(ip)) ) /* ensures minimum match of 4 */ { const size_t mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH; - if (mlt > ml) { ml = mlt; *matchpos = match; if (ip+ml >= iLimit) break; } + if (mlt > ml) + //if (((int)(4*mlt) - (int)ZSTD_highbit((U32)(ip-match)+1)) > ((int)(4*ml) - (int)ZSTD_highbit((U32)((*offsetPtr)+1)))) + { + ml = mlt; *offsetPtr = ip-match; + if (ip+ml >= iLimit) break; + } } } else @@ -261,12 +266,12 @@ size_t ZSTD_HC_insertAndFindBestMatch ( mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH; if ((ip+mlt == vLimit) && (vLimit < iLimit)) mlt += ZSTD_count(ip+mlt, base+dictLimit, iLimit); - if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */ + if (mlt > ml) { ml = mlt; *offsetPtr = (ip-base) - matchIndex; } } } if (base + matchIndex <= ip - chainSize) break; - matchIndex = NEXT_IN_CHAIN(matchIndex); + matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); } return ml; @@ -276,15 +281,15 @@ size_t ZSTD_HC_insertAndFindBestMatch ( FORCE_INLINE size_t ZSTD_HC_insertAndFindBestMatch_selectMLS ( ZSTD_HC_CCtx* zc, /* Index table will be updated */ const BYTE* ip, const BYTE* const iLimit, - const BYTE** matchpos, + size_t* offsetPtr, const U32 maxNbAttempts, const U32 matchLengthSearch) { switch(matchLengthSearch) { default : - case 4 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, matchpos, maxNbAttempts, 4); - case 5 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, matchpos, maxNbAttempts, 5); - case 6 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, matchpos, maxNbAttempts, 6); + case 4 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4); + case 5 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5); + case 6 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6); } } @@ -297,7 +302,6 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; - const BYTE* match = istart; size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; const U32 maxSearches = 1 << ctx->params.searchLog; @@ -311,7 +315,7 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs while (ip <= ilimit) { size_t matchLength; - size_t offset; + size_t offset=999999; const BYTE* start; /* try to find a first match */ @@ -330,11 +334,10 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs } offset_2 = offset_1; - matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls); if (!matchLength) { ip++; continue; } /* let's try to find a better solution */ - offset = ip - match; start = ip; while (ip gain1) @@ -360,6 +363,7 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs } } + /* let's find an even better one */ if (ip gain1) matchLength = ml2, offset = 0, start = ip; } { - size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); - size_t offset2 = ip - match; + size_t offset2=999999; + size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset2, maxSearches, mls); int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ - int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 8); + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7); if (gain2 > gain1) { matchLength = ml2, offset = offset2, start = ip; @@ -383,7 +387,7 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs } } } - break; /* nothing found : store previous one */ + break; /* nothing found : store previous solution */ } /* store sequence */ @@ -418,7 +422,6 @@ size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSiz const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; - const BYTE* match = istart; size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; const U32 maxSearches = 1 << ctx->params.searchLog; @@ -432,7 +435,7 @@ size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSiz while (ip <= ilimit) { size_t matchLength; - size_t offset; + size_t offset=0; const BYTE* start; /* try to find a first match */ @@ -451,11 +454,10 @@ size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSiz } offset_2 = offset_1; - matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls); if (!matchLength) { ip++; continue; } /* let's try to find a better solution */ - offset = ip - match; start = ip; while (ip gain1) @@ -519,7 +521,6 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; - const BYTE* match = istart; size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; const U32 maxSearches = 1 << ctx->params.searchLog; @@ -562,12 +563,13 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS /* search */ { - size_t matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + size_t offset=999999; + size_t matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls); if (!matchLength) { ip++; continue; } /* store sequence */ { size_t litLength = ip-anchor; - offset_1 = ip-match; + offset_1 = offset; ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset_1, matchLength-MINMATCH); ip += matchLength; anchor = ip; @@ -591,9 +593,17 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) { - if (ctx->params.strategy == ZSTD_HC_greedy) - return ZSTD_HC_compressBlock_greedy(ctx, dst, maxDstSize, src, srcSize); - return ZSTD_HC_compressBlock_lazy(ctx, dst, maxDstSize, src, srcSize); + switch(ctx->params.strategy) + { + case ZSTD_HC_greedy: + return ZSTD_HC_compressBlock_greedy(ctx, dst, maxDstSize, src, srcSize); + case ZSTD_HC_lazy: + return ZSTD_HC_compressBlock_lazy(ctx, dst, maxDstSize, src, srcSize); + case ZSTD_HC_lazydeep: + return ZSTD_HC_compressBlock_lazydeep(ctx, dst, maxDstSize, src, srcSize); + default : + return ERROR(GENERIC); /* unknown block compressor */ + } } diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index 40d0b60c8a9..db185b400a5 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -53,7 +53,7 @@ typedef struct U32 hashLog; /* dispatch table : larger == more memory, faster*/ U32 searchLog; /* nb of searches : larger == more compression, slower*/ U32 searchLength; /* size of matches : larger == faster decompression */ - ZSTD_HC_strategy strategy; /* greedy, lazy (stronger, slower) */ + ZSTD_HC_strategy strategy; /* greedy, lazy, lazydeep */ } ZSTD_HC_parameters; /* parameters boundaries */ @@ -73,7 +73,7 @@ typedef struct * Advanced function ***************************************/ /** ZSTD_HC_compress_advanced -* Same as ZSTD_HC_compressCCtx(), but can fine-tune each compression parameter */ +* Same as ZSTD_HC_compressCCtx(), with fine-tune control of each compression parameter */ size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, @@ -94,35 +94,36 @@ size_t ZSTD_HC_compressEnd(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize); #define ZSTD_HC_MAX_CLEVEL 26 static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] = { /* W, C, H, S, L, strat */ - { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 0 - never used */ - { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 1 - in fact redirected towards zstd fast */ - { 18, 12, 15, 2, 4, ZSTD_HC_greedy }, /* level 2 */ - { 19, 13, 17, 3, 5, ZSTD_HC_greedy }, /* level 3 */ - { 20, 18, 19, 2, 5, ZSTD_HC_greedy }, /* level 4 */ - { 20, 19, 19, 3, 5, ZSTD_HC_greedy }, /* level 5 */ - { 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ - { 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ - { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ - { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ - { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ - { 21, 21, 20, 5, 5, ZSTD_HC_lazy }, /* level 11 */ - { 22, 20, 22, 6, 5, ZSTD_HC_lazy }, /* level 12 */ - { 22, 21, 22, 6, 5, ZSTD_HC_lazy }, /* level 13 */ - { 23, 21, 22, 6, 5, ZSTD_HC_lazy }, /* level 14 */ - { 23, 21, 23, 7, 5, ZSTD_HC_lazy }, /* level 15 */ - { 23, 22, 22, 6, 5, ZSTD_HC_lazy }, /* level 16 */ - { 23, 22, 22, 7, 5, ZSTD_HC_lazy }, /* level 17 */ - { 23, 23, 22, 7, 5, ZSTD_HC_lazy }, /* level 18 */ - { 23, 22, 23, 8, 5, ZSTD_HC_lazy }, /* level 19 */ - { 23, 23, 23, 8, 5, ZSTD_HC_lazy }, /* level 20 */ - { 23, 23, 23, 8, 5, ZSTD_HC_lazy }, /* level 21 */ - { 24, 24, 24, 8, 5, ZSTD_HC_lazy }, /* level 22 */ - { 24, 23, 23, 9, 5, ZSTD_HC_lazy }, /* level 23 */ - { 24, 24, 24, 9, 5, ZSTD_HC_lazy }, /* level 24 */ - { 24, 24, 24, 9, 5, ZSTD_HC_lazy }, /* level 25 */ - { 24, 24, 24, 10, 5, ZSTD_HC_lazy }, /* level 26 */ /* ZSTD_HC_MAX_CLEVEL */ + { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 0 - never used */ + { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 1 - in fact redirected towards zstd fast */ + { 18, 12, 15, 2, 4, ZSTD_HC_greedy }, /* level 2 */ + { 19, 13, 17, 3, 5, ZSTD_HC_greedy }, /* level 3 */ + { 20, 18, 19, 2, 5, ZSTD_HC_greedy }, /* level 4 */ + { 20, 18, 19, 2, 5, ZSTD_HC_lazy }, /* level 5 */ + { 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ + { 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ + { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ + { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ + { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ + { 21, 20, 20, 5, 5, ZSTD_HC_lazydeep }, /* level 11 */ + { 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ + { 22, 20, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 13 */ + { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ + { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ + { 22, 21, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 16 */ + { 23, 21, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 17 */ + { 23, 22, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 18 */ + { 23, 22, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 19 */ + { 23, 22, 23, 8, 5, ZSTD_HC_lazydeep }, /* level 20 */ + { 23, 22, 23, 8, 5, ZSTD_HC_lazydeep }, /* level 21 */ + { 23, 23, 24, 8, 5, ZSTD_HC_lazydeep }, /* level 22 */ + { 24, 24, 24, 8, 5, ZSTD_HC_lazydeep }, /* level 23 */ + { 23, 23, 23, 9, 5, ZSTD_HC_lazydeep }, /* level 24 */ + { 24, 23, 23, 9, 5, ZSTD_HC_lazydeep }, /* level 25 */ + { 24, 24, 24, 9, 5, ZSTD_HC_lazydeep }, /* level 26 */ }; + #if defined (__cplusplus) } #endif diff --git a/programs/bench.c b/programs/bench.c index 85c3700b403..8dab7126592 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -83,7 +83,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -#define MAX_MEM (2 GB - 64 MB) +static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : 8ULL GB; #define DEFAULT_CHUNKSIZE (4 MB) static U32 g_compressibilityDefault = 50; @@ -401,7 +401,7 @@ static size_t BMK_findMaxMem(U64 requiredMem) requiredMem = (((requiredMem >> 26) + 1) << 26); requiredMem += 2 * step; - if (requiredMem > MAX_MEM) requiredMem = MAX_MEM; + if (requiredMem > maxMemory) requiredMem = maxMemory; while (!testmem) { From 588d1e5fa035a5aad0f3ebf2e594ba3c6798e98e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Nov 2015 10:48:42 +0100 Subject: [PATCH 03/14] Fixed asan issue reported by Maciej Adamczyk --- lib/zstd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/zstd.c b/lib/zstd.c index c7999445648..c7dcc262a38 100644 --- a/lib/zstd.c +++ b/lib/zstd.c @@ -570,7 +570,7 @@ static size_t ZSTD_compressBlock(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, c ZSTD_resetSeqStore(seqStorePtr); /* Main Search Loop */ - while (ip <= ilimit) + while (ip < ilimit) /* < instead of <=, because unconditionnal ZSTD_addPtr(ip+1) */ { const BYTE* match = ZSTD_updateMatch(HashTable, ip, base); @@ -591,7 +591,8 @@ static size_t ZSTD_compressBlock(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, c ZSTD_addPtr(HashTable, ip+1, base); ip += matchLength + MINMATCH; anchor = ip; - if (ip <= ilimit) ZSTD_addPtr(HashTable, ip-2, base); + if (ip < ilimit) /* same test as loop, for speed */ + ZSTD_addPtr(HashTable, ip-2, base); } } From cdc2b2f7583c05c3c8dd2430dcba44398109df52 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Nov 2015 10:52:14 +0100 Subject: [PATCH 04/14] fixed clang warning --- programs/bench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/bench.c b/programs/bench.c index 8dab7126592..8ab66d92157 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -83,7 +83,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : 8ULL GB; +static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(8ULL GB); #define DEFAULT_CHUNKSIZE (4 MB) static U32 g_compressibilityDefault = 50; From 293d0cc2614f253d46cce5259638e4309290276e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Nov 2015 13:10:25 +0100 Subject: [PATCH 05/14] fixed Visual warning --- programs/bench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/bench.c b/programs/bench.c index 8ab66d92157..1892ddd60e5 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -83,7 +83,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(8ULL GB); +static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(1ULL << (sizeof(size_t)*8-31)); #define DEFAULT_CHUNKSIZE (4 MB) static U32 g_compressibilityDefault = 50; From 96b9f0ba4d22734c4e5b5ee40e807905ab993792 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 03:52:54 +0100 Subject: [PATCH 06/14] btlazy2 --- lib/zstdhc.c | 315 +++++++++++++++++++++++++++++++++++++++++- lib/zstdhc_static.h | 8 +- programs/bench.c | 2 +- programs/paramgrill.c | 8 +- 4 files changed, 319 insertions(+), 14 deletions(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index 693c713b2a0..d053b2138f8 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -173,14 +173,14 @@ static const U64 prime6bytes = 227718039650203ULL; static size_t ZSTD_HC_hash6(U64 u, U32 h) { return (size_t)((u * prime6bytes) << (64-48) >> (64-h)) ; } static size_t ZSTD_HC_hash6Ptr(const void* p, U32 h) { return ZSTD_HC_hash6(MEM_read64(p), h); } -static size_t ZSTD_HC_hashPtr(const void* p, U32 h, U32 mls) +static size_t ZSTD_HC_hashPtr(const void* p, U32 hBits, U32 mls) { switch(mls) { default: - case 4: return ZSTD_HC_hash4Ptr(p,h); - case 5: return ZSTD_HC_hash5Ptr(p,h); - case 6: return ZSTD_HC_hash6Ptr(p,h); + case 4: return ZSTD_HC_hash4Ptr(p, hBits); + case 5: return ZSTD_HC_hash5Ptr(p, hBits); + case 6: return ZSTD_HC_hash6Ptr(p, hBits); } } @@ -188,8 +188,308 @@ static size_t ZSTD_HC_hashPtr(const void* p, U32 h, U32 mls) /* ************************************* -* HC Compression +* Binary Tree search ***************************************/ +#define BT_SHORTCUT 256 + +/** ZSTD_HC_insertBt1 : add one ptr to tree + @ip : assumed <= iend-8 */ +static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares) +{ + U32* const hashTable = zc->hashTable; + const U32 hashLog = zc->params.hashLog; + const size_t h = ZSTD_HC_hashPtr(ip, hashLog, mls); + U32* const bt = zc->chainTable; + const U32 btLog = zc->params.chainLog - 1; + const U32 btMask= (1 << btLog) - 1; + U32 matchIndex = hashTable[h]; + size_t commonLengthSmaller=0, commonLengthLarger=0; + const BYTE* const base = zc->base; + const U32 current = (U32)(ip-base); + const U32 btLow = btMask >= current ? 0 : current - btMask; + U32* smallerPtr = bt + 2*(current&btMask); + U32* largerPtr = bt + 2*(current&btMask) + 1; + U32 dummy32; /* to be nullified at the end */ + const U32 windowSize = 1 << zc->params.windowLog; + const U32 windowLow = windowSize >= current ? 0 : current - windowSize; + + hashTable[h] = (U32)(ip-base); /* Update Hash Table */ + + while (nbCompares-- && (matchIndex > windowLow)) + { + U32* nextPtr = bt + 2*(matchIndex & btMask); + const BYTE* match = base + matchIndex; + size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ + + matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); + + if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ + break; /* just drop , to guarantee consistency (miss a bit of compression; if someone knows better, please tell) */ + + if (match[matchLength] < ip[matchLength]) + { + /* match is smaller than current */ + *smallerPtr = matchIndex; /* update smaller idx */ + commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ + matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ + } + else + { + /* match is larger than current */ + *largerPtr = matchIndex; + commonLengthLarger = matchLength; + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + largerPtr = nextPtr; + matchIndex = nextPtr[0]; + } + } + + *smallerPtr = *largerPtr = 0; +} + + +FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */ +size_t ZSTD_HC_insertBtAndFindBestMatch ( + ZSTD_HC_CCtx* zc, + const BYTE* const ip, const BYTE* const iend, + size_t* offsetPtr, + U32 nbCompares, const U32 mls) +{ + U32* const hashTable = zc->hashTable; + const U32 hashLog = zc->params.hashLog; + const size_t h = ZSTD_HC_hashPtr(ip, hashLog, mls); + U32* const bt = zc->chainTable; + const U32 btLog = zc->params.chainLog - 1; + const U32 btMask= (1 << btLog) - 1; + U32 matchIndex = hashTable[h]; + size_t commonLengthSmaller=0, commonLengthLarger=0; + const BYTE* const base = zc->base; + const U32 current = (U32)(ip-base); + const U32 btLow = btMask >= current ? 0 : current - btMask; + const U32 windowSize = 1 << zc->params.windowLog; + const U32 windowLow = windowSize >= current ? 0 : current - windowSize; + U32* smallerPtr = bt + 2*(current&btMask); + U32* largerPtr = bt + 2*(current&btMask) + 1; + U32 bestLength = 0; + U32 dummy32; /* to be nullified at the end */ + + hashTable[h] = (U32)(ip-base); /* Update Hash Table */ + + while (nbCompares-- && (matchIndex > windowLow)) + { + U32* nextPtr = bt + 2*(matchIndex & btMask); + const BYTE* match = base + matchIndex; + size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ + + matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); + + if (matchLength > bestLength) + { + bestLength = (U32)matchLength; + *offsetPtr = current - matchIndex; + if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ + break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ + } + + if (match[matchLength] < ip[matchLength]) + { + /* match is smaller than current */ + *smallerPtr = matchIndex; /* update smaller idx */ + commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ + matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ + } + else + { + /* match is larger than current */ + *largerPtr = matchIndex; + commonLengthLarger = matchLength; + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + largerPtr = nextPtr; + matchIndex = nextPtr[0]; + } + } + + *smallerPtr = *largerPtr = 0; + + zc->nextToUpdate = current+1; /* current has been inserted */ + if (bestLength < MINMATCH) return 0; + return bestLength; +} + + +static void ZSTD_HC_updateTree(ZSTD_HC_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls) +{ + const BYTE* const base = zc->base; + const U32 target = (U32)(ip - base); + U32 idx = zc->nextToUpdate; + //size_t dummy; + + for( ; idx < target ; idx++) + ZSTD_HC_insertBt1(zc, base+idx, mls, iend, nbCompares); + //ZSTD_HC_insertBtAndFindBestMatch(zc, base+idx, iend, &dummy, nbCompares, mls); + + zc->nextToUpdate = target; +} + + +/** Tree updater, providing best match */ +FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */ +size_t ZSTD_HC_BtFindBestMatch ( + ZSTD_HC_CCtx* zc, + const BYTE* const ip, const BYTE* const iLimit, + size_t* offsetPtr, + const U32 maxNbAttempts, const U32 mls) +{ + ZSTD_HC_updateTree(zc, ip, iLimit, maxNbAttempts, mls); + return ZSTD_HC_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls); +} + + +FORCE_INLINE size_t ZSTD_HC_BtFindBestMatch_selectMLS ( + ZSTD_HC_CCtx* zc, /* Index table will be updated */ + const BYTE* ip, const BYTE* const iLimit, + size_t* offsetPtr, + const U32 maxNbAttempts, const U32 matchLengthSearch) +{ + switch(matchLengthSearch) + { + default : + case 4 : return ZSTD_HC_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4); + case 5 : return ZSTD_HC_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5); + case 6 : return ZSTD_HC_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6); + } +} + + +size_t ZSTD_HC_compressBlock_btLazy2(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + seqStore_t* seqStorePtr = &(ctx->seqStore); + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip = istart; + const BYTE* anchor = istart; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - 8; + + size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; + const U32 maxSearches = 1 << ctx->params.searchLog; + const U32 mls = ctx->params.searchLength; + + /* init */ + ZSTD_resetSeqStore(seqStorePtr); + if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE; + + /* Match Loop */ + while (ip <= ilimit) + { + size_t matchLength; + size_t offset=999999; + const BYTE* start; + + /* try to find a first match */ + if (MEM_read32(ip) == MEM_read32(ip - offset_2)) + { + /* repcode : we take it*/ + size_t offtmp = offset_2; + size_t litLength = ip - anchor; + matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend); + offset_2 = offset_1; + offset_1 = offtmp; + ZSTD_storeSeq(seqStorePtr, litLength, anchor, 0, matchLength); + ip += matchLength+MINMATCH; + anchor = ip; + continue; + } + + offset_2 = offset_1; + matchLength = ZSTD_HC_BtFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls); + if (!matchLength) { ip++; continue; } + + /* let's try to find a better solution */ + start = ip; + + while (ip gain1) + matchLength = ml2, offset = 0, start = ip; + } + { + size_t offset2=999999; + size_t ml2 = ZSTD_HC_BtFindBestMatch_selectMLS(ctx, ip, iend, &offset2, maxSearches, mls); + int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4); + if (gain2 > gain1) + { + matchLength = ml2, offset = offset2, start = ip; + continue; /* search a better one */ + } + } + + /* let's find an even better one */ + if (ip gain1) + matchLength = ml2, offset = 0, start = ip; + } + { + size_t offset2=999999; + size_t ml2 = ZSTD_HC_BtFindBestMatch_selectMLS(ctx, ip, iend, &offset2, maxSearches, mls); + int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7); + if (gain2 > gain1) + { + matchLength = ml2, offset = offset2, start = ip; + continue; + } + } + } + break; /* nothing found : store previous solution */ + } + + /* store sequence */ + { + size_t litLength = start - anchor; + if (offset) offset_1 = offset; + ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH); + ip = start + matchLength; + anchor = ip; + } + + } + + /* Last Literals */ + { + size_t lastLLSize = iend - anchor; + memcpy(seqStorePtr->lit, anchor, lastLLSize); + seqStorePtr->lit += lastLLSize; + } + + /* Final compression stage */ + return ZSTD_compressSequences((BYTE*)dst, maxDstSize, + seqStorePtr, srcSize); +} + + + +/* *********************** +* Hash Chain +*************************/ + /* Update chains up to ip (excluded) */ static U32 ZSTD_HC_insertAndFindFirstIndex (ZSTD_HC_CCtx* zc, const BYTE* ip, U32 mls) { @@ -601,6 +901,8 @@ size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, co return ZSTD_HC_compressBlock_lazy(ctx, dst, maxDstSize, src, srcSize); case ZSTD_HC_lazydeep: return ZSTD_HC_compressBlock_lazydeep(ctx, dst, maxDstSize, src, srcSize); + case ZSTD_HC_btlazy2: + return ZSTD_HC_compressBlock_btLazy2(ctx, dst, maxDstSize, src, srcSize); default : return ERROR(GENERIC); /* unknown block compressor */ } @@ -630,6 +932,9 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, case ZSTD_HC_lazydeep: blockCompressor = ZSTD_HC_compressBlock_lazydeep; break; + case ZSTD_HC_btlazy2: + blockCompressor = ZSTD_HC_compressBlock_btLazy2; + break; default : return ERROR(GENERIC); /* unknown block compressor */ } diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index db185b400a5..36e0781f506 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -45,7 +45,7 @@ extern "C" { /* ************************************* * Types ***************************************/ -typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy, ZSTD_HC_lazydeep } ZSTD_HC_strategy; +typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy, ZSTD_HC_lazydeep, ZSTD_HC_btlazy2 } ZSTD_HC_strategy; typedef struct { U32 windowLog; /* largest match distance : impact decompression buffer size */ @@ -100,13 +100,13 @@ static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] { 19, 13, 17, 3, 5, ZSTD_HC_greedy }, /* level 3 */ { 20, 18, 19, 2, 5, ZSTD_HC_greedy }, /* level 4 */ { 20, 18, 19, 2, 5, ZSTD_HC_lazy }, /* level 5 */ - { 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ - { 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ + { 20, 18, 19, 2, 5, ZSTD_HC_lazydeep }, //{ 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ + { 20, 18, 19, 2, 5, ZSTD_HC_btlazy2 }, //{ 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazydeep }, /* level 11 */ - { 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ + { 21, 20, 20, 5, 5, ZSTD_HC_btlazy2 }, //{ 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ { 22, 20, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 13 */ { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ diff --git a/programs/bench.c b/programs/bench.c index 1892ddd60e5..c19d0fd97ff 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -83,7 +83,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(1ULL << (sizeof(size_t)*8-31)); +static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(1ULL << ((sizeof(size_t)*8)-31)); #define DEFAULT_CHUNKSIZE (4 MB) static U32 g_compressibilityDefault = 50; diff --git a/programs/paramgrill.c b/programs/paramgrill.c index d27a22b5f39..78f2b1959b7 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -425,7 +425,7 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, return 0; } -const char* g_stratName[] = { "ZSTD_HC_greedy ", "ZSTD_HC_lazy ", "ZSTD_HC_lazydeep" }; +const char* g_stratName[] = { "ZSTD_HC_greedy ", "ZSTD_HC_lazy ", "ZSTD_HC_lazydeep", "ZSTD_HC_btlazy2 " }; static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_HC_parameters params, size_t srcSize) { @@ -576,7 +576,7 @@ static BYTE g_alreadyTested[ZSTD_HC_WINDOWLOG_MAX+1-ZSTD_HC_WINDOWLOG_MIN] [ZSTD_HC_HASHLOG_MAX+1-ZSTD_HC_HASHLOG_MIN] [ZSTD_HC_SEARCHLOG_MAX+1-ZSTD_HC_SEARCHLOG_MIN] [ZSTD_HC_SEARCHLENGTH_MAX+1-ZSTD_HC_SEARCHLENGTH_MIN] - [3 /* strategy */ ] = {}; /* init to zero */ + [4 /* strategy */ ] = {}; /* init to zero */ #define NB_TESTS_PLAYED(p) \ g_alreadyTested[p.windowLog-ZSTD_HC_WINDOWLOG_MIN] \ @@ -647,7 +647,7 @@ static void playAround(FILE* f, winnerInfo_t* winners, if (p.searchLength > ZSTD_HC_SEARCHLENGTH_MAX) continue; if (p.searchLength < ZSTD_HC_SEARCHLENGTH_MIN) continue; if (p.strategy < ZSTD_HC_greedy) continue; - if (p.strategy > ZSTD_HC_lazydeep) continue; + if (p.strategy > ZSTD_HC_btlazy2) continue; /* exclude faster if already played params */ if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(p))-1)) @@ -680,7 +680,7 @@ static void BMK_selectRandomStart( p.searchLog = FUZ_rand(&g_rand) % (ZSTD_HC_SEARCHLOG_MAX+1 - ZSTD_HC_SEARCHLOG_MIN) + ZSTD_HC_SEARCHLOG_MIN; p.windowLog = FUZ_rand(&g_rand) % (ZSTD_HC_WINDOWLOG_MAX+1 - ZSTD_HC_WINDOWLOG_MIN) + ZSTD_HC_WINDOWLOG_MIN; p.searchLength=FUZ_rand(&g_rand) % (ZSTD_HC_SEARCHLENGTH_MAX+1 - ZSTD_HC_SEARCHLENGTH_MIN) + ZSTD_HC_SEARCHLENGTH_MIN; - p.strategy = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) % 3); + p.strategy = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) % 4); playAround(f, winners, p, srcBuffer, srcSize, ctx); } else From 59d7063fbc86b8d8a74aa92f9a54d70cead12685 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 12:05:27 +0100 Subject: [PATCH 07/14] fix and level tuning --- lib/zstd_internal.h | 2 +- lib/zstdhc.c | 140 +++++++++++++++++++++++------------------- lib/zstdhc_static.h | 40 ++++++------ programs/paramgrill.c | 29 ++++----- 4 files changed, 111 insertions(+), 100 deletions(-) diff --git a/lib/zstd_internal.h b/lib/zstd_internal.h index 8077259238a..207fd84bf35 100644 --- a/lib/zstd_internal.h +++ b/lib/zstd_internal.h @@ -154,7 +154,7 @@ MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pI return (size_t)(pIn - pStart); } - if (MEM_32bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; } + if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; } if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; } if ((pIn 0 */ +void ZSTD_HC_validateParams(ZSTD_HC_parameters* params, size_t srcSize) +{ + const U32 chainplus = (params->strategy == ZSTD_HC_btlazy2); + + /* validate params */ + if (params->windowLog > ZSTD_HC_WINDOWLOG_MAX) params->windowLog = ZSTD_HC_WINDOWLOG_MAX; + if (params->windowLog < ZSTD_HC_WINDOWLOG_MIN) params->windowLog = ZSTD_HC_WINDOWLOG_MIN; + + /* correct params, to use less memory */ + if (srcSize > 0) + { + U32 srcLog = ZSTD_highbit((U32)srcSize-1) + 1; + if (params->windowLog > srcLog) params->windowLog = srcLog; + } + + if (params->chainLog > params->windowLog + chainplus) params->chainLog = params->windowLog+chainplus; /* <= ZSTD_HC_CHAINLOG_MAX */ + if (params->chainLog < ZSTD_HC_CHAINLOG_MIN) params->chainLog = ZSTD_HC_CHAINLOG_MIN; + if (params->hashLog > ZSTD_HC_HASHLOG_MAX) params->hashLog = ZSTD_HC_HASHLOG_MAX; + if (params->hashLog < ZSTD_HC_HASHLOG_MIN) params->hashLog = ZSTD_HC_HASHLOG_MIN; + if (params->searchLog > ZSTD_HC_SEARCHLOG_MAX) params->searchLog = ZSTD_HC_SEARCHLOG_MAX; + if (params->searchLog < ZSTD_HC_SEARCHLOG_MIN) params->searchLog = ZSTD_HC_SEARCHLOG_MIN; + if (params->searchLength> ZSTD_HC_SEARCHLENGTH_MAX) params->searchLength = ZSTD_HC_SEARCHLENGTH_MAX; + if (params->searchLength< ZSTD_HC_SEARCHLENGTH_MIN) params->searchLength = ZSTD_HC_SEARCHLENGTH_MIN; + if ((U32)params->strategy>(U32)ZSTD_HC_btlazy2) params->strategy = ZSTD_HC_btlazy2; + if ((int)params->strategy<(int)ZSTD_HC_greedy) params->strategy = ZSTD_HC_greedy; +} + + static size_t ZSTD_HC_resetCCtx_advanced (ZSTD_HC_CCtx* zc, ZSTD_HC_parameters params) { - /* validate params */ - if (params.windowLog > ZSTD_HC_WINDOWLOG_MAX) params.windowLog = ZSTD_HC_WINDOWLOG_MAX; - if (params.windowLog < ZSTD_HC_WINDOWLOG_MIN) params.windowLog = ZSTD_HC_WINDOWLOG_MIN; - if (params.chainLog > params.windowLog) params.chainLog = params.windowLog; /* <= ZSTD_HC_CHAINLOG_MAX */ - if (params.chainLog < ZSTD_HC_CHAINLOG_MIN) params.chainLog = ZSTD_HC_CHAINLOG_MIN; - if (params.hashLog > ZSTD_HC_HASHLOG_MAX) params.hashLog = ZSTD_HC_HASHLOG_MAX; - if (params.hashLog < ZSTD_HC_HASHLOG_MIN) params.hashLog = ZSTD_HC_HASHLOG_MIN; - if (params.searchLog > ZSTD_HC_SEARCHLOG_MAX) params.searchLog = ZSTD_HC_SEARCHLOG_MAX; - if (params.searchLog < ZSTD_HC_SEARCHLOG_MIN) params.searchLog = ZSTD_HC_SEARCHLOG_MIN; - if (params.searchLength> ZSTD_HC_SEARCHLENGTH_MAX) params.searchLength = ZSTD_HC_SEARCHLENGTH_MAX; - if (params.searchLength< ZSTD_HC_SEARCHLENGTH_MIN) params.searchLength = ZSTD_HC_SEARCHLENGTH_MIN; + ZSTD_HC_validateParams(¶ms, 0); /* reserve table memory */ { @@ -190,8 +212,6 @@ static size_t ZSTD_HC_hashPtr(const void* p, U32 hBits, U32 mls) /* ************************************* * Binary Tree search ***************************************/ -#define BT_SHORTCUT 256 - /** ZSTD_HC_insertBt1 : add one ptr to tree @ip : assumed <= iend-8 */ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares) @@ -209,7 +229,7 @@ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32 const U32 btLow = btMask >= current ? 0 : current - btMask; U32* smallerPtr = bt + 2*(current&btMask); U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 dummy32; /* to be nullified at the end */ + U32 dummy32; /* to be nullified at the end */ const U32 windowSize = 1 << zc->params.windowLog; const U32 windowLow = windowSize >= current ? 0 : current - windowSize; @@ -223,30 +243,30 @@ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32 matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); - if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ - break; /* just drop , to guarantee consistency (miss a bit of compression; if someone knows better, please tell) */ + if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ + break; /* just drop , to guarantee consistency (miss a bit of compression; if someone knows better, please tell) */ if (match[matchLength] < ip[matchLength]) - { + { /* match is smaller than current */ *smallerPtr = matchIndex; /* update smaller idx */ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } + } else - { + { /* match is larger than current */ *largerPtr = matchIndex; commonLengthLarger = matchLength; - if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ largerPtr = nextPtr; matchIndex = nextPtr[0]; - } + } } - *smallerPtr = *largerPtr = 0; + *smallerPtr = *largerPtr = 0; } @@ -273,9 +293,9 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( U32* smallerPtr = bt + 2*(current&btMask); U32* largerPtr = bt + 2*(current&btMask) + 1; U32 bestLength = 0; - U32 dummy32; /* to be nullified at the end */ + U32 dummy32; /* to be nullified at the end */ - hashTable[h] = (U32)(ip-base); /* Update Hash Table */ + hashTable[h] = (U32)(ip-base); /* Update Hash Table */ while (nbCompares-- && (matchIndex > windowLow)) { @@ -289,34 +309,34 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( { bestLength = (U32)matchLength; *offsetPtr = current - matchIndex; - if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ - break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ + if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ + break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ } if (match[matchLength] < ip[matchLength]) - { + { /* match is smaller than current */ *smallerPtr = matchIndex; /* update smaller idx */ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ - smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } + } else - { + { /* match is larger than current */ *largerPtr = matchIndex; commonLengthLarger = matchLength; - if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ largerPtr = nextPtr; matchIndex = nextPtr[0]; - } + } } - *smallerPtr = *largerPtr = 0; + *smallerPtr = *largerPtr = 0; zc->nextToUpdate = current+1; /* current has been inserted */ - if (bestLength < MINMATCH) return 0; + if (bestLength < MINMATCH) return 0; return bestLength; } @@ -326,7 +346,7 @@ static void ZSTD_HC_updateTree(ZSTD_HC_CCtx* zc, const BYTE* const ip, const BYT const BYTE* const base = zc->base; const U32 target = (U32)(ip - base); U32 idx = zc->nextToUpdate; - //size_t dummy; + //size_t dummy; for( ; idx < target ; idx++) ZSTD_HC_insertBt1(zc, base+idx, mls, iend, nbCompares); @@ -510,7 +530,7 @@ static U32 ZSTD_HC_insertAndFindFirstIndex (ZSTD_HC_CCtx* zc, const BYTE* ip, U } zc->nextToUpdate = target; - return hashTable[ZSTD_HC_hashPtr(ip, hashLog, mls)]; + return hashTable[ZSTD_HC_hashPtr(ip, hashLog, mls)]; } @@ -891,24 +911,33 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS } -size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) +typedef size_t (*ZSTD_HC_blockCompressor) (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); + + +static ZSTD_HC_blockCompressor ZSTD_HC_selectBlockCompressor(ZSTD_HC_strategy strat) { - switch(ctx->params.strategy) + switch(strat) { + default : case ZSTD_HC_greedy: - return ZSTD_HC_compressBlock_greedy(ctx, dst, maxDstSize, src, srcSize); + return ZSTD_HC_compressBlock_greedy; case ZSTD_HC_lazy: - return ZSTD_HC_compressBlock_lazy(ctx, dst, maxDstSize, src, srcSize); + return ZSTD_HC_compressBlock_lazy; case ZSTD_HC_lazydeep: - return ZSTD_HC_compressBlock_lazydeep(ctx, dst, maxDstSize, src, srcSize); + return ZSTD_HC_compressBlock_lazydeep; case ZSTD_HC_btlazy2: - return ZSTD_HC_compressBlock_btLazy2(ctx, dst, maxDstSize, src, srcSize); - default : - return ERROR(GENERIC); /* unknown block compressor */ + return ZSTD_HC_compressBlock_btLazy2; } } +size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + ZSTD_HC_blockCompressor blockCompressor = ZSTD_HC_selectBlockCompressor(ctx->params.strategy); + return blockCompressor(ctx, dst, maxDstSize, src, srcSize); +} + + static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, void* dst, size_t maxDstSize, const void* src, size_t srcSize) @@ -919,25 +948,8 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; BYTE* const oend = op + maxDstSize; - size_t (*blockCompressor) (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); + const ZSTD_HC_blockCompressor blockCompressor = ZSTD_HC_selectBlockCompressor(ctxPtr->params.strategy); - switch(ctxPtr->params.strategy) - { - case ZSTD_HC_greedy: - blockCompressor = ZSTD_HC_compressBlock_greedy; - break; - case ZSTD_HC_lazy: - blockCompressor = ZSTD_HC_compressBlock_lazy; - break; - case ZSTD_HC_lazydeep: - blockCompressor = ZSTD_HC_compressBlock_lazydeep; - break; - case ZSTD_HC_btlazy2: - blockCompressor = ZSTD_HC_compressBlock_btLazy2; - break; - default : - return ERROR(GENERIC); /* unknown block compressor */ - } while (remaining > blockSize) { diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index 36e0781f506..06174fcdeca 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -59,7 +59,7 @@ typedef struct /* parameters boundaries */ #define ZSTD_HC_WINDOWLOG_MAX 26 #define ZSTD_HC_WINDOWLOG_MIN 18 -#define ZSTD_HC_CHAINLOG_MAX ZSTD_HC_WINDOWLOG_MAX +#define ZSTD_HC_CHAINLOG_MAX (ZSTD_HC_WINDOWLOG_MAX+1) #define ZSTD_HC_CHAINLOG_MIN 4 #define ZSTD_HC_HASHLOG_MAX 28 #define ZSTD_HC_HASHLOG_MIN 4 @@ -79,6 +79,11 @@ size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx, const void* src, size_t srcSize, ZSTD_HC_parameters params); +/** ZSTD_HC_validateParams + correct params value to remain within authorized range + optimize for srcSize if srcSize > 0 */ +void ZSTD_HC_validateParams(ZSTD_HC_parameters* params, size_t srcSize); + /* ************************************* * Streaming functions @@ -97,33 +102,32 @@ static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 0 - never used */ { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 1 - in fact redirected towards zstd fast */ { 18, 12, 15, 2, 4, ZSTD_HC_greedy }, /* level 2 */ - { 19, 13, 17, 3, 5, ZSTD_HC_greedy }, /* level 3 */ - { 20, 18, 19, 2, 5, ZSTD_HC_greedy }, /* level 4 */ + { 19, 14, 18, 2, 5, ZSTD_HC_greedy }, /* level 3 */ + { 20, 17, 19, 3, 5, ZSTD_HC_greedy }, /* level 4 */ { 20, 18, 19, 2, 5, ZSTD_HC_lazy }, /* level 5 */ - { 20, 18, 19, 2, 5, ZSTD_HC_lazydeep }, //{ 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ - { 20, 18, 19, 2, 5, ZSTD_HC_btlazy2 }, //{ 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ + { 21, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ + { 21, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazydeep }, /* level 11 */ - { 21, 20, 20, 5, 5, ZSTD_HC_btlazy2 }, //{ 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ + { 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ { 22, 20, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 13 */ { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ - { 22, 21, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 16 */ - { 23, 21, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 17 */ - { 23, 22, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 18 */ - { 23, 22, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 19 */ - { 23, 22, 23, 8, 5, ZSTD_HC_lazydeep }, /* level 20 */ - { 23, 22, 23, 8, 5, ZSTD_HC_lazydeep }, /* level 21 */ - { 23, 23, 24, 8, 5, ZSTD_HC_lazydeep }, /* level 22 */ - { 24, 24, 24, 8, 5, ZSTD_HC_lazydeep }, /* level 23 */ - { 23, 23, 23, 9, 5, ZSTD_HC_lazydeep }, /* level 24 */ - { 24, 23, 23, 9, 5, ZSTD_HC_lazydeep }, /* level 25 */ - { 24, 24, 24, 9, 5, ZSTD_HC_lazydeep }, /* level 26 */ + { 22, 21, 22, 5, 5, ZSTD_HC_btlazy2 }, /* level 16 */ + { 22, 22, 23, 5, 5, ZSTD_HC_btlazy2 }, /* level 17 */ + { 22, 22, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 18 */ + { 24, 24, 22, 7, 5, ZSTD_HC_btlazy2 }, /* level 19 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 21 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 22 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 23 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 24 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 25 */ + { 25, 25, 24, 9, 5, ZSTD_HC_btlazy2 }, /* level 26 */ }; - #if defined (__cplusplus) } #endif diff --git a/programs/paramgrill.c b/programs/paramgrill.c index 78f2b1959b7..f7cfef98e52 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -348,7 +348,7 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, if (totalTime > g_maxParamTime) break; /* Compression */ - DISPLAY("%1u-%s : %9u ->\r", loopNb, name, (U32)srcSize); + DISPLAY("\r%1u-%s : %9u ->", loopNb, name, (U32)srcSize); memset(compressedBuffer, 0xE5, maxCompressedSize); nbLoops = 0; @@ -371,8 +371,9 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, cSize += blockTable[blockNb].cSize; if ((double)milliTime < fastestC*nbLoops) fastestC = (double)milliTime / nbLoops; ratio = (double)srcSize / (double)cSize; + DISPLAY("\r"); DISPLAY("%1u-%s : %9u ->", loopNb, name, (U32)srcSize); - DISPLAY(" %9u (%4.3f),%7.1f MB/s\r", (U32)cSize, ratio, (double)srcSize / fastestC / 1000.); + DISPLAY(" %9u (%4.3f),%7.1f MB/s", (U32)cSize, ratio, (double)srcSize / fastestC / 1000.); resultPtr->cSize = cSize; resultPtr->cSpeed = (U32)((double)srcSize / fastestC); @@ -393,9 +394,10 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, milliTime = BMK_GetMilliSpan(milliTime); if ((double)milliTime < fastestD*nbLoops) fastestD = (double)milliTime / nbLoops; + DISPLAY("\r"); DISPLAY("%1u-%s : %9u -> ", loopNb, name, (U32)srcSize); DISPLAY("%9u (%4.3f),%7.1f MB/s, ", (U32)cSize, ratio, (double)srcSize / fastestC / 1000.); - DISPLAY("%7.1f MB/s\r", (double)srcSize / fastestD / 1000.); + DISPLAY("%7.1f MB/s", (double)srcSize / fastestD / 1000.); resultPtr->dSpeed = (U32)((double)srcSize / fastestD); /* CRC Checking */ @@ -420,11 +422,13 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, } /* End cleaning */ + DISPLAY("\r"); free(compressedBuffer); free(resultBuffer); return 0; } + const char* g_stratName[] = { "ZSTD_HC_greedy ", "ZSTD_HC_lazy ", "ZSTD_HC_lazydeep", "ZSTD_HC_btlazy2 " }; static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_HC_parameters params, size_t srcSize) @@ -592,7 +596,6 @@ static void playAround(FILE* f, winnerInfo_t* winners, const void* srcBuffer, size_t srcSize, ZSTD_HC_CCtx* ctx) { - const U32 srcLog = BMK_highbit((U32)( (g_blockSize ? g_blockSize : srcSize) -1))+1; int nbVariations = 0; const int startTime = BMK_GetMilliStart(); @@ -635,19 +638,11 @@ static void playAround(FILE* f, winnerInfo_t* winners, } /* validate new conf */ - if (p.windowLog > srcLog) continue; - if (p.windowLog > ZSTD_HC_WINDOWLOG_MAX) continue; - if (p.windowLog < MAX(ZSTD_HC_WINDOWLOG_MIN, p.chainLog)) continue; - if (p.chainLog > p.windowLog) continue; - if (p.chainLog < ZSTD_HC_CHAINLOG_MIN) continue; - if (p.hashLog > ZSTD_HC_HASHLOG_MAX) continue; - if (p.hashLog < ZSTD_HC_HASHLOG_MIN) continue; - if (p.searchLog > p.chainLog) continue; - if (p.searchLog < ZSTD_HC_SEARCHLOG_MIN) continue; - if (p.searchLength > ZSTD_HC_SEARCHLENGTH_MAX) continue; - if (p.searchLength < ZSTD_HC_SEARCHLENGTH_MIN) continue; - if (p.strategy < ZSTD_HC_greedy) continue; - if (p.strategy > ZSTD_HC_btlazy2) continue; + { + ZSTD_HC_parameters saved = p; + ZSTD_HC_validateParams(&p, g_blockSize ? g_blockSize : srcSize); + if (memcmp(&p, &saved, sizeof(p))) continue; /* p was invalid */ + } /* exclude faster if already played params */ if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(p))-1)) From b241e9deb7d207f87658f79856b2717a19c25162 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 13:57:24 +0100 Subject: [PATCH 08/14] small compression improvement --- lib/zstdhc.c | 6 +++--- lib/zstdhc_static.h | 6 +++--- programs/paramgrill.c | 4 +++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index 716213fd3ad..e90b7f3a646 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -292,7 +292,7 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( const U32 windowLow = windowSize >= current ? 0 : current - windowSize; U32* smallerPtr = bt + 2*(current&btMask); U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 bestLength = 0; + size_t bestLength = 0; U32 dummy32; /* to be nullified at the end */ hashTable[h] = (U32)(ip-base); /* Update Hash Table */ @@ -307,8 +307,8 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( if (matchLength > bestLength) { - bestLength = (U32)matchLength; - *offsetPtr = current - matchIndex; + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit(offsetPtr[0]+1)) ) + bestLength = matchLength, *offsetPtr = current - matchIndex; if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ } diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index 06174fcdeca..bbe1571347b 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -116,10 +116,10 @@ static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ { 22, 21, 22, 5, 5, ZSTD_HC_btlazy2 }, /* level 16 */ - { 22, 22, 23, 5, 5, ZSTD_HC_btlazy2 }, /* level 17 */ + { 22, 23, 22, 4, 5, ZSTD_HC_btlazy2 }, /* level 17 */ { 22, 22, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 18 */ - { 24, 24, 22, 7, 5, ZSTD_HC_btlazy2 }, /* level 19 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ + { 23, 23, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 19 */ + { 24, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 21 */ { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 22 */ { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 23 */ diff --git a/programs/paramgrill.c b/programs/paramgrill.c index f7cfef98e52..40033a6a341 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -696,6 +696,7 @@ static void BMK_benchMem(void* srcBuffer, size_t srcSize) if (g_singleRun) { BMK_result_t testResult; + ZSTD_HC_validateParams(&g_params, g_blockSize ? g_blockSize : srcSize); BMK_benchParam(&testResult, srcBuffer, srcSize, ctx, g_params); DISPLAY("\n"); return; @@ -978,7 +979,8 @@ int main(int argc, char** argv) argument++; while ((*argument>= '0') && (*argument<='9')) { - if (*argument++) g_params.strategy = ZSTD_HC_lazy; + g_params.strategy = (ZSTD_HC_strategy)((U32)g_params.strategy *10); + g_params.strategy = (ZSTD_HC_strategy)((U32)g_params.strategy + *argument++ - '0'); } continue; case 'L': From e8455f51eac9ec84eeeb035dc1a92175fa3f1b2d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 17:41:20 +0100 Subject: [PATCH 09/14] fix clang warning --- lib/zstdhc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index e90b7f3a646..c061ecdbef3 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -307,7 +307,7 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( if (matchLength > bestLength) { - if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit(offsetPtr[0]+1)) ) + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)offsetPtr[0]+1)) ) bestLength = matchLength, *offsetPtr = current - matchIndex; if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ From 2c7ac7c055c8f12758cd4b72de44993915eae6cf Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 17:52:18 +0100 Subject: [PATCH 10/14] fix bench on /dev/null --- programs/bench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/bench.c b/programs/bench.c index c19d0fd97ff..0009e4ae549 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -241,7 +241,7 @@ static size_t local_compress_fast (void* dst, size_t maxDstSize, const void* src static int BMK_benchMem(void* srcBuffer, size_t srcSize, const char* fileName, int cLevel) { - const size_t blockSize = g_blockSize ? g_blockSize : srcSize; + const size_t blockSize = (g_blockSize ? g_blockSize : srcSize) + (!srcSize); /* avoid div by 0 */ const U32 nbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize); blockParam_t* const blockTable = (blockParam_t*) malloc(nbBlocks * sizeof(blockParam_t)); const size_t maxCompressedSize = (size_t)nbBlocks * ZSTD_compressBound(blockSize); From 3e3582719c3fdc2be5792ebdf9304d7a65fcabec Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 18:19:39 +0100 Subject: [PATCH 11/14] Fixed issue #62, reported by @luben --- lib/zstdhc.c | 39 +++++++++++---------------------------- programs/fuzzer.c | 21 +++++++++++---------- 2 files changed, 22 insertions(+), 38 deletions(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index c061ecdbef3..ccd25236225 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -942,45 +942,26 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, void* dst, size_t maxDstSize, const void* src, size_t srcSize) { - static const size_t blockSize = 128 KB; + size_t blockSize = BLOCKSIZE; size_t remaining = srcSize; const BYTE* ip = (const BYTE*)src; BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; - BYTE* const oend = op + maxDstSize; const ZSTD_HC_blockCompressor blockCompressor = ZSTD_HC_selectBlockCompressor(ctxPtr->params.strategy); - - while (remaining > blockSize) + while (remaining) { - size_t cSize = blockCompressor(ctxPtr, op+3, oend-op, ip, blockSize); + size_t cSize; - if (cSize == 0) - { - cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, blockSize); /* block is not compressible */ - } - else - { - op[0] = (BYTE)(cSize>>16); - op[1] = (BYTE)(cSize>>8); - op[2] = (BYTE)cSize; - op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */ - cSize += 3; - } + if (maxDstSize < 5) return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */ - remaining -= blockSize; - ip += blockSize; - op += cSize; + if (remaining < blockSize) blockSize = remaining; + cSize = blockCompressor(ctxPtr, op+3, maxDstSize-3, ip, blockSize); if (ZSTD_isError(cSize)) return cSize; - } - - /* last block */ - { - size_t cSize = blockCompressor(ctxPtr, op+3, oend-op, ip, remaining); if (cSize == 0) { - cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, remaining); /* block is not compressible */ + cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, blockSize); /* block is not compressible */ } else { @@ -991,8 +972,10 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, cSize += 3; } + remaining -= blockSize; + maxDstSize -= cSize; + ip += blockSize; op += cSize; - if (ZSTD_isError(cSize)) return cSize; } return op-ostart; @@ -1077,7 +1060,7 @@ size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx, /* body (compression) */ ctx->base = (const BYTE*)src; - op += ZSTD_HC_compress_generic (ctx, op, maxDstSize, src, srcSize); + oSize = ZSTD_HC_compress_generic (ctx, op, maxDstSize, src, srcSize); if(ZSTD_isError(oSize)) return oSize; op += oSize; maxDstSize -= oSize; diff --git a/programs/fuzzer.c b/programs/fuzzer.c index a549d232f59..217c829296b 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -328,14 +328,15 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize); crcOrig = XXH64(srcBuffer + sampleStart, sampleSize, 0); - /* HC compression test */ - cLevel = (FUZ_rand(&lseed) & 3) + 2; - cSize = ZSTD_HC_compressCCtx(hcctx, cBuffer, cBufferSize, srcBuffer + sampleStart, sampleSize, cLevel); - CHECK(ZSTD_isError(cSize), "ZSTD_compress failed"); - /* compression test */ + /* covered by HC cLevel 1 cSize = ZSTD_compressCCtx(ctx, cBuffer, cBufferSize, srcBuffer + sampleStart, sampleSize); - CHECK(ZSTD_isError(cSize), "ZSTD_compress failed"); + CHECK(ZSTD_isError(cSize), "ZSTD_compress failed"); */ + + /* HC compression test */ + cLevel = (FUZ_rand(&lseed) & 3) +1; + cSize = ZSTD_HC_compressCCtx(hcctx, cBuffer, cBufferSize, srcBuffer + sampleStart, sampleSize, cLevel); + CHECK(ZSTD_isError(cSize), "ZSTD_HC_compressCCtx failed"); /* compression failure test : too small dest buffer */ if (cSize > 3) @@ -346,16 +347,16 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit static const U32 endMark = 0x4DC2B1A9; U32 endCheck; memcpy(dstBuffer+tooSmallSize, &endMark, 4); - errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, srcBuffer + sampleStart, sampleSize); - CHECK(!ZSTD_isError(errorCode), "ZSTD_compress should have failed ! (buffer too small)"); + errorCode = ZSTD_HC_compressCCtx(hcctx, dstBuffer, tooSmallSize, srcBuffer + sampleStart, sampleSize, cLevel); + CHECK(!ZSTD_isError(errorCode), "ZSTD_HC_compressCCtx should have failed ! (buffer too small : %u < %u)", (U32)tooSmallSize, (U32)cSize); memcpy(&endCheck, dstBuffer+tooSmallSize, 4); - CHECK(endCheck != endMark, "ZSTD_compress : dst buffer overflow"); + CHECK(endCheck != endMark, "ZSTD_HC_compressCCtx : dst buffer overflow"); } /* successfull decompression tests*/ dSupSize = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1; dSize = ZSTD_decompress(dstBuffer, sampleSize + dSupSize, cBuffer, cSize); - CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s)", ZSTD_getErrorName(dSize)); + CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (U32)sampleSize, (U32)cSize); crcDest = XXH64(dstBuffer, sampleSize, 0); CHECK(crcOrig != crcDest, "dstBuffer corrupted (pos %u / %u)", (U32)findDiff(srcBuffer+sampleStart, dstBuffer, sampleSize), (U32)sampleSize); From 50c5cdb44ca30860ddebe64c9a3633fa7fc8f04c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 20:35:33 +0100 Subject: [PATCH 12/14] fixed issues reported by Maciej Adamczyk --- lib/zstd.c | 1 + lib/zstd_internal.h | 4 +++- programs/zstdcli.c | 17 +++++++++-------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/zstd.c b/lib/zstd.c index c7dcc262a38..db533f9a50d 100644 --- a/lib/zstd.c +++ b/lib/zstd.c @@ -921,6 +921,7 @@ size_t ZSTD_decodeLiteralsBlock(void* ctx, { if (litSize > srcSize-3) return ERROR(corruption_detected); memcpy(dctx->litBuffer, istart, litSize); + dctx->litPtr = dctx->litBuffer; dctx->litBufSize = BLOCKSIZE+8; dctx->litSize = litSize; return litSize+3; diff --git a/lib/zstd_internal.h b/lib/zstd_internal.h index 207fd84bf35..f6363645946 100644 --- a/lib/zstd_internal.h +++ b/lib/zstd_internal.h @@ -171,7 +171,9 @@ static void ZSTD_wildcopy(void* dst, const void* src, size_t length) const BYTE* ip = (const BYTE*)src; BYTE* op = (BYTE*)dst; BYTE* const oend = op + length; - do COPY8(op, ip) while (op < oend); + do + COPY8(op, ip) + while (op < oend); } diff --git a/programs/zstdcli.c b/programs/zstdcli.c index b22095983fe..4c8460d8a2c 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -178,7 +178,7 @@ int main(int argc, char** argv) const char* inFileName = NULL; const char* outFileName = NULL; char* dynNameSpace = NULL; - char extension[] = ZSTD_EXTENSION; + const char extension[] = ZSTD_EXTENSION; displayOut = stderr; /* Pick out basename component. Don't rely on stdlib because of conflicting behavior. */ @@ -351,16 +351,17 @@ int main(int argc, char** argv) } /* decompression to file (automatic name will work only if input filename has correct format extension) */ { - size_t outl; - size_t inl = strlen(inFileName); - dynNameSpace = (char*)calloc(1,inl+1); + size_t filenameSize = strlen(inFileName); + if (strcmp(inFileName + (filenameSize-4), extension)) + { + DISPLAYLEVEL(1, "unknown suffix - cannot determine destination filename\n"); + return badusage(programName); + } + dynNameSpace = (char*)calloc(1,filenameSize+1); if (dynNameSpace==NULL) { DISPLAY("not enough memory\n"); exit(1); } outFileName = dynNameSpace; strcpy(dynNameSpace, inFileName); - outl = inl; - if (inl>4) - while ((outl >= inl-4) && (inFileName[outl] == extension[outl-inl+4])) dynNameSpace[outl--]=0; - if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename\n"); return badusage(programName); } + dynNameSpace[filenameSize-4]=0; DISPLAYLEVEL(2, "Decoding file %s \n", outFileName); } } From 3137d1a059eb78b8791c825c795d5170166aac17 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 23:36:36 +0100 Subject: [PATCH 13/14] fix fuzzer32 litCSize limit condition --- lib/zstd.c | 2 -- lib/zstd_internal.h | 4 ++++ lib/zstdhc.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/zstd.c b/lib/zstd.c index db533f9a50d..776a5bca529 100644 --- a/lib/zstd.c +++ b/lib/zstd.c @@ -120,8 +120,6 @@ #define GB *(1U<<30) #define BLOCKSIZE (128 KB) /* define, for static allocation */ -#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/) -#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE) #define IS_RAW BIT0 #define IS_RLE BIT1 diff --git a/lib/zstd_internal.h b/lib/zstd_internal.h index f6363645946..ee0f67359ae 100644 --- a/lib/zstd_internal.h +++ b/lib/zstd_internal.h @@ -214,6 +214,10 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr); #define MaxLL ((1< Date: Thu, 5 Nov 2015 00:48:37 +0100 Subject: [PATCH 14/14] level tuning --- images/CSpeed.png | Bin 18232 -> 18534 bytes lib/zstdhc_static.h | 24 +++++++++++------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/images/CSpeed.png b/images/CSpeed.png index 6e60dbc78f70e5907339a28c0399ecd63ec56895..88d302c8a1d1755b16286f6df0ec812da334175b 100644 GIT binary patch literal 18534 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 diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index bbe1571347b..0cf7476b7b3 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -96,7 +96,7 @@ size_t ZSTD_HC_compressEnd(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize); /* ************************************* * Pre-defined compression levels ***************************************/ -#define ZSTD_HC_MAX_CLEVEL 26 +#define ZSTD_HC_MAX_CLEVEL 22 static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] = { /* W, C, H, S, L, strat */ { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 0 - never used */ @@ -106,28 +106,26 @@ static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] { 20, 17, 19, 3, 5, ZSTD_HC_greedy }, /* level 4 */ { 20, 18, 19, 2, 5, ZSTD_HC_lazy }, /* level 5 */ { 21, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ - { 21, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ + { 21, 20, 20, 3, 5, ZSTD_HC_lazy }, /* level 7 */ { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazydeep }, /* level 11 */ { 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ { 22, 20, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 13 */ - { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ + { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ { 22, 21, 22, 5, 5, ZSTD_HC_btlazy2 }, /* level 16 */ - { 22, 23, 22, 4, 5, ZSTD_HC_btlazy2 }, /* level 17 */ - { 22, 22, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 18 */ - { 23, 23, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 19 */ - { 24, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 21 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 22 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 23 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 24 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 25 */ - { 25, 25, 24, 9, 5, ZSTD_HC_btlazy2 }, /* level 26 */ + { 22, 22, 23, 5, 5, ZSTD_HC_btlazy2 }, /* level 17 */ + { 23, 23, 23, 5, 5, ZSTD_HC_btlazy2 }, /* level 18 */ + { 25, 25, 22, 5, 5, ZSTD_HC_btlazy2 }, /* level 19 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ + { 25, 26, 23, 9, 5, ZSTD_HC_btlazy2 }, /* level 21 */ + { 25, 26, 23, 9, 5, ZSTD_HC_btlazy2 }, /* level 22 */ }; + + #if defined (__cplusplus) } #endif