Part 2 of #3528 Adds hash salt that helps to avoid regressions where consecutive compressions use the same tag space with similar data (running zstd -b5e7 enwik8 -B128K reproduces this regression).
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
#include "zstd_opt.h"
|
||||
#include "zstd_ldm.h"
|
||||
#include "zstd_compress_superblock.h"
|
||||
#include "../common/bits.h" /* ZSTD_highbit32 */
|
||||
#include "../common/bits.h" /* ZSTD_highbit32, ZSTD_rotateRight_U64 */
|
||||
|
||||
/* ***************************************************************
|
||||
* Tuning parameters
|
||||
@@ -1907,6 +1907,19 @@ typedef enum {
|
||||
ZSTD_resetTarget_CCtx
|
||||
} ZSTD_resetTarget_e;
|
||||
|
||||
/* Mixes bits in a 64 bits in a value, based on XXH3_rrmxmx */
|
||||
static U64 ZSTD_bitmix(U64 val, U64 len) {
|
||||
val ^= ZSTD_rotateRight_U64(val, 49) ^ ZSTD_rotateRight_U64(val, 24);
|
||||
val *= 0x9FB21C651E98DF25ULL;
|
||||
val ^= (val >> 35) + len ;
|
||||
val *= 0x9FB21C651E98DF25ULL;
|
||||
return val ^ (val >> 28);
|
||||
}
|
||||
|
||||
/* Mixes in the hashSalt and hashSaltEntropy to create a new hashSalt */
|
||||
static void ZSTD_advanceHashSalt(ZSTD_matchState_t* ms) {
|
||||
ms->hashSalt = ZSTD_bitmix(ms->hashSalt, 8) ^ ZSTD_bitmix((U64) ms->hashSaltEntropy, 4);
|
||||
}
|
||||
|
||||
static size_t
|
||||
ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
||||
@@ -1958,7 +1971,17 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
||||
if (ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)) {
|
||||
/* Row match finder needs an additional table of hashes ("tags") */
|
||||
size_t const tagTableSize = hSize;
|
||||
ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned_init_once(ws, tagTableSize);
|
||||
/* We want to generate a new salt in case we reset a Cctx, but we always want to use
|
||||
* 0 when we reset a Cdict */
|
||||
if(forWho == ZSTD_resetTarget_CCtx) {
|
||||
ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned_init_once(ws, tagTableSize);
|
||||
ZSTD_advanceHashSalt(ms);
|
||||
} else {
|
||||
/* When we are not salting we want to always memset the memory */
|
||||
ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned(ws, tagTableSize);
|
||||
ZSTD_memset(ms->tagTable, 0, tagTableSize);
|
||||
ms->hashSalt = 0;
|
||||
}
|
||||
{ /* Switch to 32-entry rows if searchLog is 5 (or more) */
|
||||
U32 const rowLog = BOUNDED(4, cParams->searchLog, 6);
|
||||
assert(cParams->hashLog >= rowLog);
|
||||
@@ -2364,8 +2387,9 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
||||
if (ZSTD_rowMatchFinderUsed(cdict_cParams->strategy, cdict->useRowMatchFinder)) {
|
||||
size_t const tagTableSize = hSize;
|
||||
ZSTD_memcpy(cctx->blockState.matchState.tagTable,
|
||||
cdict->matchState.tagTable,
|
||||
tagTableSize);
|
||||
cdict->matchState.tagTable,
|
||||
tagTableSize);
|
||||
cctx->blockState.matchState.hashSalt = cdict->matchState.hashSalt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user