]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
added fast mode
authorYann Collet <yann.collet.73@gmail.com>
Thu, 5 Nov 2015 16:32:18 +0000 (17:32 +0100)
committerYann Collet <yann.collet.73@gmail.com>
Thu, 5 Nov 2015 16:32:18 +0000 (17:32 +0100)
lib/zstd.c
lib/zstd_internal.h
lib/zstdhc.c
lib/zstdhc_static.h
programs/paramgrill.c

index 776a5bca529bb3afa034e07b56428727284e6cf3..a76d111f3de0989c5c1a8c3e467a07b425fbce87 100644 (file)
 
 static const U32 g_maxDistance = 4 * BLOCKSIZE;
 static const U32 g_maxLimit = 1 GB;
-static const U32 g_searchStrength = 8;
 
 #define WORKPLACESIZE (BLOCKSIZE*3)
 #define MINMATCH 4
@@ -524,8 +523,6 @@ static U32   ZSTD_hashPtr(const void* p) { return ( (MEM_read64(p) * prime7bytes
 
 //static U32   ZSTD_hashPtr(const void* p) { return ( (*(U32*)p * KNUTH) >> (32-HASH_LOG)); }
 
-static void  ZSTD_addPtr(U32* table, const BYTE* p, const BYTE* start) { table[ZSTD_hashPtr(p)] = (U32)(p-start); }
-
 static const BYTE* ZSTD_updateMatch(U32* table, const BYTE* p, const BYTE* start)
 {
     U32 h = ZSTD_hashPtr(p);
@@ -540,6 +537,8 @@ static int ZSTD_checkMatch(const BYTE* match, const BYTE* ip)
     return MEM_read32(match) == MEM_read32(ip);
 }
 
+static void  ZSTD_addPtr(U32* table, const BYTE* p, const BYTE* start) { table[ZSTD_hashPtr(p)] = (U32)(p-start); }
+
 
 static size_t ZSTD_compressBlock(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
 {
index ee0f67359aed64aab8f30e19a938de03181b4cdf..dffa1fe684a469ca7e91ce607b7b8912c6d149e1 100644 (file)
@@ -206,6 +206,8 @@ typedef struct {
 
 void ZSTD_resetSeqStore(seqStore_t* ssPtr);
 
+static const U32 g_searchStrength = 8;
+
 #define REPCODE_STARTVALUE 4
 #define MLbits   7
 #define LLbits   6
@@ -217,7 +219,6 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr);
 #define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)
 #define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)
 
-
 /** ZSTD_storeSeq
     Store a sequence (literal length, literals, offset code and match length) into seqStore_t
     @offsetCode : distance to match, or 0 == repCode
index 178ac970a47c998db1df16608788f4067d7fa260..fa059cb97921d9b7df850ee4c382f365ecef6cd6 100644 (file)
@@ -91,7 +91,7 @@ struct ZSTD_HC_CCtx_s
 
     seqStore_t seqStore;    /* sequences storage ptrs */
     U32* hashTable;
-    U32* chainTable;
+    U32* contentTable;
 };
 
 
@@ -113,7 +113,7 @@ size_t ZSTD_HC_freeCCtx(ZSTD_HC_CCtx* cctx)
     optimize for srcSize if srcSize > 0 */
 void ZSTD_HC_validateParams(ZSTD_HC_parameters* params, size_t srcSize)
 {
-    const U32 chainplus = (params->strategy == ZSTD_HC_btlazy2);
+    const U32 btPlus = (params->strategy == ZSTD_HC_btlazy2);
 
     /* validate params */
     if (params->windowLog   > ZSTD_HC_WINDOWLOG_MAX) params->windowLog = ZSTD_HC_WINDOWLOG_MAX;
@@ -126,8 +126,8 @@ void ZSTD_HC_validateParams(ZSTD_HC_parameters* params, size_t srcSize)
         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->contentLog  > params->windowLog+btPlus) params->contentLog = params->windowLog+btPlus;   /* <= ZSTD_HC_CONTENTLOG_MAX */
+    if (params->contentLog  < ZSTD_HC_CONTENTLOG_MIN) params->contentLog = ZSTD_HC_CONTENTLOG_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;
@@ -135,7 +135,6 @@ void ZSTD_HC_validateParams(ZSTD_HC_parameters* params, size_t srcSize)
     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;
 }
 
 
@@ -146,7 +145,8 @@ static size_t ZSTD_HC_resetCCtx_advanced (ZSTD_HC_CCtx* zc,
 
     /* reserve table memory */
     {
-        const size_t tableSpace = ((1 << params.chainLog) + (1 << params.hashLog)) * sizeof(U32);
+        const U32 contentLog = params.strategy == ZSTD_HC_fast ? 1 : params.contentLog;
+        const size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog)) * sizeof(U32);
         const size_t neededSpace = tableSpace + WORKPLACESIZE;
         if (zc->workSpaceSize < neededSpace)
         {
@@ -156,8 +156,8 @@ static size_t ZSTD_HC_resetCCtx_advanced (ZSTD_HC_CCtx* zc,
             if (zc->workSpace == NULL) return ERROR(memory_allocation);
         }
         zc->hashTable = (U32*)zc->workSpace;
-        zc->chainTable = zc->hashTable + ((size_t)1 << params.hashLog);
-        zc->seqStore.buffer = (void*) (zc->chainTable + ((size_t)1 << params.chainLog));
+        zc->contentTable = zc->hashTable + ((size_t)1 << params.hashLog);
+        zc->seqStore.buffer = (void*) (zc->contentTable + ((size_t)1 << contentLog));
         memset(zc->hashTable, 0, tableSpace );
     }
 
@@ -195,6 +195,10 @@ 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 const U64 prime7bytes =    58295818150454627ULL;
+static size_t ZSTD_HC_hash7(U64 u, U32 h) { return (size_t)((u * prime7bytes) << (64-56) >> (64-h)) ; }
+static size_t ZSTD_HC_hash7Ptr(const void* p, U32 h) { return ZSTD_HC_hash7(MEM_read64(p), h); }
+
 static size_t ZSTD_HC_hashPtr(const void* p, U32 hBits, U32 mls)
 {
     switch(mls)
@@ -203,10 +207,104 @@ static size_t ZSTD_HC_hashPtr(const void* p, U32 hBits, U32 mls)
     case 4: return ZSTD_HC_hash4Ptr(p, hBits);
     case 5: return ZSTD_HC_hash5Ptr(p, hBits);
     case 6: return ZSTD_HC_hash6Ptr(p, hBits);
+    case 7: return ZSTD_HC_hash7Ptr(p, hBits);
     }
 }
 
-#define NEXT_IN_CHAIN(d, mask)   chainTable[(d) & mask]
+/* *************************************
+*  Fast Scan
+***************************************/
+
+FORCE_INLINE
+size_t ZSTD_HC_compressBlock_fast_generic(ZSTD_HC_CCtx* ctx,
+                                          void* dst, size_t maxDstSize,
+                                    const void* src, size_t srcSize,
+                                    const U32 mls)
+{
+    U32* hashTable = ctx->hashTable;
+    const U32 hBits = ctx->params.hashLog;
+    seqStore_t* seqStorePtr = &(ctx->seqStore);
+    const BYTE* const base = ctx->base;
+
+    const BYTE* const istart = (const BYTE*)src;
+    const BYTE* ip = istart + 1;
+    const BYTE* anchor = istart;
+    const BYTE* const iend = istart + srcSize;
+    const BYTE* const ilimit = iend - 8;
+
+    size_t offset_2=4, offset_1=4;
+
+
+    /* init */
+    if (ip == base)
+    {
+        hashTable[ZSTD_HC_hashPtr(base+1, hBits, mls)] = 1;
+        hashTable[ZSTD_HC_hashPtr(base+2, hBits, mls)] = 2;
+        hashTable[ZSTD_HC_hashPtr(base+3, hBits, mls)] = 3;
+        ip = base+4;
+    }
+    ZSTD_resetSeqStore(seqStorePtr);
+
+    /* Main Search Loop */
+    while (ip < ilimit)  /* < instead of <=, because unconditionnal ZSTD_addPtr(ip+1) */
+    {
+        const size_t h = ZSTD_HC_hashPtr(ip, hBits, mls);
+        const BYTE* match = base + hashTable[h];
+        hashTable[h] = (U32)(ip-base);
+
+        if (MEM_read32(ip-offset_2) == MEM_read32(ip)) match = ip-offset_2;
+        if (MEM_read32(match) != MEM_read32(ip)) { ip += ((ip-anchor) >> g_searchStrength) + 1; offset_2 = offset_1; continue; }
+        while ((ip>anchor) && (match>base) && (ip[-1] == match[-1])) { ip--; match--; }  /* catch up */
+
+        {
+            size_t litLength = ip-anchor;
+            size_t matchLength = ZSTD_count(ip+MINMATCH, match+MINMATCH, iend);
+            size_t offsetCode = ip-match;
+            if (offsetCode == offset_2) offsetCode = 0;
+            offset_2 = offset_1;
+            offset_1 = ip-match;
+            ZSTD_storeSeq(seqStorePtr, litLength, anchor, offsetCode, matchLength);
+
+            /* Fill Table */
+            hashTable[ZSTD_HC_hashPtr(ip+1, hBits, mls)] = (U32)(ip+1-base);
+            ip += matchLength + MINMATCH;
+            anchor = ip;
+            if (ip < ilimit) /* same test as loop, for speed */
+                hashTable[ZSTD_HC_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
+        }
+    }
+
+    /* Last Literals */
+    {
+        size_t lastLLSize = iend - anchor;
+        memcpy(seqStorePtr->lit, anchor, lastLLSize);
+        seqStorePtr->lit += lastLLSize;
+    }
+
+    /* Finale compression stage */
+    return ZSTD_compressSequences((BYTE*)dst, maxDstSize,
+                                  seqStorePtr, srcSize);
+}
+
+
+size_t ZSTD_HC_compressBlock_fast(ZSTD_HC_CCtx* ctx,
+                               void* dst, size_t maxDstSize,
+                         const void* src, size_t srcSize)
+{
+    const U32 mls = ctx->params.searchLength;
+    switch(mls)
+    {
+    default:
+    case 4 :
+        return ZSTD_HC_compressBlock_fast_generic(ctx, dst, maxDstSize, src, srcSize, 4);
+    case 5 :
+        return ZSTD_HC_compressBlock_fast_generic(ctx, dst, maxDstSize, src, srcSize, 5);
+    case 6 :
+        return ZSTD_HC_compressBlock_fast_generic(ctx, dst, maxDstSize, src, srcSize, 6);
+    case 7 :
+        return ZSTD_HC_compressBlock_fast_generic(ctx, dst, maxDstSize, src, srcSize, 7);
+    }
+}
 
 
 /* *************************************
@@ -219,8 +317,8 @@ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32
     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;
+    U32* const bt   = zc->contentTable;
+    const U32 btLog = zc->params.contentLog - 1;
     const U32 btMask= (1 << btLog) - 1;
     U32 matchIndex  = hashTable[h];
     size_t commonLengthSmaller=0, commonLengthLarger=0;
@@ -280,8 +378,8 @@ size_t ZSTD_HC_insertBtAndFindBestMatch (
     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;
+    U32* const bt   = zc->contentTable;
+    const U32 btLog = zc->params.contentLog - 1;
     const U32 btMask= (1 << btLog) - 1;
     U32 matchIndex  = hashTable[h];
     size_t commonLengthSmaller=0, commonLengthLarger=0;
@@ -389,13 +487,15 @@ FORCE_INLINE size_t ZSTD_HC_BtFindBestMatch_selectMLS (
 *  Hash Chain
 *************************/
 
+#define NEXT_IN_CHAIN(d, mask)   chainTable[(d) & mask]
+
 /* Update chains up to ip (excluded) */
 static U32 ZSTD_HC_insertAndFindFirstIndex  (ZSTD_HC_CCtx* zc, const BYTE* ip, U32 mls)
 {
     U32* const hashTable  = zc->hashTable;
     const U32 hashLog = zc->params.hashLog;
-    U32* const chainTable = zc->chainTable;
-    const U32 chainMask = (1 << zc->params.chainLog) - 1;
+    U32* const chainTable = zc->contentTable;
+    const U32 chainMask = (1 << zc->params.contentLog) - 1;
     const BYTE* const base = zc->base;
     const U32 target = (U32)(ip - base);
     U32 idx = zc->nextToUpdate;
@@ -414,14 +514,14 @@ 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 (
+size_t ZSTD_HC_HcFindBestMatch (
                         ZSTD_HC_CCtx* zc,   /* Index table will be updated */
                         const BYTE* const ip, const BYTE* const iLimit,
                         size_t* offsetPtr,
                         const U32 maxNbAttempts, const U32 matchLengthSearch)
 {
-    U32* const chainTable = zc->chainTable;
-    const U32 chainSize = (1 << zc->params.chainLog);
+    U32* const chainTable = zc->contentTable;
+    const U32 chainSize = (1 << zc->params.contentLog);
     const U32 chainMask = chainSize-1;
     const BYTE* const base = zc->base;
     const BYTE* const dictBase = zc->dictBase;
@@ -477,7 +577,7 @@ size_t ZSTD_HC_insertAndFindBestMatch (
 }
 
 
-FORCE_INLINE size_t ZSTD_HC_insertAndFindBestMatch_selectMLS (
+FORCE_INLINE size_t ZSTD_HC_HcFindBestMatch_selectMLS (
                         ZSTD_HC_CCtx* zc,   /* Index table will be updated */
                         const BYTE* ip, const BYTE* const iLimit,
                         size_t* offsetPtr,
@@ -486,9 +586,9 @@ FORCE_INLINE size_t ZSTD_HC_insertAndFindBestMatch_selectMLS (
     switch(matchLengthSearch)
     {
     default :
-    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);
+    case 4 : return ZSTD_HC_HcFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
+    case 5 : return ZSTD_HC_HcFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
+    case 6 : return ZSTD_HC_HcFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
     }
 }
 
@@ -513,7 +613,7 @@ size_t ZSTD_HC_compressBlock_lazy_generic(ZSTD_HC_CCtx* ctx,
     typedef size_t (*searchMax_f)(ZSTD_HC_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
                         size_t* offsetPtr,
                         U32 maxNbAttempts, U32 matchLengthSearch);
-    searchMax_f searchMax = searchMethod ? ZSTD_HC_BtFindBestMatch_selectMLS : ZSTD_HC_insertAndFindBestMatch_selectMLS;
+    searchMax_f searchMax = searchMethod ? ZSTD_HC_BtFindBestMatch_selectMLS : ZSTD_HC_HcFindBestMatch_selectMLS;
 
     /* init */
     ZSTD_resetSeqStore(seqStorePtr);
@@ -688,7 +788,7 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS
         /* search */
         {
             size_t offset=999999;
-            size_t matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls);
+            size_t matchLength = ZSTD_HC_HcFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls);
             if (!matchLength) { ip++; continue; }
             /* store sequence */
             {
@@ -717,12 +817,13 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS
 
 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(strat)
     {
     default :
+    case ZSTD_HC_fast:
+        return ZSTD_HC_compressBlock_fast;
     case ZSTD_HC_greedy:
         return ZSTD_HC_compressBlock_greedy;
     case ZSTD_HC_lazy:
@@ -852,9 +953,12 @@ size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx,
     size_t oSize;
 
     /* correct params, to use less memory */
-    U32 srcLog = ZSTD_highbit((U32)srcSize-1) + 1;
-    if (params.windowLog > srcLog) params.windowLog = srcLog;
-    if (params.chainLog > srcLog) params.chainLog = srcLog;
+    {
+        U32 srcLog = ZSTD_highbit((U32)srcSize-1) + 1;
+        U32 contentBtPlus = (ctx->params.strategy == ZSTD_HC_btlazy2);
+        if (params.windowLog > srcLog) params.windowLog = srcLog;
+        if (params.contentLog > srcLog+contentBtPlus) params.contentLog = srcLog+contentBtPlus;
+    }
 
     /* Header */
     oSize = ZSTD_HC_compressBegin_advanced(ctx, dst, maxDstSize, params);
index aa76781e844f46b00115528ec5048be5d2a82d60..b1bf5af8212ea5ee42c0e13a547721433b3d20e3 100644 (file)
@@ -46,12 +46,12 @@ extern "C" {
 *  Types
 ***************************************/
 /** from faster to stronger */
-typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy, ZSTD_HC_lazy2, ZSTD_HC_btlazy2 } ZSTD_HC_strategy;
+typedef enum { ZSTD_HC_fast, ZSTD_HC_greedy, ZSTD_HC_lazy, ZSTD_HC_lazy2, ZSTD_HC_btlazy2 } ZSTD_HC_strategy;
 
 typedef struct
 {
     U32 windowLog;     /* largest match distance : impact decompression buffer size */
-    U32 chainLog;      /* full search distance : larger == more compression, slower, more memory*/
+    U32 contentLog;    /* full search segment : larger == more compression, slower, more memory*/
     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 */
@@ -61,13 +61,13 @@ 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+1)
-#define ZSTD_HC_CHAINLOG_MIN 4
+#define ZSTD_HC_CONTENTLOG_MAX (ZSTD_HC_WINDOWLOG_MAX+1)
+#define ZSTD_HC_CONTENTLOG_MIN 4
 #define ZSTD_HC_HASHLOG_MAX 28
 #define ZSTD_HC_HASHLOG_MIN 4
-#define ZSTD_HC_SEARCHLOG_MAX (ZSTD_HC_CHAINLOG_MAX-1)
+#define ZSTD_HC_SEARCHLOG_MAX (ZSTD_HC_CONTENTLOG_MAX-1)
 #define ZSTD_HC_SEARCHLOG_MIN 1
-#define ZSTD_HC_SEARCHLENGTH_MAX 6
+#define ZSTD_HC_SEARCHLENGTH_MAX 7
 #define ZSTD_HC_SEARCHLENGTH_MIN 4
 
 
index af1e83aaec0291738277ebcea17d2155a35d06fb..db0ca790af296a82d0591070e09f669aa8a0ccb8 100644 (file)
@@ -280,7 +280,7 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
     void* const compressedBuffer = malloc(maxCompressedSize);
     void* const resultBuffer = malloc(srcSize);
     U32 Wlog = params.windowLog;
-    U32 Clog = params.chainLog;
+    U32 Clog = params.contentLog;
     U32 Hlog = params.hashLog;
     U32 Slog = params.searchLog;
     U32 Slength = params.searchLength;
@@ -429,7 +429,8 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
 }
 
 
-const char* g_stratName[] = { "ZSTD_HC_greedy ",
+const char* g_stratName[] = { "ZSTD_HC_fast   ",
+                              "ZSTD_HC_greedy ",
                               "ZSTD_HC_lazy   ",
                               "ZSTD_HC_lazy2  ",
                               "ZSTD_HC_btlazy2" };
@@ -438,8 +439,8 @@ static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_HC_pa
 {
     DISPLAY("\r%79s\r", "");
     fprintf(f,"    {%3u,%3u,%3u,%3u,%3u, %s },  ",
-            params.windowLog, params.chainLog, params.hashLog, params.searchLog, params.searchLength,
-            g_stratName[params.strategy]);
+            params.windowLog, params.contentLog, params.hashLog, params.searchLog, params.searchLength,
+            g_stratName[(U32)(params.strategy)]);
     fprintf(f,
             "/* 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.);
@@ -512,8 +513,8 @@ static int BMK_seed(winnerInfo_t* winners, const ZSTD_HC_parameters params,
             double W_DMemUsed_note = W_ratioNote * ( 40 + 9*cLevel) - log((double)W_DMemUsed);
             double O_DMemUsed_note = O_ratioNote * ( 40 + 9*cLevel) - log((double)O_DMemUsed);
 
-            size_t W_CMemUsed = (1 << params.windowLog) + 4 * (1 << params.hashLog) + 4 * (1 << params.chainLog);
-            size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + 4 * (1 << winners[cLevel].params.hashLog) + 4 * (1 << winners[cLevel].params.chainLog);
+            size_t W_CMemUsed = (1 << params.windowLog) + 4 * (1 << params.hashLog) + 4 * (1 << params.contentLog);
+            size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + 4 * (1 << winners[cLevel].params.hashLog) + 4 * (1 << winners[cLevel].params.contentLog);
             double W_CMemUsed_note = W_ratioNote * ( 50 + 13*cLevel) - log((double)W_CMemUsed);
             double O_CMemUsed_note = O_ratioNote * ( 50 + 13*cLevel) - log((double)O_CMemUsed);
 
@@ -579,15 +580,15 @@ static int BMK_seed(winnerInfo_t* winners, const ZSTD_HC_parameters params,
 #define MAX(a,b)   ( (a) > (b) ? (a) : (b) )
 
 static BYTE g_alreadyTested[ZSTD_HC_WINDOWLOG_MAX+1-ZSTD_HC_WINDOWLOG_MIN]
-                           [ZSTD_HC_CHAINLOG_MAX+1-ZSTD_HC_CHAINLOG_MIN]
+                           [ZSTD_HC_CONTENTLOG_MAX+1-ZSTD_HC_CONTENTLOG_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]
-                           [4 /* strategy */ ] = {};   /* init to zero */
+                           [ZSTD_HC_btlazy2+1 /* strategy */ ] = {};   /* init to zero */
 
 #define NB_TESTS_PLAYED(p) \
     g_alreadyTested[p.windowLog-ZSTD_HC_WINDOWLOG_MIN] \
-                   [p.chainLog-ZSTD_HC_CHAINLOG_MIN]   \
+                   [p.contentLog-ZSTD_HC_CONTENTLOG_MIN]   \
                    [p.hashLog-ZSTD_HC_HASHLOG_MIN]     \
                    [p.searchLog-ZSTD_HC_SEARCHLOG_MIN] \
                    [p.searchLength-ZSTD_HC_SEARCHLENGTH_MIN] \
@@ -614,9 +615,9 @@ static void playAround(FILE* f, winnerInfo_t* winners,
             switch(changeID)
             {
             case 0:
-                p.chainLog++; break;
+                p.contentLog++; break;
             case 1:
-                p.chainLog--; break;
+                p.contentLog--; break;
             case 2:
                 p.hashLog++; break;
             case 3:
@@ -673,12 +674,12 @@ static void BMK_selectRandomStart(
     {
         /* totally random entry */
         ZSTD_HC_parameters p;
-        p.chainLog   = FUZ_rand(&g_rand) % (ZSTD_HC_CHAINLOG_MAX+1 - ZSTD_HC_CHAINLOG_MIN) + ZSTD_HC_CHAINLOG_MIN;
+        p.contentLog = FUZ_rand(&g_rand) % (ZSTD_HC_CONTENTLOG_MAX+1 - ZSTD_HC_CONTENTLOG_MIN) + ZSTD_HC_CONTENTLOG_MIN;
         p.hashLog    = FUZ_rand(&g_rand) % (ZSTD_HC_HASHLOG_MAX+1 - ZSTD_HC_HASHLOG_MIN) + ZSTD_HC_HASHLOG_MIN;
         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) % 4);
+        p.strategy   = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) % (ZSTD_HC_btlazy2+1));
         playAround(f, winners, p, srcBuffer, srcSize, ctx);
     }
     else
@@ -718,8 +719,8 @@ static void BMK_benchMem(void* srcBuffer, size_t srcSize)
         BMK_result_t testResult;
         params = g_seedParams[2];
         params.windowLog = MIN(srcLog, params.windowLog);
-        params.chainLog = MIN(params.windowLog, params.chainLog);
-        params.searchLog = MIN(params.chainLog, params.searchLog);
+        params.contentLog = MIN(params.windowLog, params.contentLog);
+        params.searchLog = MIN(params.contentLog, params.searchLog);
         BMK_benchParam(&testResult, srcBuffer, srcSize, ctx, params);
         g_cSpeedTarget[2] = (testResult.cSpeed * 15) >> 4;
     }
@@ -735,8 +736,8 @@ static void BMK_benchMem(void* srcBuffer, size_t srcSize)
         {
             params = g_seedParams[i];
             params.windowLog = MIN(srcLog, params.windowLog);
-            params.chainLog = MIN(params.windowLog, params.chainLog);
-            params.searchLog = MIN(params.chainLog, params.searchLog);
+            params.contentLog = MIN(params.windowLog, params.contentLog);
+            params.searchLog = MIN(params.contentLog, params.searchLog);
             BMK_seed(winners, params, srcBuffer, srcSize, ctx);
         }
     }
@@ -954,10 +955,10 @@ int main(int argc, char** argv)
                                 g_params.windowLog *= 10, g_params.windowLog += *argument++ - '0';
                             continue;
                         case 'c':
-                            g_params.chainLog = 0;
+                            g_params.contentLog = 0;
                             argument++;
                             while ((*argument>= '0') && (*argument<='9'))
-                                g_params.chainLog *= 10, g_params.chainLog += *argument++ - '0';
+                                g_params.contentLog *= 10, g_params.contentLog += *argument++ - '0';
                             continue;
                         case 'h':
                             g_params.hashLog = 0;
@@ -978,7 +979,7 @@ int main(int argc, char** argv)
                                 g_params.searchLength *= 10, g_params.searchLength += *argument++ - '0';
                             continue;
                         case 't':  /* strategy */
-                            g_params.strategy = ZSTD_HC_greedy;
+                            g_params.strategy = (ZSTD_HC_strategy)0;
                             argument++;
                             while ((*argument>= '0') && (*argument<='9'))
                             {