From e1ae398ad539038d2148bca87fc35b8837ff2f42 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 11:07:52 -0400
Subject: [PATCH 01/51] Add rawSeqStore to match state
---
lib/compress/zstd_compress_internal.h | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index 728afade7..524cbb025 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -86,6 +86,19 @@ typedef struct {
U32 len;
} ZSTD_match_t;
+typedef struct {
+ U32 offset;
+ U32 litLength;
+ U32 matchLength;
+} rawSeq;
+
+typedef struct {
+ rawSeq* seq; /* The start of the sequences */
+ size_t pos; /* The position where reading stopped. <= size. */
+ size_t size; /* The number of sequences. <= capacity. */
+ size_t capacity; /* The capacity starting from `seq` pointer */
+} rawSeqStore_t;
+
typedef struct {
int price;
U32 off;
@@ -152,6 +165,7 @@ struct ZSTD_matchState_t {
optState_t opt; /* optimal parser state */
const ZSTD_matchState_t* dictMatchState;
ZSTD_compressionParameters cParams;
+ rawSeqStore_t ldmSeqStore;
};
typedef struct {
@@ -183,19 +197,6 @@ typedef struct {
U32 windowLog; /* Window log for the LDM */
} ldmParams_t;
-typedef struct {
- U32 offset;
- U32 litLength;
- U32 matchLength;
-} rawSeq;
-
-typedef struct {
- rawSeq* seq; /* The start of the sequences */
- size_t pos; /* The position where reading stopped. <= size. */
- size_t size; /* The number of sequences. <= capacity. */
- size_t capacity; /* The capacity starting from `seq` pointer */
-} rawSeqStore_t;
-
typedef struct {
int collectSequences;
ZSTD_Sequence* seqStart;
From 35d9f488f5d3dd8918cba5e44d946ce5ce17339d Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 11:13:39 -0400
Subject: [PATCH 02/51] Modify codepath to use opt parser exclusively if the
compression level is high enough
---
lib/compress/zstd_ldm.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index dbfce3dce..c68693bd6 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -576,6 +576,13 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
/* Input positions */
BYTE const* ip = istart;
+ if (cParams->strategy >= ZSTD_btopt) {
+ size_t lastLLSize;
+ ms->ldmSeqStore = *rawSeqStore; /* copy current seqStore */
+ lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
+ return lastLLSize;
+ }
+
DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize);
assert(rawSeqStore->pos <= rawSeqStore->size);
assert(rawSeqStore->size <= rawSeqStore->capacity);
From aea61e3c91a4ea608fa2bbea4144f3ef1a2c6e43 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 11:22:50 -0400
Subject: [PATCH 03/51] Add ldm helper function declarations into opt parser
---
lib/compress/zstd_opt.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 5acc9e0b6..240b94cfa 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -764,6 +764,34 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
}
}
+/*-*******************************
+* LDM util functions
+*********************************/
+
+static int ldm_splitSequence() {
+
+}
+
+/* Returns 1 if the rest of the block is just LDM literals */
+static int ldm_getNextMatch() {
+ int ret = ldm_splitSequence();
+}
+
+/* Adds an LDM if it's long enough */
+static void ldm_maybeAddLdm() {
+
+}
+
+/* Updates the pos field in rawSeqStore */
+static void ldm_maybeUpdateSeqStoreReadPos() {
+
+}
+
+/* Wrapper function to call ldm functions as needed */
+static void ldm_handleLdm() {
+ int noMoreLdms = getNextMatch();
+}
+
/*-*******************************
* Optimal parser
From db7076103295969c53e42c4af964dde2a0b61613 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 11:24:29 -0400
Subject: [PATCH 04/51] Add callsites to appropriate locations in
..opt_generic()
---
lib/compress/zstd_opt.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 240b94cfa..3c3f22313 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -788,7 +788,7 @@ static void ldm_maybeUpdateSeqStoreReadPos() {
}
/* Wrapper function to call ldm functions as needed */
-static void ldm_handleLdm() {
+static void ldm_handleLdm(int* nbMatches) {
int noMoreLdms = getNextMatch();
}
@@ -861,6 +861,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
+ ldm_handleLdm(&nbMatches);
if (!nbMatches) { ip++; continue; }
/* initialize opt[0] */
@@ -975,6 +976,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
U32 matchNb;
+
+ ldm_handleLdm(&nbMatches);
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
continue;
From 634ab7830da587ece201563be9c6836ef50ce6e4 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 11:59:07 -0400
Subject: [PATCH 05/51] Flesh out required args for ldm_handleLdm()
---
lib/compress/zstd_opt.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 3c3f22313..0680e831b 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,12 +768,14 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM util functions
*********************************/
-static int ldm_splitSequence() {
+// The only function that can update pos (i think, for now)
+static int ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes) {
+ rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
}
/* Returns 1 if the rest of the block is just LDM literals */
-static int ldm_getNextMatch() {
+static int ldm_getNextMatch(U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32 remainingBytes) {
int ret = ldm_splitSequence();
}
@@ -788,8 +790,13 @@ static void ldm_maybeUpdateSeqStoreReadPos() {
}
/* Wrapper function to call ldm functions as needed */
-static void ldm_handleLdm(int* nbMatches) {
- int noMoreLdms = getNextMatch();
+static void ldm_handleLdm(ZSTD_match_t* matches, int* nbMatches,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32 currPosInBlock, U32 remainingBytes) {
+ if (currPosInBlock >= matchEndPosInBlock) {
+ int noMoreLdms = ldm_getNextMatch(matchStartPosInBlock, matchEndPosInBlock, remainingBytes);
+ }
+ ldm_maybeAddLdm(matches, currPosInBlock, matchStartPosInBlock, matchEndPosInBlock);
}
@@ -846,6 +853,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ZSTD_match_t* const matches = optStatePtr->matchTable;
ZSTD_optimal_t lastSequence;
+ U32 matchStartPosInBlock = 0;
+ U32 matchEndPosInBlock = 0;
+ ldm_getNextMatch(matchStartPosInBlock, matchEndPosInBlock, (U32)(iend - ip));
+
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
@@ -976,7 +987,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
U32 matchNb;
-
+
ldm_handleLdm(&nbMatches);
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
From 28c74bf591bf18800d292353b4e1cb0c4b378129 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 12:09:19 -0400
Subject: [PATCH 06/51] Implement basic splitSequence and skipSequence
functions
---
lib/compress/zstd_opt.c | 56 +++++++++++++++++++++++++++++++++++++----
1 file changed, 51 insertions(+), 5 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 0680e831b..6c8e8cc1d 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,15 +768,61 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM util functions
*********************************/
-// The only function that can update pos (i think, for now)
-static int ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes) {
- rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
+ while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
+ rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
+ if (srcSize <= seq->litLength) {
+ /* Skip past srcSize literals */
+ seq->litLength -= (U32)srcSize;
+ return;
+ }
+ srcSize -= seq->litLength;
+ seq->litLength = 0;
+ if (srcSize < seq->matchLength) {
+ /* Skip past the first srcSize of the match */
+ seq->matchLength -= (U32)srcSize;
+ if (seq->matchLength < minMatch) {
+ /* The match is too short, omit it */
+ if (rawSeqStore->pos + 1 < rawSeqStore->size) {
+ seq[1].litLength += seq[0].matchLength;
+ }
+ rawSeqStore->pos++;
+ }
+ return;
+ }
+ srcSize -= seq->matchLength;
+ seq->matchLength = 0;
+ rawSeqStore->pos++;
+ }
+}
+
+// The only function that can update pos (i think, for now)
+static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes) {
+ rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ /* No split */
+ if (remainingBytes >= currSeq.litLength + currSeq.matchLength) {
+ ldmSeqStore->pos++;
+ return currSeq;
+ }
+ /* Need a split */
+ if (remainingBytes <= currSeq.litLength) {
+ currSeq.offset = 0;
+ } else if (remainingBytes < currSeq.litLength + currSeq.matchLength) {
+ if (currSeq.matchLength < MINMATCH) {
+ currSeq.offset = 0;
+ }
+ }
+
+ ldm_skipSequences(ldmSeqStore, remainingBytes, MINMATCH);
+ return currSeq;
}
/* Returns 1 if the rest of the block is just LDM literals */
-static int ldm_getNextMatch(U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32 remainingBytes) {
- int ret = ldm_splitSequence();
+static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32 remainingBytes) {
+ int ret = ldm_splitSequence(ldmSeqStore, remainingBytes);
}
/* Adds an LDM if it's long enough */
From 84777059d24dc9a82b52bab7c68985e1b23ff3e3 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 12:16:15 -0400
Subject: [PATCH 07/51] Implement ldm_getNextMatch()
---
lib/compress/zstd_opt.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 6c8e8cc1d..c131e6f18 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -821,8 +821,20 @@ static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes)
/* Returns 1 if the rest of the block is just LDM literals */
static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32* matchOffset, U32 currPosInBlock,
U32 remainingBytes) {
- int ret = ldm_splitSequence(ldmSeqStore, remainingBytes);
+ rawSeq seq = ldm_splitSequence(ldmSeqStore, remainingBytes);
+ if (seq.offset == 0) {
+ // Don't use the LDM for the rest of the block (there is none)
+ *matchStartPosInBlock = UINT32_MAX;
+ *matchEndPosInBlock = UINT32_MAX;
+ return 1;
+ }
+
+ *matchStartPosInBlock = currPosInBlock + seq.litLength;
+ *matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
+ *matchOffset = seq.offset;
+ return 0;
}
/* Adds an LDM if it's long enough */
@@ -899,8 +911,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ZSTD_match_t* const matches = optStatePtr->matchTable;
ZSTD_optimal_t lastSequence;
- U32 matchStartPosInBlock = 0;
- U32 matchEndPosInBlock = 0;
+ U32 ldmStartPosInBlock = 0;
+ U32 ldmEndPosInBlock = 0;
+ U32 ldmOffset = 0;
ldm_getNextMatch(matchStartPosInBlock, matchEndPosInBlock, (U32)(iend - ip));
/* init */
From 766c4a8c2837addf5ede83c378e1e02982826caa Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 12:28:10 -0400
Subject: [PATCH 08/51] Implement part of ldm_maybeAddLdm()
---
lib/compress/zstd_opt.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index c131e6f18..9187edbef 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -838,8 +838,20 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
}
/* Adds an LDM if it's long enough */
-static void ldm_maybeAddLdm() {
+static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32 nbMatches,
+ U32 matchStartPosInBlock, U32 matchEndPosInBlock,
+ U32 matchOffset, U32 currPosInBlock) {
+ /* Check that current block position is not outside of the match */
+ if (currPosInBlock < matchStartPosInBlock || currPosInBlock >= matchEndPosInBlock)
+ return;
+ U32 posDiff = currPosInBlock - matchStartPosInBlock;
+ assert(posDiff < matchEndPosInBlock - matchStartPosInBlock);
+ U32 matchLengthAdjusted = matchEndPosInBlock - matchStartPosInBlock - posDiff;
+ U32 matchOffsetAdjusted = matchOffset + posDiff;
+ if (matchLengthAdjusted >= matches[nbMatches-1]) {
+
+ }
}
/* Updates the pos field in rawSeqStore */
@@ -849,12 +861,12 @@ static void ldm_maybeUpdateSeqStoreReadPos() {
/* Wrapper function to call ldm functions as needed */
static void ldm_handleLdm(ZSTD_match_t* matches, int* nbMatches,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
U32 currPosInBlock, U32 remainingBytes) {
if (currPosInBlock >= matchEndPosInBlock) {
int noMoreLdms = ldm_getNextMatch(matchStartPosInBlock, matchEndPosInBlock, remainingBytes);
}
- ldm_maybeAddLdm(matches, currPosInBlock, matchStartPosInBlock, matchEndPosInBlock);
+ ldm_maybeAddLdm(matches, *nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
}
From dd3dd199bb74e097e1b697bf20c1e42dd43ffe59 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 21:38:35 -0400
Subject: [PATCH 09/51] Get zstd to build with new functions and callsites, fix
arguments
---
lib/compress/zstd_opt.c | 41 +++++++++++++++++++++++++++++------------
1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 9187edbef..64d28b2fd 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -799,20 +799,25 @@ static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 co
// The only function that can update pos (i think, for now)
static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes) {
+ printf("Split Sequence with remaining = %u : ", remainingBytes);
rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
/* No split */
if (remainingBytes >= currSeq.litLength + currSeq.matchLength) {
+ printf("NO SPLIT\n", remainingBytes);
ldmSeqStore->pos++;
return currSeq;
}
/* Need a split */
if (remainingBytes <= currSeq.litLength) {
+ printf("SPLITTING: all remaining bytes were literals");
currSeq.offset = 0;
} else if (remainingBytes < currSeq.litLength + currSeq.matchLength) {
if (currSeq.matchLength < MINMATCH) {
+ printf("CurrSeq less than minmatch: all remaining bytes were literals");
currSeq.offset = 0;
}
}
+ printf("\n");
ldm_skipSequences(ldmSeqStore, remainingBytes, MINMATCH);
return currSeq;
@@ -838,7 +843,7 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
}
/* Adds an LDM if it's long enough */
-static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32 nbMatches,
+static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
U32 matchOffset, U32 currPosInBlock) {
/* Check that current block position is not outside of the match */
@@ -849,8 +854,10 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32 nbMatches,
U32 matchLengthAdjusted = matchEndPosInBlock - matchStartPosInBlock - posDiff;
U32 matchOffsetAdjusted = matchOffset + posDiff;
- if (matchLengthAdjusted >= matches[nbMatches-1]) {
-
+ if (matchLengthAdjusted >= matches[*nbMatches-1].len) {
+ matches[*nbMatches].len = matchLengthAdjusted;
+ matches[*nbMatches].off = matchOffsetAdjusted;
+ (*nbMatches)++;
}
}
@@ -860,13 +867,15 @@ static void ldm_maybeUpdateSeqStoreReadPos() {
}
/* Wrapper function to call ldm functions as needed */
-static void ldm_handleLdm(ZSTD_match_t* matches, int* nbMatches,
+static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
U32 currPosInBlock, U32 remainingBytes) {
- if (currPosInBlock >= matchEndPosInBlock) {
- int noMoreLdms = ldm_getNextMatch(matchStartPosInBlock, matchEndPosInBlock, remainingBytes);
+ if (currPosInBlock >= *matchEndPosInBlock) {
+ int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
+ matchEndPosInBlock, matchOffset,
+ currPosInBlock, remainingBytes);
}
- ldm_maybeAddLdm(matches, *nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
+ ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
}
@@ -926,7 +935,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmStartPosInBlock = 0;
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
- ldm_getNextMatch(matchStartPosInBlock, matchEndPosInBlock, (U32)(iend - ip));
+ ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend - ip));
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
@@ -942,8 +953,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
/* find first match */
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
- U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
- ldm_handleLdm(&nbMatches);
+ U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
+ ldm_handleLdm(&ms->ldmSeqStore, matches,
+ &nbMatches, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend-ip));
if (!nbMatches) { ip++; continue; }
/* initialize opt[0] */
@@ -1056,10 +1070,13 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
U32 const previousPrice = opt[cur].price;
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
- U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
+ U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
U32 matchNb;
- ldm_handleLdm(&nbMatches);
+ ldm_handleLdm(&ms->ldmSeqStore, matches,
+ &nbMatches, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(inr-istart), (U32)(iend-inr));
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
continue;
From 42395a70c2f70cc4d6c73ff3567943b62c2f246e Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 21:56:14 -0400
Subject: [PATCH 10/51] Add debug statements, flesh out functions
---
lib/compress/zstd_opt.c | 46 ++++++++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 64d28b2fd..0a17374ae 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -799,11 +799,12 @@ static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 co
// The only function that can update pos (i think, for now)
static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes) {
- printf("Split Sequence with remaining = %u : ", remainingBytes);
rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ printf("Current sequence: (of: %u, ml: %u, ll: %u)\n", currSeq.offset, currSeq.matchLength, currSeq.litLength);
+ printf("Split Sequence with remaining = %u : ", remainingBytes);
/* No split */
if (remainingBytes >= currSeq.litLength + currSeq.matchLength) {
- printf("NO SPLIT\n", remainingBytes);
+ printf("NO SPLIT\n");
ldmSeqStore->pos++;
return currSeq;
}
@@ -820,6 +821,7 @@ static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes)
printf("\n");
ldm_skipSequences(ldmSeqStore, remainingBytes, MINMATCH);
+ printf("Sequence final: (of: %u, ml: %u, ll: %u)\n", currSeq.offset, currSeq.matchLength, currSeq.litLength);
return currSeq;
}
@@ -850,22 +852,20 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
if (currPosInBlock < matchStartPosInBlock || currPosInBlock >= matchEndPosInBlock)
return;
U32 posDiff = currPosInBlock - matchStartPosInBlock;
+ if (posDiff > 0)
+ return; // dont deal with extra ldms for now
assert(posDiff < matchEndPosInBlock - matchStartPosInBlock);
U32 matchLengthAdjusted = matchEndPosInBlock - matchStartPosInBlock - posDiff;
U32 matchOffsetAdjusted = matchOffset + posDiff;
if (matchLengthAdjusted >= matches[*nbMatches-1].len) {
+ printf("Adding LDM with of: %u, ml: %u\n", matchOffsetAdjusted, matchLengthAdjusted);
matches[*nbMatches].len = matchLengthAdjusted;
matches[*nbMatches].off = matchOffsetAdjusted;
(*nbMatches)++;
}
}
-/* Updates the pos field in rawSeqStore */
-static void ldm_maybeUpdateSeqStoreReadPos() {
-
-}
-
/* Wrapper function to call ldm functions as needed */
static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
@@ -875,7 +875,8 @@ static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32
matchEndPosInBlock, matchOffset,
currPosInBlock, remainingBytes);
}
- ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
+ if (ldmSeqStore->pos <= ldmSeqStore->size)
+ ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
}
@@ -935,9 +936,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmStartPosInBlock = 0;
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
- ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend - ip));
+ if (ms->ldmSeqStore.size != 0) {
+ ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend - ip));
+ }
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
@@ -954,10 +957,12 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
- ldm_handleLdm(&ms->ldmSeqStore, matches,
- &nbMatches, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend-ip));
+ if (ms->ldmSeqStore.size != 0) {
+ ldm_handleLdm(&ms->ldmSeqStore, matches,
+ &nbMatches, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend-ip));
+ }
if (!nbMatches) { ip++; continue; }
/* initialize opt[0] */
@@ -1073,10 +1078,13 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
U32 matchNb;
- ldm_handleLdm(&ms->ldmSeqStore, matches,
- &nbMatches, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(inr-istart), (U32)(iend-inr));
+
+ if (ms->ldmSeqStore.size != 0) {
+ ldm_handleLdm(&ms->ldmSeqStore, matches,
+ &nbMatches, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(inr-istart), (U32)(iend-inr));
+ }
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
continue;
From 84009a076ad4f23de5eef76a84ac34be47ae5fef Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sat, 26 Sep 2020 22:14:21 -0400
Subject: [PATCH 11/51] Add re-copying of ldmSeqStore after processing
---
lib/compress/zstd_ldm.c | 1 +
lib/compress/zstd_opt.c | 22 +++++++++++++---------
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index c68693bd6..42e6aa2d8 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -580,6 +580,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
size_t lastLLSize;
ms->ldmSeqStore = *rawSeqStore; /* copy current seqStore */
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
+ rawSeqStore->pos = ms->ldmSeqStore.pos;
return lastLLSize;
}
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 0a17374ae..f938cce8e 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -806,6 +806,7 @@ static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes)
if (remainingBytes >= currSeq.litLength + currSeq.matchLength) {
printf("NO SPLIT\n");
ldmSeqStore->pos++;
+ printf("pos is now: %u\n", ldmSeqStore->pos);
return currSeq;
}
/* Need a split */
@@ -831,8 +832,9 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
U32* matchOffset, U32 currPosInBlock,
U32 remainingBytes) {
rawSeq seq = ldm_splitSequence(ldmSeqStore, remainingBytes);
- if (seq.offset == 0) {
+ if (seq.offset == 0 || ldmSeqStore->pos > ldmSeqStore->size) {
// Don't use the LDM for the rest of the block (there is none)
+ printf("No ldm left in the block\n");
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
return 1;
@@ -841,6 +843,7 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
*matchStartPosInBlock = currPosInBlock + seq.litLength;
*matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
*matchOffset = seq.offset;
+ printf("New match range in block is: (%u, %u) with of: %u where currPosInBlock: %u\n", *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
return 0;
}
@@ -860,6 +863,7 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
if (matchLengthAdjusted >= matches[*nbMatches-1].len) {
printf("Adding LDM with of: %u, ml: %u\n", matchOffsetAdjusted, matchLengthAdjusted);
+ /* Add sifting */
matches[*nbMatches].len = matchLengthAdjusted;
matches[*nbMatches].off = matchOffsetAdjusted;
(*nbMatches)++;
@@ -875,8 +879,7 @@ static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32
matchEndPosInBlock, matchOffset,
currPosInBlock, remainingBytes);
}
- if (ldmSeqStore->pos <= ldmSeqStore->size)
- ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
+ ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
}
@@ -936,11 +939,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmStartPosInBlock = 0;
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
- if (ms->ldmSeqStore.size != 0) {
- ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend - ip));
- }
+
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
@@ -948,7 +947,12 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
assert(optLevel <= 2);
ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
ip += (ip==prefixStart);
-
+
+ if (ms->ldmSeqStore.size != 0) {
+ ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend - ip));
+ }
/* Match Loop */
while (ip < ilimit) {
U32 cur, last_pos = 0;
From f8ce7cabc3c0eb416c6f31e31c431e9910bf2f44 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sun, 27 Sep 2020 13:02:46 -0400
Subject: [PATCH 12/51] Added more debugging
---
lib/compress/zstd_opt.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index f938cce8e..8852fcbe5 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -850,7 +850,7 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
/* Adds an LDM if it's long enough */
static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
- U32 matchOffset, U32 currPosInBlock) {
+ U32 matchOffset, U32 currPosInBlock, U32 curr) {
/* Check that current block position is not outside of the match */
if (currPosInBlock < matchStartPosInBlock || currPosInBlock >= matchEndPosInBlock)
return;
@@ -862,10 +862,10 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchOffsetAdjusted = matchOffset + posDiff;
if (matchLengthAdjusted >= matches[*nbMatches-1].len) {
- printf("Adding LDM with of: %u, ml: %u\n", matchOffsetAdjusted, matchLengthAdjusted);
+ printf("Adding LDM with of: %u, ml: %u @ currposinblock: %u, current: %u\n", matchOffsetAdjusted, matchLengthAdjusted, currPosInBlock, curr);
/* Add sifting */
matches[*nbMatches].len = matchLengthAdjusted;
- matches[*nbMatches].off = matchOffsetAdjusted;
+ matches[*nbMatches].off = matchOffsetAdjusted + ZSTD_REP_MOVE;
(*nbMatches)++;
}
}
@@ -873,13 +873,13 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
/* Wrapper function to call ldm functions as needed */
static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
- U32 currPosInBlock, U32 remainingBytes) {
+ U32 currPosInBlock, U32 remainingBytes, U32 curr) {
if (currPosInBlock >= *matchEndPosInBlock) {
int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
matchEndPosInBlock, matchOffset,
currPosInBlock, remainingBytes);
}
- ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
+ ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, curr);
}
@@ -947,12 +947,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
assert(optLevel <= 2);
ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
ip += (ip==prefixStart);
-
- if (ms->ldmSeqStore.size != 0) {
- ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend - ip));
- }
+
/* Match Loop */
while (ip < ilimit) {
U32 cur, last_pos = 0;
@@ -963,9 +958,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
if (ms->ldmSeqStore.size != 0) {
ldm_handleLdm(&ms->ldmSeqStore, matches,
- &nbMatches, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend-ip));
+ &nbMatches, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend - ip), (U32)(ip-base));
}
if (!nbMatches) { ip++; continue; }
@@ -1087,7 +1082,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ldm_handleLdm(&ms->ldmSeqStore, matches,
&nbMatches, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
- (U32)(inr-istart), (U32)(iend-inr));
+ (U32)(inr-istart), (U32)(iend-inr), (U32)(ip-base));
}
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
From 5df9b5e05fdd0b85b3d89e6524c49e8a1778ed38 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sun, 27 Sep 2020 13:19:54 -0400
Subject: [PATCH 13/51] Add initial getNextMatch() in opt parser
---
lib/compress/zstd_opt.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 8852fcbe5..4ffcefe37 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -940,7 +940,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
-
+ if (ms->ldmSeqStore.size != 0) {
+ ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset, (U32)(ip-istart), (U32)(iend-ip));
+ }
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
From f57c7e6bbfc1e61d92ba31d7ecf25d35744591d9 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sun, 27 Sep 2020 13:25:27 -0400
Subject: [PATCH 14/51] Add base adjustment correction
---
lib/compress/zstd_ldm.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 42e6aa2d8..5f44ce78a 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -579,8 +579,15 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
if (cParams->strategy >= ZSTD_btopt) {
size_t lastLLSize;
ms->ldmSeqStore = *rawSeqStore; /* copy current seqStore */
+ const BYTE* const prevBase = (BYTE const*)ms->window.base;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
rawSeqStore->pos = ms->ldmSeqStore.pos;
+ ms->ldmSeqStore = *rawSeqStore;
+ if (prevBase != ms->window.base) {
+ int baseDiff = (int)(prevBase - ms->window.base);
+ printf("Bases were different, adjusting, diff = %d\n", baseDiff);
+ rawSeqStore->seq[rawSeqStore->pos].litLength += baseDiff;
+ }
return lastLLSize;
}
From c8b8572b38f9d2c52c57a6a4d03381fb39e3ba7c Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sun, 27 Sep 2020 20:00:14 -0400
Subject: [PATCH 15/51] Adjustments to no longer segfault on nci
---
lib/compress/zstd_compress.c | 2 +-
lib/compress/zstd_opt.c | 56 +++++++++++++++++++++++++++---------
2 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index b6edba207..037b5360a 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2336,7 +2336,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
if (curr > ms->nextToUpdate + 384)
ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
}
-
+ printf("--NEW BLOCK--\n");
/* select and store sequences */
{ ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
size_t lastLLSize;
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 4ffcefe37..c642de4da 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,6 +768,19 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM util functions
*********************************/
+static void ldm_skipOvershotBytes(rawSeqStore_t* rawSeqStore, size_t posOvershoot) {
+ if (rawSeqStore->seq[rawSeqStore->pos].matchLength > posOvershoot) {
+ rawSeqStore->seq[rawSeqStore->pos].matchLength -= posOvershoot;
+ return;
+ } else {
+ rawSeqStore->seq[rawSeqStore->pos].matchLength = 0;
+ rawSeqStore->pos++;
+ }
+
+ while (posOvershoot > 0 && rawSeqStore->pos < rawSeqStore->size) {
+
+ }
+}
static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
@@ -780,8 +793,10 @@ static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 co
srcSize -= seq->litLength;
seq->litLength = 0;
if (srcSize < seq->matchLength) {
+ printf("Splitting match: ml curr: %u ", seq->matchLength);
/* Skip past the first srcSize of the match */
seq->matchLength -= (U32)srcSize;
+ printf("ml in store left: %u ", seq->matchLength);
if (seq->matchLength < minMatch) {
/* The match is too short, omit it */
if (rawSeqStore->pos + 1 < rawSeqStore->size) {
@@ -818,6 +833,7 @@ static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes)
printf("CurrSeq less than minmatch: all remaining bytes were literals");
currSeq.offset = 0;
}
+ currSeq.matchLength = remainingBytes - currSeq.litLength;
}
printf("\n");
@@ -830,7 +846,7 @@ static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes)
static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
U32* matchStartPosInBlock, U32* matchEndPosInBlock,
U32* matchOffset, U32 currPosInBlock,
- U32 remainingBytes) {
+ U32 remainingBytes, U32 sbi) {
rawSeq seq = ldm_splitSequence(ldmSeqStore, remainingBytes);
if (seq.offset == 0 || ldmSeqStore->pos > ldmSeqStore->size) {
// Don't use the LDM for the rest of the block (there is none)
@@ -843,14 +859,14 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
*matchStartPosInBlock = currPosInBlock + seq.litLength;
*matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
*matchOffset = seq.offset;
- printf("New match range in block is: (%u, %u) with of: %u where currPosInBlock: %u\n", *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
+ printf("New match range in block is: (%u, %u) with of: %u where currPosInBlock: %u at adjusted absolute range: %u, %u\n", *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, *matchStartPosInBlock+sbi, *matchEndPosInBlock+sbi);
return 0;
}
/* Adds an LDM if it's long enough */
static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
- U32 matchOffset, U32 currPosInBlock, U32 curr) {
+ U32 matchOffset, U32 currPosInBlock, U32 curr, U32 sbi) {
/* Check that current block position is not outside of the match */
if (currPosInBlock < matchStartPosInBlock || currPosInBlock >= matchEndPosInBlock)
return;
@@ -861,25 +877,37 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchLengthAdjusted = matchEndPosInBlock - matchStartPosInBlock - posDiff;
U32 matchOffsetAdjusted = matchOffset + posDiff;
- if (matchLengthAdjusted >= matches[*nbMatches-1].len) {
- printf("Adding LDM with of: %u, ml: %u @ currposinblock: %u, current: %u\n", matchOffsetAdjusted, matchLengthAdjusted, currPosInBlock, curr);
+ if (*nbMatches == 0 || matchLengthAdjusted >= matches[*nbMatches-1].len) {
+ printf("Adding LDM with of: %u, ml: %u @ currposinblock: %u, current: %u, currposinblock+sbi: %u\n", matchOffsetAdjusted, matchLengthAdjusted, currPosInBlock, curr, currPosInBlock+sbi);
/* Add sifting */
matches[*nbMatches].len = matchLengthAdjusted;
matches[*nbMatches].off = matchOffsetAdjusted + ZSTD_REP_MOVE;
(*nbMatches)++;
+ } else {
+ printf("too small ldm\n");
}
}
/* Wrapper function to call ldm functions as needed */
static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
- U32 currPosInBlock, U32 remainingBytes, U32 curr) {
+ U32 currPosInBlock, U32 remainingBytes, U32 curr, U32 sbi) {
if (currPosInBlock >= *matchEndPosInBlock) {
- int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
- matchEndPosInBlock, matchOffset,
- currPosInBlock, remainingBytes);
+ printf("Went over match boundary: currPosInBlock: %u, %matchEndPosInBlock: %u\n", currPosInBlock, *matchEndPosInBlock);
+ if (currPosInBlock > *matchEndPosInBlock) {
+ U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
+ printf("Overshot position by: %u\n", posOvershoot);
+ ldm_skipSequences(ldmSeqStore, posOvershoot, MINMATCH);
+ int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
+ matchEndPosInBlock, matchOffset,
+ matchEndPosInBlock, remainingBytes, sbi);
+ } else {
+ int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
+ matchEndPosInBlock, matchOffset,
+ currPosInBlock, remainingBytes, sbi);
+ }
}
- ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, curr);
+ ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, curr, sbi);
}
@@ -931,6 +959,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
U32 nextToUpdate3 = ms->nextToUpdate;
+ U32 const sbi = (U32)(istart-base);
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
ZSTD_match_t* const matches = optStatePtr->matchTable;
@@ -940,9 +969,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
+ printf("SBI for this block: %u\n", sbi);
if (ms->ldmSeqStore.size != 0) {
ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset, (U32)(ip-istart), (U32)(iend-ip));
+ &ldmEndPosInBlock, &ldmOffset, (U32)(ip-istart), (U32)(iend-ip), sbi);
}
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
@@ -963,7 +993,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ldm_handleLdm(&ms->ldmSeqStore, matches,
&nbMatches, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend - ip), (U32)(ip-base));
+ (U32)(ip-istart), (U32)(iend - ip), (U32)(ip-base), sbi);
}
if (!nbMatches) { ip++; continue; }
@@ -1085,7 +1115,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ldm_handleLdm(&ms->ldmSeqStore, matches,
&nbMatches, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
- (U32)(inr-istart), (U32)(iend-inr), (U32)(ip-base));
+ (U32)(inr-istart), (U32)(iend-inr), (U32)(inr-base), sbi);
}
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
From 9c3c7cd20e9cff361eb78fa4dd097e57929d542e Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sun, 27 Sep 2020 20:06:44 -0400
Subject: [PATCH 16/51] Fix function argument to getNextMatch()
---
lib/compress/zstd_opt.c | 66 +++++++++++++++++++++++++++++++++--------
1 file changed, 53 insertions(+), 13 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index c642de4da..f1e39d7c3 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,7 +768,14 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM util functions
*********************************/
-static void ldm_skipOvershotBytes(rawSeqStore_t* rawSeqStore, size_t posOvershoot) {
+/*
+static void ldm_skipOvershotBytes(rawSeqStore_t* rawSeqStore, U32 bytesOvershot) {
+ while (bytesOvershot > 0 && rawSeqStore->pos < rawSeqStore->size) {
+ rawSeq seq = rawSeqStore->seq[rawSeqStore->pos];
+ if (bytesOvershot <= seq.litLength) {
+ seq->litLength -= bytesOvershot;
+ }
+ }
if (rawSeqStore->seq[rawSeqStore->pos].matchLength > posOvershoot) {
rawSeqStore->seq[rawSeqStore->pos].matchLength -= posOvershoot;
return;
@@ -780,14 +787,17 @@ static void ldm_skipOvershotBytes(rawSeqStore_t* rawSeqStore, size_t posOvershoo
while (posOvershoot > 0 && rawSeqStore->pos < rawSeqStore->size) {
}
-}
+}*/
static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
+ printf("ldm_skipSequences(): %u remaining\n", srcSize);
rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
+ printf("ldm_skipSequences(): before: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
if (srcSize <= seq->litLength) {
/* Skip past srcSize literals */
seq->litLength -= (U32)srcSize;
+ printf("ldm_skipSequences(): final: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
return;
}
srcSize -= seq->litLength;
@@ -804,6 +814,7 @@ static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 co
}
rawSeqStore->pos++;
}
+ printf("ldm_skipSequences(): final: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
return;
}
srcSize -= seq->matchLength;
@@ -874,17 +885,46 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
if (posDiff > 0)
return; // dont deal with extra ldms for now
assert(posDiff < matchEndPosInBlock - matchStartPosInBlock);
- U32 matchLengthAdjusted = matchEndPosInBlock - matchStartPosInBlock - posDiff;
- U32 matchOffsetAdjusted = matchOffset + posDiff;
+ U32 candidateMatchLength = matchEndPosInBlock - matchStartPosInBlock - posDiff;
+ U32 candidateOffCode = matchOffset + posDiff + ZSTD_REP_MOVE;
- if (*nbMatches == 0 || matchLengthAdjusted >= matches[*nbMatches-1].len) {
- printf("Adding LDM with of: %u, ml: %u @ currposinblock: %u, current: %u, currposinblock+sbi: %u\n", matchOffsetAdjusted, matchLengthAdjusted, currPosInBlock, curr, currPosInBlock+sbi);
- /* Add sifting */
- matches[*nbMatches].len = matchLengthAdjusted;
- matches[*nbMatches].off = matchOffsetAdjusted + ZSTD_REP_MOVE;
- (*nbMatches)++;
- } else {
- printf("too small ldm\n");
+ if ((*nbMatches == 0 || candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
+ printf("large enough, adding\n");
+ /*matches[*nbMatches].len = candidateMatchLength;
+ matches[*nbMatches].off = candidateOffCode;
+ (*nbMatches)++;*/
+
+ if (*nbMatches == 0) {
+ matches[*nbMatches].len = candidateMatchLength;
+ matches[*nbMatches].off = candidateOffCode;
+ (*nbMatches)++;
+ } else {
+ if (candidateMatchLength == matches[*nbMatches-1].len) {
+ U32 candidateMatchIdx = *nbMatches;
+ matches[*nbMatches].len = candidateMatchLength;
+ matches[*nbMatches].off = candidateOffCode;
+ printf("Sifting...: idx: %u, len: %u, off: %u\n", candidateMatchIdx, candidateMatchLength, candidateOffCode);
+ //printf("Current best is...: idx: %u, len: %u, off: %u\n", *nbMatches-1, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ if (candidateOffCode != matches[*nbMatches].off)
+ printf("DIFF: ldm: (len: %u, off: %u), best: (len: %u, off: %u)\n", candidateMatchLength, candidateOffCode, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ //printf("Current best is...: idx: %u, len: %u, off: %u\n", *nbMatches-1, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ while (candidateMatchIdx > 0 &&
+ matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
+ matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
+ //printf("Compared to: idx: %u, len: %u, off: %u", candidateMatchIdx - 1, matches[candidateMatchIdx - 1].len, matches[candidateMatchIdx - 1].off);
+ ZSTD_match_t tmp = matches[candidateMatchIdx - 1];
+ matches[candidateMatchIdx - 1] = matches[candidateMatchIdx];
+ matches[candidateMatchIdx] = tmp;
+ --candidateMatchIdx;
+ }
+ (*nbMatches)++;
+ } else {
+ printf("MATCHDIFF: ldm: (len: %u, off: %u), best: (len: %u, off: %u)\n", candidateMatchLength, candidateOffCode, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ matches[*nbMatches].len = candidateMatchLength;
+ matches[*nbMatches].off = candidateOffCode;
+ (*nbMatches)++;
+ }
+ }
}
}
@@ -900,7 +940,7 @@ static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32
ldm_skipSequences(ldmSeqStore, posOvershoot, MINMATCH);
int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
matchEndPosInBlock, matchOffset,
- matchEndPosInBlock, remainingBytes, sbi);
+ currPosInBlock, remainingBytes, sbi);
} else {
int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
matchEndPosInBlock, matchOffset,
From a2f2b58d04956d79a88fa4cafabda52a995952ca Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Mon, 28 Sep 2020 10:29:17 -0400
Subject: [PATCH 17/51] Add a function ldm_voidSequences()
---
lib/compress/zstd_opt.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index f1e39d7c3..70ec8a941 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -789,6 +789,15 @@ static void ldm_skipOvershotBytes(rawSeqStore_t* rawSeqStore, U32 bytesOvershot)
}
}*/
+
+static void ldm_voidSequences(rawSeqStore_t* ldmSeqStore, U32 overshotBytes) {
+ U32 posAdjustment;
+ U32 bytesAdjustment;
+ while (overshotBytes > 0 && ldmSeqStore->pos < ldmSeqStore->size) {
+
+ }
+}
+
static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
printf("ldm_skipSequences(): %u remaining\n", srcSize);
From 28394b64f242dd6efcdda2dd3f4b8d926933fd97 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Mon, 28 Sep 2020 17:58:23 -0400
Subject: [PATCH 18/51] Add proper bounds check on adding ldms
---
lib/compress/zstd_ldm.c | 8 ++++++++
lib/compress/zstd_opt.c | 35 ++++++++++++++++++-----------------
2 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 5f44ce78a..e31c6838d 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -562,6 +562,13 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
return sequence;
}
+static void printSeqStore(rawSeqStore_t* rawSeqStore) {
+ printf("rawSeqStore: pos: %zu, bytesDiscarded: %zu\n", rawSeqStore->pos);
+ for (int i = 0; i < rawSeqStore->size; ++i) {
+ printf("(of:%u ml:%u ll: %u)\n", rawSeqStore->seq[i].offset, rawSeqStore->seq[i].matchLength, rawSeqStore->seq[i].litLength);
+ }
+}
+
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize)
@@ -578,6 +585,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
if (cParams->strategy >= ZSTD_btopt) {
size_t lastLLSize;
+ printSeqStore(rawSeqStore);
ms->ldmSeqStore = *rawSeqStore; /* copy current seqStore */
const BYTE* const prevBase = (BYTE const*)ms->window.base;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 70ec8a941..bc6436a1a 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -828,6 +828,7 @@ static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 co
}
srcSize -= seq->matchLength;
seq->matchLength = 0;
+ printf("ldm_skipSequences(): final: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
rawSeqStore->pos++;
}
}
@@ -867,10 +868,17 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
U32* matchStartPosInBlock, U32* matchEndPosInBlock,
U32* matchOffset, U32 currPosInBlock,
U32 remainingBytes, U32 sbi) {
- rawSeq seq = ldm_splitSequence(ldmSeqStore, remainingBytes);
- if (seq.offset == 0 || ldmSeqStore->pos > ldmSeqStore->size) {
+ if (ldmSeqStore->pos >= ldmSeqStore->size) {
// Don't use the LDM for the rest of the block (there is none)
- printf("No ldm left in the block\n");
+ printf("No ldm left in the block, pos max reached\n");
+ *matchStartPosInBlock = UINT32_MAX;
+ *matchEndPosInBlock = UINT32_MAX;
+ return 1;
+ }
+ rawSeq seq = ldm_splitSequence(ldmSeqStore, remainingBytes);
+ if (seq.offset == 0) {
+ // Don't use the LDM for the rest of the block (there is none)
+ printf("No ldm left in the block, offset = 0\n");
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
return 1;
@@ -898,11 +906,8 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 candidateOffCode = matchOffset + posDiff + ZSTD_REP_MOVE;
if ((*nbMatches == 0 || candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
- printf("large enough, adding\n");
- /*matches[*nbMatches].len = candidateMatchLength;
- matches[*nbMatches].off = candidateOffCode;
- (*nbMatches)++;*/
-
+ printf("large enough: curr: %u currposinblock: %u (ofcode: %u, ml: %u)\n", curr, currPosInBlock, candidateOffCode, candidateMatchLength);
+
if (*nbMatches == 0) {
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
@@ -947,14 +952,10 @@ static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32
U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
printf("Overshot position by: %u\n", posOvershoot);
ldm_skipSequences(ldmSeqStore, posOvershoot, MINMATCH);
- int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
- matchEndPosInBlock, matchOffset,
- currPosInBlock, remainingBytes, sbi);
- } else {
- int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
- matchEndPosInBlock, matchOffset,
- currPosInBlock, remainingBytes, sbi);
- }
+ }
+ int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
+ matchEndPosInBlock, matchOffset,
+ currPosInBlock, remainingBytes, sbi);
}
ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, curr, sbi);
}
@@ -1018,7 +1019,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
- printf("SBI for this block: %u\n", sbi);
+ printf("SBI for this block: %u, base: %u\n", sbi, base);
if (ms->ldmSeqStore.size != 0) {
ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset, (U32)(ip-istart), (U32)(iend-ip), sbi);
From 6ccd97fc96d4769fc4edcbd3dfdc66f38e214d2c Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Tue, 29 Sep 2020 12:12:58 -0400
Subject: [PATCH 19/51] Fixed end of match boundary update issues
---
lib/compress/zstd_compress.c | 4 +-
lib/compress/zstd_compress_internal.h | 1 +
lib/compress/zstd_ldm.c | 17 ++---
lib/compress/zstd_opt.c | 104 +++++++++++++++-----------
lib/compress/zstdmt_compress.c | 2 +-
5 files changed, 72 insertions(+), 56 deletions(-)
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 037b5360a..3c80ab860 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2336,7 +2336,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
if (curr > ms->nextToUpdate + 384)
ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
}
- printf("--NEW BLOCK--\n");
+ //printf("--NEW BLOCK--\n");
/* select and store sequences */
{ ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
size_t lastLLSize;
@@ -2354,7 +2354,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
src, srcSize);
assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
} else if (zc->appliedParams.ldmParams.enableLdm) {
- rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0};
+ rawSeqStore_t ldmSeqStore = {NULL, NULL, 0, 0, 0};
ldmSeqStore.seq = zc->ldmSequences;
ldmSeqStore.capacity = zc->maxNbLdmSequences;
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index 524cbb025..53c20b12c 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -94,6 +94,7 @@ typedef struct {
typedef struct {
rawSeq* seq; /* The start of the sequences */
+ BYTE const* base;
size_t pos; /* The position where reading stopped. <= size. */
size_t size; /* The number of sequences. <= capacity. */
size_t capacity; /* The capacity starting from `seq` pointer */
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index e31c6838d..9fcb9fc29 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -563,9 +563,9 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
}
static void printSeqStore(rawSeqStore_t* rawSeqStore) {
- printf("rawSeqStore: pos: %zu, bytesDiscarded: %zu\n", rawSeqStore->pos);
+ printf("rawSeqStore: pos: %zu\n", rawSeqStore->pos);
for (int i = 0; i < rawSeqStore->size; ++i) {
- printf("(of:%u ml:%u ll: %u)\n", rawSeqStore->seq[i].offset, rawSeqStore->seq[i].matchLength, rawSeqStore->seq[i].litLength);
+ printf("pos %d (of:%u ml:%u ll: %u)\n", i, rawSeqStore->seq[i].offset, rawSeqStore->seq[i].matchLength, rawSeqStore->seq[i].litLength);
}
}
@@ -582,20 +582,19 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
BYTE const* const iend = istart + srcSize;
/* Input positions */
BYTE const* ip = istart;
-
+ //printSeqStore(rawSeqStore);
if (cParams->strategy >= ZSTD_btopt) {
size_t lastLLSize;
- printSeqStore(rawSeqStore);
+ //printSeqStore(rawSeqStore);
ms->ldmSeqStore = *rawSeqStore; /* copy current seqStore */
- const BYTE* const prevBase = (BYTE const*)ms->window.base;
+ ms->ldmSeqStore.base = ms->window.base;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
- rawSeqStore->pos = ms->ldmSeqStore.pos;
- ms->ldmSeqStore = *rawSeqStore;
- if (prevBase != ms->window.base) {
+ *rawSeqStore = ms->ldmSeqStore;
+ /*if (prevBase != ms->window.base) {
int baseDiff = (int)(prevBase - ms->window.base);
printf("Bases were different, adjusting, diff = %d\n", baseDiff);
rawSeqStore->seq[rawSeqStore->pos].litLength += baseDiff;
- }
+ }*/
return lastLLSize;
}
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index bc6436a1a..05fa4cae7 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -800,85 +800,85 @@ static void ldm_voidSequences(rawSeqStore_t* ldmSeqStore, U32 overshotBytes) {
static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
- printf("ldm_skipSequences(): %u remaining\n", srcSize);
+ ////printf("ldm_skipSequences(): %u remaining\n", srcSize);
rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
- printf("ldm_skipSequences(): before: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
+ ////printf("ldm_skipSequences(): before: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
if (srcSize <= seq->litLength) {
/* Skip past srcSize literals */
seq->litLength -= (U32)srcSize;
- printf("ldm_skipSequences(): final: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
+ ////printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
return;
}
srcSize -= seq->litLength;
seq->litLength = 0;
if (srcSize < seq->matchLength) {
- printf("Splitting match: ml curr: %u ", seq->matchLength);
+ ////printf("Splitting match: ml curr: %u ", seq->matchLength);
/* Skip past the first srcSize of the match */
seq->matchLength -= (U32)srcSize;
- printf("ml in store left: %u ", seq->matchLength);
- if (seq->matchLength < minMatch) {
- /* The match is too short, omit it */
+ ////printf("ml in store left: %u ", seq->matchLength);
+ /*if (seq->matchLength < minMatch) {
+ // The match is too short, omit it
if (rawSeqStore->pos + 1 < rawSeqStore->size) {
seq[1].litLength += seq[0].matchLength;
}
rawSeqStore->pos++;
- }
- printf("ldm_skipSequences(): final: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
+ }*/
+ //printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
return;
}
srcSize -= seq->matchLength;
seq->matchLength = 0;
- printf("ldm_skipSequences(): final: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
+ //printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
rawSeqStore->pos++;
}
}
// The only function that can update pos (i think, for now)
-static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32 remainingBytes) {
+static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesConsumed, U32 remainingBytes) {
rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- printf("Current sequence: (of: %u, ml: %u, ll: %u)\n", currSeq.offset, currSeq.matchLength, currSeq.litLength);
- printf("Split Sequence with remaining = %u : ", remainingBytes);
+ //printf("ldm_splitSequence(): Current sequence: (of: %u, ml: %u, ll: %u) - remaining: %u\n", currSeq.offset, currSeq.matchLength, currSeq.litLength, remainingBytes);
/* No split */
if (remainingBytes >= currSeq.litLength + currSeq.matchLength) {
- printf("NO SPLIT\n");
+ ////printf("NO SPLIT\n");
+ *ldmSeqStoreBytesConsumed += currSeq.litLength + currSeq.matchLength;
ldmSeqStore->pos++;
- printf("pos is now: %u\n", ldmSeqStore->pos);
+ ////printf("pos is now: %u\n", ldmSeqStore->pos);
return currSeq;
}
/* Need a split */
if (remainingBytes <= currSeq.litLength) {
- printf("SPLITTING: all remaining bytes were literals");
+ ////printf("SPLITTING: all remaining bytes were literals");
currSeq.offset = 0;
} else if (remainingBytes < currSeq.litLength + currSeq.matchLength) {
- if (currSeq.matchLength < MINMATCH) {
- printf("CurrSeq less than minmatch: all remaining bytes were literals");
+ /*if (currSeq.matchLength < MINMATCH) {
+ ////printf("CurrSeq less than minmatch: all remaining bytes were literals");
currSeq.offset = 0;
- }
+ }*/
currSeq.matchLength = remainingBytes - currSeq.litLength;
}
- printf("\n");
-
+ ////printf("\n");
+ *ldmSeqStoreBytesConsumed += remainingBytes;
ldm_skipSequences(ldmSeqStore, remainingBytes, MINMATCH);
- printf("Sequence final: (of: %u, ml: %u, ll: %u)\n", currSeq.offset, currSeq.matchLength, currSeq.litLength);
+ //printf("ldm_splitSequence(): Sequence final: (of: %u, ml: %u, ll: %u)\n", currSeq.offset, currSeq.matchLength, currSeq.litLength);
return currSeq;
}
/* Returns 1 if the rest of the block is just LDM literals */
-static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
+static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesConsumed,
U32* matchStartPosInBlock, U32* matchEndPosInBlock,
U32* matchOffset, U32 currPosInBlock,
U32 remainingBytes, U32 sbi) {
if (ldmSeqStore->pos >= ldmSeqStore->size) {
// Don't use the LDM for the rest of the block (there is none)
- printf("No ldm left in the block, pos max reached\n");
+ //printf("No ldm left in the block, pos max reached\n");
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
return 1;
}
- rawSeq seq = ldm_splitSequence(ldmSeqStore, remainingBytes);
+ rawSeq seq = ldm_splitSequence(ldmSeqStore, ldmSeqStoreBytesConsumed, remainingBytes);
if (seq.offset == 0) {
// Don't use the LDM for the rest of the block (there is none)
- printf("No ldm left in the block, offset = 0\n");
+ ////printf("No ldm left in the block, offset = 0\n");
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
return 1;
@@ -887,14 +887,14 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
*matchStartPosInBlock = currPosInBlock + seq.litLength;
*matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
*matchOffset = seq.offset;
- printf("New match range in block is: (%u, %u) with of: %u where currPosInBlock: %u at adjusted absolute range: %u, %u\n", *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, *matchStartPosInBlock+sbi, *matchEndPosInBlock+sbi);
+ //printf("New match range in block is: (%u, %u) with of: %u where currPosInBlock: %u at adjusted absolute range: %u, %u\n", *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, *matchStartPosInBlock+sbi, *matchEndPosInBlock+sbi);
return 0;
}
/* Adds an LDM if it's long enough */
static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
- U32 matchOffset, U32 currPosInBlock, U32 curr, U32 sbi) {
+ U32 matchOffset, U32 currPosInBlock, U32 curr, U32 sbi, rawSeqStore_t* rawSeqStore) {
/* Check that current block position is not outside of the match */
if (currPosInBlock < matchStartPosInBlock || currPosInBlock >= matchEndPosInBlock)
return;
@@ -906,7 +906,8 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 candidateOffCode = matchOffset + posDiff + ZSTD_REP_MOVE;
if ((*nbMatches == 0 || candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
- printf("large enough: curr: %u currposinblock: %u (ofcode: %u, ml: %u)\n", curr, currPosInBlock, candidateOffCode, candidateMatchLength);
+ //printf("large enough: curr: %u currposinblock: %u (ofcode: %u, ml: %u) - range: (%u, %u) - (of: %u ml: %u ll: %u) @ pos: %u - \n",
+ // curr, currPosInBlock, candidateOffCode, candidateMatchLength, matchStartPosInBlock, matchEndPosInBlock, rawSeqStore->seq[rawSeqStore->pos].offset, rawSeqStore->seq[rawSeqStore->pos].matchLength, rawSeqStore->seq[rawSeqStore->pos].litLength, rawSeqStore->pos);
if (*nbMatches == 0) {
matches[*nbMatches].len = candidateMatchLength;
@@ -917,15 +918,15 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 candidateMatchIdx = *nbMatches;
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
- printf("Sifting...: idx: %u, len: %u, off: %u\n", candidateMatchIdx, candidateMatchLength, candidateOffCode);
- //printf("Current best is...: idx: %u, len: %u, off: %u\n", *nbMatches-1, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ ////printf("Sifting...: idx: %u, len: %u, off: %u\n", candidateMatchIdx, candidateMatchLength, candidateOffCode);
+ //////printf("Current best is...: idx: %u, len: %u, off: %u\n", *nbMatches-1, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
if (candidateOffCode != matches[*nbMatches].off)
- printf("DIFF: ldm: (len: %u, off: %u), best: (len: %u, off: %u)\n", candidateMatchLength, candidateOffCode, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
- //printf("Current best is...: idx: %u, len: %u, off: %u\n", *nbMatches-1, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ ////printf("DIFF: ldm: (len: %u, off: %u), best: (len: %u, off: %u)\n", candidateMatchLength, candidateOffCode, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ //////printf("Current best is...: idx: %u, len: %u, off: %u\n", *nbMatches-1, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
while (candidateMatchIdx > 0 &&
matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
- //printf("Compared to: idx: %u, len: %u, off: %u", candidateMatchIdx - 1, matches[candidateMatchIdx - 1].len, matches[candidateMatchIdx - 1].off);
+ //////printf("Compared to: idx: %u, len: %u, off: %u", candidateMatchIdx - 1, matches[candidateMatchIdx - 1].len, matches[candidateMatchIdx - 1].off);
ZSTD_match_t tmp = matches[candidateMatchIdx - 1];
matches[candidateMatchIdx - 1] = matches[candidateMatchIdx];
matches[candidateMatchIdx] = tmp;
@@ -933,7 +934,7 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
}
(*nbMatches)++;
} else {
- printf("MATCHDIFF: ldm: (len: %u, off: %u), best: (len: %u, off: %u)\n", candidateMatchLength, candidateOffCode, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ ////printf("MATCHDIFF: ldm: (len: %u, off: %u), best: (len: %u, off: %u)\n", candidateMatchLength, candidateOffCode, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
(*nbMatches)++;
@@ -943,21 +944,22 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
}
/* Wrapper function to call ldm functions as needed */
-static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
+static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesConsumed, ZSTD_match_t* matches, U32* nbMatches,
U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
U32 currPosInBlock, U32 remainingBytes, U32 curr, U32 sbi) {
+ ////printf("currPosInBlock: %u, curr: %u, called ldm_handleLdm()", currPosInBlock, curr);
if (currPosInBlock >= *matchEndPosInBlock) {
- printf("Went over match boundary: currPosInBlock: %u, %matchEndPosInBlock: %u\n", currPosInBlock, *matchEndPosInBlock);
+ //printf("Went over match boundary: currPosInBlock: %u, %matchEndPosInBlock: %u\n", currPosInBlock, *matchEndPosInBlock);
if (currPosInBlock > *matchEndPosInBlock) {
U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
- printf("Overshot position by: %u\n", posOvershoot);
+ //printf("Overshot position by: %u\n", posOvershoot);
ldm_skipSequences(ldmSeqStore, posOvershoot, MINMATCH);
}
- int noMoreLdms = ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
+ int noMoreLdms = ldm_getNextMatch(ldmSeqStore, ldmSeqStoreBytesConsumed, matchStartPosInBlock,
matchEndPosInBlock, matchOffset,
currPosInBlock, remainingBytes, sbi);
}
- ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, curr, sbi);
+ ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, curr, sbi, ldmSeqStore);
}
@@ -1018,10 +1020,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmStartPosInBlock = 0;
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
+ U32 ldmSeqStoreBytesConsumed = 0;
- printf("SBI for this block: %u, base: %u\n", sbi, base);
+ ////printf("SBI for this block: %u, base: %u\n", sbi, base);
+ if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.base != base) {
+ int baseDiff = (int)(ms->ldmSeqStore.base - base);
+ //printf("Bases were different, adjusting, diff = %d\n", baseDiff);
+ ms->ldmSeqStore.seq[ms->ldmSeqStore.pos].litLength += baseDiff;
+ ms->ldmSeqStore.base = ms->window.base;
+ }
if (ms->ldmSeqStore.size != 0) {
- ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ ldm_getNextMatch(&ms->ldmSeqStore, &ldmSeqStoreBytesConsumed, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset, (U32)(ip-istart), (U32)(iend-ip), sbi);
}
/* init */
@@ -1040,7 +1049,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const ll0 = !litlen;
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
if (ms->ldmSeqStore.size != 0) {
- ldm_handleLdm(&ms->ldmSeqStore, matches,
+ ldm_handleLdm(&ms->ldmSeqStore, &ldmSeqStoreBytesConsumed, matches,
&nbMatches, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
(U32)(ip-istart), (U32)(iend - ip), (U32)(ip-base), sbi);
@@ -1162,7 +1171,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
if (ms->ldmSeqStore.size != 0) {
- ldm_handleLdm(&ms->ldmSeqStore, matches,
+ ldm_handleLdm(&ms->ldmSeqStore, &ldmSeqStoreBytesConsumed, matches,
&nbMatches, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
(U32)(inr-istart), (U32)(iend-inr), (U32)(inr-base), sbi);
@@ -1281,6 +1290,13 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
}
} /* while (ip < ilimit) */
+ int i = ms->ldmSeqStore.pos;
+ //printf("pos %d (of:%u ml:%u ll: %u)\n", i, ms->ldmSeqStore.seq[i].offset, ms->ldmSeqStore.seq[i].matchLength, ms->ldmSeqStore.seq[i].litLength);
+ //printf("matchend: %u bytesconsumed: %u\n", ldmEndPosInBlock, ldmSeqStoreBytesConsumed);
+ if (ldmEndPosInBlock < srcSize) {
+ //printf("Needs adjustment, endpos didn't reach end of block\n");
+ ldm_skipSequences(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock, MINMATCH);
+ }
/* Return the last literals size */
return (size_t)(iend - anchor);
}
diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
index baf6ef4ca..57015f156 100644
--- a/lib/compress/zstdmt_compress.c
+++ b/lib/compress/zstdmt_compress.c
@@ -277,7 +277,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
static rawSeqStore_t bufferToSeq(buffer_t buffer)
{
- rawSeqStore_t seq = {NULL, 0, 0, 0};
+ rawSeqStore_t seq = {NULL, NULL, 0, 0, 0};
seq.seq = (rawSeq*)buffer.start;
seq.capacity = buffer.capacity / sizeof(rawSeq);
return seq;
From 78da2e1808ea40e68320dc045e996024daa242f9 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Tue, 29 Sep 2020 15:35:13 -0400
Subject: [PATCH 20/51] Fixed sifting algorithm
---
lib/compress/zstd_opt.c | 137 ++++++++++++++++++++--------------------
1 file changed, 67 insertions(+), 70 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 05fa4cae7..6cea5a38b 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,54 +768,24 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM util functions
*********************************/
-/*
-static void ldm_skipOvershotBytes(rawSeqStore_t* rawSeqStore, U32 bytesOvershot) {
- while (bytesOvershot > 0 && rawSeqStore->pos < rawSeqStore->size) {
- rawSeq seq = rawSeqStore->seq[rawSeqStore->pos];
- if (bytesOvershot <= seq.litLength) {
- seq->litLength -= bytesOvershot;
- }
- }
- if (rawSeqStore->seq[rawSeqStore->pos].matchLength > posOvershoot) {
- rawSeqStore->seq[rawSeqStore->pos].matchLength -= posOvershoot;
- return;
- } else {
- rawSeqStore->seq[rawSeqStore->pos].matchLength = 0;
- rawSeqStore->pos++;
- }
-
- while (posOvershoot > 0 && rawSeqStore->pos < rawSeqStore->size) {
-
- }
-}*/
-
-
-static void ldm_voidSequences(rawSeqStore_t* ldmSeqStore, U32 overshotBytes) {
- U32 posAdjustment;
- U32 bytesAdjustment;
- while (overshotBytes > 0 && ldmSeqStore->pos < ldmSeqStore->size) {
-
- }
-}
-
static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
- ////printf("ldm_skipSequences(): %u remaining\n", srcSize);
+ //////printf("ldm_skipSequences(): %u remaining\n", srcSize);
rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
- ////printf("ldm_skipSequences(): before: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
+ //////printf("ldm_skipSequences(): before: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
if (srcSize <= seq->litLength) {
/* Skip past srcSize literals */
seq->litLength -= (U32)srcSize;
- ////printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
+ //////printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
return;
}
srcSize -= seq->litLength;
seq->litLength = 0;
if (srcSize < seq->matchLength) {
- ////printf("Splitting match: ml curr: %u ", seq->matchLength);
+ //////printf("Splitting match: ml curr: %u ", seq->matchLength);
/* Skip past the first srcSize of the match */
seq->matchLength -= (U32)srcSize;
- ////printf("ml in store left: %u ", seq->matchLength);
+ //////printf("ml in store left: %u ", seq->matchLength);
/*if (seq->matchLength < minMatch) {
// The match is too short, omit it
if (rawSeqStore->pos + 1 < rawSeqStore->size) {
@@ -823,12 +793,12 @@ static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 co
}
rawSeqStore->pos++;
}*/
- //printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
+ ////printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
return;
}
srcSize -= seq->matchLength;
seq->matchLength = 0;
- //printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
+ ////printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
rawSeqStore->pos++;
}
}
@@ -836,30 +806,30 @@ static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 co
// The only function that can update pos (i think, for now)
static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesConsumed, U32 remainingBytes) {
rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- //printf("ldm_splitSequence(): Current sequence: (of: %u, ml: %u, ll: %u) - remaining: %u\n", currSeq.offset, currSeq.matchLength, currSeq.litLength, remainingBytes);
+ ////printf("ldm_splitSequence(): Current sequence: (of: %u, ml: %u, ll: %u) - remaining: %u\n", currSeq.offset, currSeq.matchLength, currSeq.litLength, remainingBytes);
/* No split */
if (remainingBytes >= currSeq.litLength + currSeq.matchLength) {
- ////printf("NO SPLIT\n");
+ //////printf("NO SPLIT\n");
*ldmSeqStoreBytesConsumed += currSeq.litLength + currSeq.matchLength;
ldmSeqStore->pos++;
- ////printf("pos is now: %u\n", ldmSeqStore->pos);
+ //////printf("pos is now: %u\n", ldmSeqStore->pos);
return currSeq;
}
/* Need a split */
if (remainingBytes <= currSeq.litLength) {
- ////printf("SPLITTING: all remaining bytes were literals");
+ //////printf("SPLITTING: all remaining bytes were literals");
currSeq.offset = 0;
} else if (remainingBytes < currSeq.litLength + currSeq.matchLength) {
/*if (currSeq.matchLength < MINMATCH) {
- ////printf("CurrSeq less than minmatch: all remaining bytes were literals");
+ //////printf("CurrSeq less than minmatch: all remaining bytes were literals");
currSeq.offset = 0;
}*/
currSeq.matchLength = remainingBytes - currSeq.litLength;
}
- ////printf("\n");
+ //////printf("\n");
*ldmSeqStoreBytesConsumed += remainingBytes;
ldm_skipSequences(ldmSeqStore, remainingBytes, MINMATCH);
- //printf("ldm_splitSequence(): Sequence final: (of: %u, ml: %u, ll: %u)\n", currSeq.offset, currSeq.matchLength, currSeq.litLength);
+ ////printf("ldm_splitSequence(): Sequence final: (of: %u, ml: %u, ll: %u)\n", currSeq.offset, currSeq.matchLength, currSeq.litLength);
return currSeq;
}
@@ -870,7 +840,7 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesCon
U32 remainingBytes, U32 sbi) {
if (ldmSeqStore->pos >= ldmSeqStore->size) {
// Don't use the LDM for the rest of the block (there is none)
- //printf("No ldm left in the block, pos max reached\n");
+ ////printf("No ldm left in the block, pos max reached\n");
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
return 1;
@@ -878,7 +848,7 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesCon
rawSeq seq = ldm_splitSequence(ldmSeqStore, ldmSeqStoreBytesConsumed, remainingBytes);
if (seq.offset == 0) {
// Don't use the LDM for the rest of the block (there is none)
- ////printf("No ldm left in the block, offset = 0\n");
+ //////printf("No ldm left in the block, offset = 0\n");
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
return 1;
@@ -887,10 +857,32 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesCon
*matchStartPosInBlock = currPosInBlock + seq.litLength;
*matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
*matchOffset = seq.offset;
- //printf("New match range in block is: (%u, %u) with of: %u where currPosInBlock: %u at adjusted absolute range: %u, %u\n", *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, *matchStartPosInBlock+sbi, *matchEndPosInBlock+sbi);
+ ////printf("New match range in block is: (%u, %u) with of: %u where currPosInBlock: %u at adjusted absolute range: %u, %u\n", *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, *matchStartPosInBlock+sbi, *matchEndPosInBlock+sbi);
return 0;
}
+static void printMatches(ZSTD_match_t* matches, U32 nbMatches) {
+ for (int i = 0; i < nbMatches; ++i) {
+ //printf("(of: %u ml: %u) ", matches[i].off, matches[i].len);
+ }
+ //printf("\n");
+}
+static void validateMatches(ZSTD_match_t* matches, U32 nbMatches) {
+ U32 prevLargestOffset = 0;
+ U32 prevLargestMatch = 0;
+ for (int i = 1; i < nbMatches; ++i) {
+ if (matches[i-1].len > matches[i].len) {
+ //printf("nope\n");
+ exit(1);
+ } else if (matches[i-1].len == matches[i].len) {
+ if (matches[i-1].off < matches[i].off) {
+ //printf("nopeOff\n");
+ exit(1);
+ }
+ }
+ }
+}
+
/* Adds an LDM if it's long enough */
static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
@@ -903,43 +895,48 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
return; // dont deal with extra ldms for now
assert(posDiff < matchEndPosInBlock - matchStartPosInBlock);
U32 candidateMatchLength = matchEndPosInBlock - matchStartPosInBlock - posDiff;
+ if (candidateMatchLength < ZSTD_LDM_MINMATCH_MIN)
+ return;
+
U32 candidateOffCode = matchOffset + posDiff + ZSTD_REP_MOVE;
if ((*nbMatches == 0 || candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
//printf("large enough: curr: %u currposinblock: %u (ofcode: %u, ml: %u) - range: (%u, %u) - (of: %u ml: %u ll: %u) @ pos: %u - \n",
- // curr, currPosInBlock, candidateOffCode, candidateMatchLength, matchStartPosInBlock, matchEndPosInBlock, rawSeqStore->seq[rawSeqStore->pos].offset, rawSeqStore->seq[rawSeqStore->pos].matchLength, rawSeqStore->seq[rawSeqStore->pos].litLength, rawSeqStore->pos);
+ // curr, currPosInBlock, candidateOffCode, candidateMatchLength, matchStartPosInBlock, matchEndPosInBlock, rawSeqStore->seq[rawSeqStore->pos].offset, rawSeqStore->seq[rawSeqStore->pos].matchLength, rawSeqStore->seq[rawSeqStore->pos].litLength, rawSeqStore->pos);
if (*nbMatches == 0) {
+ //printf("HERE1\n");
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
(*nbMatches)++;
} else {
if (candidateMatchLength == matches[*nbMatches-1].len) {
+ //printf("HERE2\n");
U32 candidateMatchIdx = *nbMatches;
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
- ////printf("Sifting...: idx: %u, len: %u, off: %u\n", candidateMatchIdx, candidateMatchLength, candidateOffCode);
- //////printf("Current best is...: idx: %u, len: %u, off: %u\n", *nbMatches-1, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
- if (candidateOffCode != matches[*nbMatches].off)
- ////printf("DIFF: ldm: (len: %u, off: %u), best: (len: %u, off: %u)\n", candidateMatchLength, candidateOffCode, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
- //////printf("Current best is...: idx: %u, len: %u, off: %u\n", *nbMatches-1, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
- while (candidateMatchIdx > 0 &&
- matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
- matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
- //////printf("Compared to: idx: %u, len: %u, off: %u", candidateMatchIdx - 1, matches[candidateMatchIdx - 1].len, matches[candidateMatchIdx - 1].off);
- ZSTD_match_t tmp = matches[candidateMatchIdx - 1];
- matches[candidateMatchIdx - 1] = matches[candidateMatchIdx];
- matches[candidateMatchIdx] = tmp;
- --candidateMatchIdx;
+ if (candidateOffCode != matches[*nbMatches-1].off) {
+ //printf("offsets not equal\n");
+ while (candidateMatchIdx > 0 &&
+ matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
+ matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
+ //printf("sifting\n");
+ ZSTD_match_t tmp = matches[candidateMatchIdx - 1];
+ matches[candidateMatchIdx - 1] = matches[candidateMatchIdx];
+ matches[candidateMatchIdx] = tmp;
+ --candidateMatchIdx;
+ }
}
(*nbMatches)++;
} else {
- ////printf("MATCHDIFF: ldm: (len: %u, off: %u), best: (len: %u, off: %u)\n", candidateMatchLength, candidateOffCode, matches[*nbMatches-1].len, matches[*nbMatches-1].off);
+ //printf("HERE3\n");
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
(*nbMatches)++;
}
}
+ printMatches(matches, *nbMatches);
+ validateMatches(matches, *nbMatches);
}
}
@@ -947,12 +944,12 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesConsumed, ZSTD_match_t* matches, U32* nbMatches,
U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
U32 currPosInBlock, U32 remainingBytes, U32 curr, U32 sbi) {
- ////printf("currPosInBlock: %u, curr: %u, called ldm_handleLdm()", currPosInBlock, curr);
+ //////printf("currPosInBlock: %u, curr: %u, called ldm_handleLdm()", currPosInBlock, curr);
if (currPosInBlock >= *matchEndPosInBlock) {
- //printf("Went over match boundary: currPosInBlock: %u, %matchEndPosInBlock: %u\n", currPosInBlock, *matchEndPosInBlock);
+ ////printf("Went over match boundary: currPosInBlock: %u, %matchEndPosInBlock: %u\n", currPosInBlock, *matchEndPosInBlock);
if (currPosInBlock > *matchEndPosInBlock) {
U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
- //printf("Overshot position by: %u\n", posOvershoot);
+ ////printf("Overshot position by: %u\n", posOvershoot);
ldm_skipSequences(ldmSeqStore, posOvershoot, MINMATCH);
}
int noMoreLdms = ldm_getNextMatch(ldmSeqStore, ldmSeqStoreBytesConsumed, matchStartPosInBlock,
@@ -1022,10 +1019,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmOffset = 0;
U32 ldmSeqStoreBytesConsumed = 0;
- ////printf("SBI for this block: %u, base: %u\n", sbi, base);
+ //////printf("SBI for this block: %u, base: %u\n", sbi, base);
if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.base != base) {
int baseDiff = (int)(ms->ldmSeqStore.base - base);
- //printf("Bases were different, adjusting, diff = %d\n", baseDiff);
+ ////printf("Bases were different, adjusting, diff = %d\n", baseDiff);
ms->ldmSeqStore.seq[ms->ldmSeqStore.pos].litLength += baseDiff;
ms->ldmSeqStore.base = ms->window.base;
}
@@ -1291,10 +1288,10 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
} /* while (ip < ilimit) */
int i = ms->ldmSeqStore.pos;
- //printf("pos %d (of:%u ml:%u ll: %u)\n", i, ms->ldmSeqStore.seq[i].offset, ms->ldmSeqStore.seq[i].matchLength, ms->ldmSeqStore.seq[i].litLength);
- //printf("matchend: %u bytesconsumed: %u\n", ldmEndPosInBlock, ldmSeqStoreBytesConsumed);
+ ////printf("pos %d (of:%u ml:%u ll: %u)\n", i, ms->ldmSeqStore.seq[i].offset, ms->ldmSeqStore.seq[i].matchLength, ms->ldmSeqStore.seq[i].litLength);
+ ////printf("matchend: %u bytesconsumed: %u\n", ldmEndPosInBlock, ldmSeqStoreBytesConsumed);
if (ldmEndPosInBlock < srcSize) {
- //printf("Needs adjustment, endpos didn't reach end of block\n");
+ ////printf("Needs adjustment, endpos didn't reach end of block\n");
ldm_skipSequences(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock, MINMATCH);
}
/* Return the last literals size */
From ea92fb3a684c412eb81fab1e11fa11ece751f409 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Tue, 29 Sep 2020 16:35:06 -0400
Subject: [PATCH 21/51] Cleanups, add comments and explanations
---
lib/compress/zstd_compress.c | 2 +-
lib/compress/zstd_compress_internal.h | 2 +-
lib/compress/zstd_ldm.c | 17 +-
lib/compress/zstd_opt.c | 251 +++++++++++---------------
lib/compress/zstdmt_compress.c | 2 +-
5 files changed, 113 insertions(+), 161 deletions(-)
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 3c80ab860..4958239cf 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2336,7 +2336,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
if (curr > ms->nextToUpdate + 384)
ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
}
- //printf("--NEW BLOCK--\n");
+
/* select and store sequences */
{ ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
size_t lastLLSize;
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index 53c20b12c..9eba078b4 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -94,7 +94,7 @@ typedef struct {
typedef struct {
rawSeq* seq; /* The start of the sequences */
- BYTE const* base;
+ BYTE const* base; /* The match state window base when LDMs were generated */
size_t pos; /* The position where reading stopped. <= size. */
size_t size; /* The number of sequences. <= capacity. */
size_t capacity; /* The capacity starting from `seq` pointer */
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 9fcb9fc29..743344036 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -562,13 +562,6 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
return sequence;
}
-static void printSeqStore(rawSeqStore_t* rawSeqStore) {
- printf("rawSeqStore: pos: %zu\n", rawSeqStore->pos);
- for (int i = 0; i < rawSeqStore->size; ++i) {
- printf("pos %d (of:%u ml:%u ll: %u)\n", i, rawSeqStore->seq[i].offset, rawSeqStore->seq[i].matchLength, rawSeqStore->seq[i].litLength);
- }
-}
-
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize)
@@ -582,19 +575,13 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
BYTE const* const iend = istart + srcSize;
/* Input positions */
BYTE const* ip = istart;
- //printSeqStore(rawSeqStore);
if (cParams->strategy >= ZSTD_btopt) {
size_t lastLLSize;
- //printSeqStore(rawSeqStore);
- ms->ldmSeqStore = *rawSeqStore; /* copy current seqStore */
+ ms->ldmSeqStore = *rawSeqStore;
ms->ldmSeqStore.base = ms->window.base;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
+ /* ldm seqstore will have changed during blockCompressor() call, make sure we copy those changes */
*rawSeqStore = ms->ldmSeqStore;
- /*if (prevBase != ms->window.base) {
- int baseDiff = (int)(prevBase - ms->window.base);
- printf("Bases were different, adjusting, diff = %d\n", baseDiff);
- rawSeqStore->seq[rawSeqStore->pos].litLength += baseDiff;
- }*/
return lastLLSize;
}
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 6cea5a38b..075826b73 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -765,90 +765,69 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
}
/*-*******************************
-* LDM util functions
+* LDM helper functions
*********************************/
-static void ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
- while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
- //////printf("ldm_skipSequences(): %u remaining\n", srcSize);
- rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
- //////printf("ldm_skipSequences(): before: (of: %u, ml: %u, ll: %u)\n", seq->offset, seq->matchLength, seq->litLength);
- if (srcSize <= seq->litLength) {
+/* Skips past srcSize bytes in an ldm seqstore */
+static void ldm_skipBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t bytesToSkip) {
+ while (bytesToSkip > 0 && ldmSeqStore->pos < ldmSeqStore->size) {
+ rawSeq* seq = ldmSeqStore->seq + ldmSeqStore->pos;
+ if (bytesToSkip <= seq->litLength) {
/* Skip past srcSize literals */
- seq->litLength -= (U32)srcSize;
- //////printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
+ seq->litLength -= (U32)bytesToSkip;
return;
}
- srcSize -= seq->litLength;
+ bytesToSkip -= seq->litLength;
seq->litLength = 0;
- if (srcSize < seq->matchLength) {
- //////printf("Splitting match: ml curr: %u ", seq->matchLength);
- /* Skip past the first srcSize of the match */
- seq->matchLength -= (U32)srcSize;
- //////printf("ml in store left: %u ", seq->matchLength);
- /*if (seq->matchLength < minMatch) {
- // The match is too short, omit it
- if (rawSeqStore->pos + 1 < rawSeqStore->size) {
- seq[1].litLength += seq[0].matchLength;
- }
- rawSeqStore->pos++;
- }*/
- ////printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
+ if (bytesToSkip < seq->matchLength) {
+ seq->matchLength -= (U32)bytesToSkip;
return;
}
- srcSize -= seq->matchLength;
+ bytesToSkip -= seq->matchLength;
seq->matchLength = 0;
- ////printf("ldm_skipSequences(): seqstore final: (of: %u, ml: %u, ll: %u) at %u\n", seq->offset, seq->matchLength, seq->litLength, rawSeqStore->pos);
- rawSeqStore->pos++;
+ ldmSeqStore->pos++;
}
}
-// The only function that can update pos (i think, for now)
-static rawSeq ldm_splitSequence(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesConsumed, U32 remainingBytes) {
+/* Splits a sequence if it's across the boundary. May update pos in the seq store too
+ * Pretty much the same function as maybeSplitSequence() in zstd_ldm.c
+ */
+static rawSeq ldm_splitSequenceAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore, U32 remainingBytes) {
rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- ////printf("ldm_splitSequence(): Current sequence: (of: %u, ml: %u, ll: %u) - remaining: %u\n", currSeq.offset, currSeq.matchLength, currSeq.litLength, remainingBytes);
- /* No split */
+ /* Case where don't split the match*/
if (remainingBytes >= currSeq.litLength + currSeq.matchLength) {
- //////printf("NO SPLIT\n");
- *ldmSeqStoreBytesConsumed += currSeq.litLength + currSeq.matchLength;
ldmSeqStore->pos++;
- //////printf("pos is now: %u\n", ldmSeqStore->pos);
return currSeq;
}
/* Need a split */
if (remainingBytes <= currSeq.litLength) {
- //////printf("SPLITTING: all remaining bytes were literals");
currSeq.offset = 0;
} else if (remainingBytes < currSeq.litLength + currSeq.matchLength) {
- /*if (currSeq.matchLength < MINMATCH) {
- //////printf("CurrSeq less than minmatch: all remaining bytes were literals");
- currSeq.offset = 0;
- }*/
currSeq.matchLength = remainingBytes - currSeq.litLength;
}
- //////printf("\n");
- *ldmSeqStoreBytesConsumed += remainingBytes;
- ldm_skipSequences(ldmSeqStore, remainingBytes, MINMATCH);
- ////printf("ldm_splitSequence(): Sequence final: (of: %u, ml: %u, ll: %u)\n", currSeq.offset, currSeq.matchLength, currSeq.litLength);
+
+ /* After deriving currSeq which is the sequence before the block boundary,
+ * we now must skip past the remaining number of bytes unaccounted for,
+ * and update the entry at pos in the seqStore, which represents the second half
+ * of the sequence after the block boundary
+ */
+ ldm_skipBytesInSeqStore(ldmSeqStore, remainingBytes);
return currSeq;
}
-/* Returns 1 if the rest of the block is just LDM literals */
-static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesConsumed,
+/* Fetch the next match in the ldm seq store */
+static void ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
U32* matchStartPosInBlock, U32* matchEndPosInBlock,
U32* matchOffset, U32 currPosInBlock,
- U32 remainingBytes, U32 sbi) {
+ U32 remainingBytes) {
+ /* Setting match end position to MAX will ensure we never use an LDM during this block */
if (ldmSeqStore->pos >= ldmSeqStore->size) {
- // Don't use the LDM for the rest of the block (there is none)
- ////printf("No ldm left in the block, pos max reached\n");
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
return 1;
}
- rawSeq seq = ldm_splitSequence(ldmSeqStore, ldmSeqStoreBytesConsumed, remainingBytes);
+ rawSeq seq = ldm_splitSequenceAndUpdateSeqStore(ldmSeqStore, remainingBytes);
if (seq.offset == 0) {
- // Don't use the LDM for the rest of the block (there is none)
- //////printf("No ldm left in the block, offset = 0\n");
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
return 1;
@@ -857,106 +836,79 @@ static int ldm_getNextMatch(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesCon
*matchStartPosInBlock = currPosInBlock + seq.litLength;
*matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
*matchOffset = seq.offset;
- ////printf("New match range in block is: (%u, %u) with of: %u where currPosInBlock: %u at adjusted absolute range: %u, %u\n", *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, *matchStartPosInBlock+sbi, *matchEndPosInBlock+sbi);
return 0;
}
-static void printMatches(ZSTD_match_t* matches, U32 nbMatches) {
- for (int i = 0; i < nbMatches; ++i) {
- //printf("(of: %u ml: %u) ", matches[i].off, matches[i].len);
- }
- //printf("\n");
-}
-static void validateMatches(ZSTD_match_t* matches, U32 nbMatches) {
- U32 prevLargestOffset = 0;
- U32 prevLargestMatch = 0;
- for (int i = 1; i < nbMatches; ++i) {
- if (matches[i-1].len > matches[i].len) {
- //printf("nope\n");
- exit(1);
- } else if (matches[i-1].len == matches[i].len) {
- if (matches[i-1].off < matches[i].off) {
- //printf("nopeOff\n");
- exit(1);
- }
- }
- }
-}
-
/* Adds an LDM if it's long enough */
static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
- U32 matchOffset, U32 currPosInBlock, U32 curr, U32 sbi, rawSeqStore_t* rawSeqStore) {
+ U32 matchOffset, U32 currPosInBlock) {
/* Check that current block position is not outside of the match */
if (currPosInBlock < matchStartPosInBlock || currPosInBlock >= matchEndPosInBlock)
return;
+
U32 posDiff = currPosInBlock - matchStartPosInBlock;
+ /* TODO: Next step will enable adding LDMs in the middle of a match */
if (posDiff > 0)
- return; // dont deal with extra ldms for now
- assert(posDiff < matchEndPosInBlock - matchStartPosInBlock);
+ return;
+
+ /* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
U32 candidateMatchLength = matchEndPosInBlock - matchStartPosInBlock - posDiff;
if (candidateMatchLength < ZSTD_LDM_MINMATCH_MIN)
return;
-
U32 candidateOffCode = matchOffset + posDiff + ZSTD_REP_MOVE;
- if ((*nbMatches == 0 || candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
- //printf("large enough: curr: %u currposinblock: %u (ofcode: %u, ml: %u) - range: (%u, %u) - (of: %u ml: %u ll: %u) @ pos: %u - \n",
- // curr, currPosInBlock, candidateOffCode, candidateMatchLength, matchStartPosInBlock, matchEndPosInBlock, rawSeqStore->seq[rawSeqStore->pos].offset, rawSeqStore->seq[rawSeqStore->pos].matchLength, rawSeqStore->seq[rawSeqStore->pos].litLength, rawSeqStore->pos);
-
- if (*nbMatches == 0) {
- //printf("HERE1\n");
+ if (*nbMatches == 0) {
+ matches[*nbMatches].len = candidateMatchLength;
+ matches[*nbMatches].off = candidateOffCode;
+ (*nbMatches)++;
+ } else if ((candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
+ /* Maintain order of matches, which is first - increasing in matchlength,
+ * and secondly - decreasing in offCode. Since matches in ldm seq store are likely
+ * to be the longest match found, we simply start at the end of the array and sift
+ * the ldm match down as necessary.
+ */
+ if (candidateMatchLength == matches[*nbMatches-1].len) {
+ U32 candidateMatchIdx = *nbMatches;
+ matches[*nbMatches].len = candidateMatchLength;
+ matches[*nbMatches].off = candidateOffCode;
+ if (candidateOffCode != matches[*nbMatches-1].off) {
+ while (candidateMatchIdx > 0 &&
+ matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
+ matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
+ ZSTD_match_t tmp = matches[candidateMatchIdx - 1];
+ matches[candidateMatchIdx - 1] = matches[candidateMatchIdx];
+ matches[candidateMatchIdx] = tmp;
+ --candidateMatchIdx;
+ }
+ }
+ (*nbMatches)++;
+ } else {
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
(*nbMatches)++;
- } else {
- if (candidateMatchLength == matches[*nbMatches-1].len) {
- //printf("HERE2\n");
- U32 candidateMatchIdx = *nbMatches;
- matches[*nbMatches].len = candidateMatchLength;
- matches[*nbMatches].off = candidateOffCode;
- if (candidateOffCode != matches[*nbMatches-1].off) {
- //printf("offsets not equal\n");
- while (candidateMatchIdx > 0 &&
- matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
- matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
- //printf("sifting\n");
- ZSTD_match_t tmp = matches[candidateMatchIdx - 1];
- matches[candidateMatchIdx - 1] = matches[candidateMatchIdx];
- matches[candidateMatchIdx] = tmp;
- --candidateMatchIdx;
- }
- }
- (*nbMatches)++;
- } else {
- //printf("HERE3\n");
- matches[*nbMatches].len = candidateMatchLength;
- matches[*nbMatches].off = candidateOffCode;
- (*nbMatches)++;
- }
}
- printMatches(matches, *nbMatches);
- validateMatches(matches, *nbMatches);
}
}
-/* Wrapper function to call ldm functions as needed */
-static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, U32* ldmSeqStoreBytesConsumed, ZSTD_match_t* matches, U32* nbMatches,
+/* Wrapper function to update and call ldm functions as necessary */
+static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
- U32 currPosInBlock, U32 remainingBytes, U32 curr, U32 sbi) {
- //////printf("currPosInBlock: %u, curr: %u, called ldm_handleLdm()", currPosInBlock, curr);
+ U32 currPosInBlock, U32 remainingBytes) {
if (currPosInBlock >= *matchEndPosInBlock) {
- ////printf("Went over match boundary: currPosInBlock: %u, %matchEndPosInBlock: %u\n", currPosInBlock, *matchEndPosInBlock);
if (currPosInBlock > *matchEndPosInBlock) {
+ /* The position at which ldm_handleLdm() is called is not necessarily
+ * at the end of a match from the ldm seq store, and will often be some bytes
+ * over the end of an ldm match. As such, we need to correct for these "overshoots"
+ */
U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
- ////printf("Overshot position by: %u\n", posOvershoot);
- ldm_skipSequences(ldmSeqStore, posOvershoot, MINMATCH);
+ ldm_skipBytesInSeqStore(ldmSeqStore, posOvershoot);
}
- int noMoreLdms = ldm_getNextMatch(ldmSeqStore, ldmSeqStoreBytesConsumed, matchStartPosInBlock,
- matchEndPosInBlock, matchOffset,
- currPosInBlock, remainingBytes, sbi);
+ ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
+ matchEndPosInBlock, matchOffset,
+ currPosInBlock, remainingBytes);
}
- ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock, curr, sbi, ldmSeqStore);
+ ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
}
@@ -1008,7 +960,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
U32 nextToUpdate3 = ms->nextToUpdate;
- U32 const sbi = (U32)(istart-base);
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
ZSTD_match_t* const matches = optStatePtr->matchTable;
@@ -1017,18 +968,34 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmStartPosInBlock = 0;
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
- U32 ldmSeqStoreBytesConsumed = 0;
- //////printf("SBI for this block: %u, base: %u\n", sbi, base);
- if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.base != base) {
- int baseDiff = (int)(ms->ldmSeqStore.base - base);
- ////printf("Bases were different, adjusting, diff = %d\n", baseDiff);
- ms->ldmSeqStore.seq[ms->ldmSeqStore.pos].litLength += baseDiff;
- ms->ldmSeqStore.base = ms->window.base;
- }
- if (ms->ldmSeqStore.size != 0) {
- ldm_getNextMatch(&ms->ldmSeqStore, &ldmSeqStoreBytesConsumed, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset, (U32)(ip-istart), (U32)(iend-ip), sbi);
+ /* It seems that if the ldm seqstore was calculated using a different base, we actually have to
+ * apply a correction to line it up with the block itself. This applies to multi-threaded cases
+ * where the block it can be the case that the LDMs were generated starting at a different
+ * block. By adding baseDiff to the litLength of seq, we pad out that base difference.
+ *
+ * For example, I found that when compressing dickens from silesia, the first LDM according to the seqStore is:
+ * (of:951277 ml:1362 ll: 952876)
+ *
+ * And as such, we might expect to insert the match in the 7th block at:
+ * pos_in_block 35373 == 952877 - 131072 * 7
+ * I.e., at position 35373 the 7th block.
+ *
+ * Surprisingly, the correct place to insert is in the 8th block at
+ * pos_in_block 35373 = 1083948 - 131072 * 8
+ *
+ * since the base shifts back 131072 bytes (1 block) after the first block. The consequence is that
+ * we should insert 35373 bytes into the 8th block, rather than 35373 bytes into the 7th block.
+ */
+ if (ms->ldmSeqStore.size > 0) {
+ if (ms->ldmSeqStore.base != base) {
+ int baseDiff = (int)(ms->ldmSeqStore.base - base);
+ ms->ldmSeqStore.seq[ms->ldmSeqStore.pos].litLength += baseDiff;
+ ms->ldmSeqStore.base = ms->window.base;
+ }
+ ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend-ip));
}
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
@@ -1046,10 +1013,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const ll0 = !litlen;
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
if (ms->ldmSeqStore.size != 0) {
- ldm_handleLdm(&ms->ldmSeqStore, &ldmSeqStoreBytesConsumed, matches,
+ ldm_handleLdm(&ms->ldmSeqStore, matches,
&nbMatches, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend - ip), (U32)(ip-base), sbi);
+ (U32)(ip-istart), (U32)(iend - ip));
}
if (!nbMatches) { ip++; continue; }
@@ -1168,10 +1135,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
if (ms->ldmSeqStore.size != 0) {
- ldm_handleLdm(&ms->ldmSeqStore, &ldmSeqStoreBytesConsumed, matches,
+ ldm_handleLdm(&ms->ldmSeqStore, matches,
&nbMatches, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
- (U32)(inr-istart), (U32)(iend-inr), (U32)(inr-base), sbi);
+ (U32)(inr-istart), (U32)(iend-inr));
}
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -1286,13 +1253,11 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
ZSTD_setBasePrices(optStatePtr, optLevel);
}
} /* while (ip < ilimit) */
-
- int i = ms->ldmSeqStore.pos;
- ////printf("pos %d (of:%u ml:%u ll: %u)\n", i, ms->ldmSeqStore.seq[i].offset, ms->ldmSeqStore.seq[i].matchLength, ms->ldmSeqStore.seq[i].litLength);
- ////printf("matchend: %u bytesconsumed: %u\n", ldmEndPosInBlock, ldmSeqStoreBytesConsumed);
+
if (ldmEndPosInBlock < srcSize) {
- ////printf("Needs adjustment, endpos didn't reach end of block\n");
- ldm_skipSequences(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock, MINMATCH);
+ /* This can occur if after adding the final match in an ldm seq store within this block,
+ ip goes to the end of the block without activating a check for ldm_getNextMatch */
+ ldm_skipBytesInSeqStore(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
}
/* Return the last literals size */
return (size_t)(iend - anchor);
diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
index 57015f156..6b3e8bee5 100644
--- a/lib/compress/zstdmt_compress.c
+++ b/lib/compress/zstdmt_compress.c
@@ -266,7 +266,7 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
/* ===== Seq Pool Wrapper ====== */
-static rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0};
+static rawSeqStore_t kNullRawSeqStore = {NULL, NULL, 0, 0, 0};
typedef ZSTDMT_bufferPool ZSTDMT_seqPool;
From 724b94ed182ec55401f365f3912715fc3ba97352 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Tue, 29 Sep 2020 18:12:32 -0400
Subject: [PATCH 22/51] ldm_getNextMatch fixed return values
---
lib/compress/zstd_opt.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 075826b73..25168d6fe 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -824,19 +824,19 @@ static void ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
if (ldmSeqStore->pos >= ldmSeqStore->size) {
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
- return 1;
+ return;
}
rawSeq seq = ldm_splitSequenceAndUpdateSeqStore(ldmSeqStore, remainingBytes);
if (seq.offset == 0) {
*matchStartPosInBlock = UINT32_MAX;
*matchEndPosInBlock = UINT32_MAX;
- return 1;
+ return;
}
*matchStartPosInBlock = currPosInBlock + seq.litLength;
*matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
*matchOffset = seq.offset;
- return 0;
+ return;
}
/* Adds an LDM if it's long enough */
From bff5785fd58fd2197da4a8252fdae2a5a0379f33 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 30 Sep 2020 11:06:44 -0400
Subject: [PATCH 23/51] Address mixed variables C90 warning
---
lib/compress/zstd_opt.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 25168d6fe..1c1700328 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -820,16 +820,18 @@ static void ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
U32* matchStartPosInBlock, U32* matchEndPosInBlock,
U32* matchOffset, U32 currPosInBlock,
U32 remainingBytes) {
+ rawSeq seq;
/* Setting match end position to MAX will ensure we never use an LDM during this block */
if (ldmSeqStore->pos >= ldmSeqStore->size) {
- *matchStartPosInBlock = UINT32_MAX;
- *matchEndPosInBlock = UINT32_MAX;
+ *matchStartPosInBlock = UINT_MAX;
+ *matchEndPosInBlock = UINT_MAX;
return;
}
- rawSeq seq = ldm_splitSequenceAndUpdateSeqStore(ldmSeqStore, remainingBytes);
+
+ seq = ldm_splitSequenceAndUpdateSeqStore(ldmSeqStore, remainingBytes);
if (seq.offset == 0) {
- *matchStartPosInBlock = UINT32_MAX;
- *matchEndPosInBlock = UINT32_MAX;
+ *matchStartPosInBlock = UINT_MAX;
+ *matchEndPosInBlock = UINT_MAX;
return;
}
@@ -843,21 +845,18 @@ static void ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
U32 matchOffset, U32 currPosInBlock) {
- /* Check that current block position is not outside of the match */
- if (currPosInBlock < matchStartPosInBlock || currPosInBlock >= matchEndPosInBlock)
- return;
-
U32 posDiff = currPosInBlock - matchStartPosInBlock;
- /* TODO: Next step will enable adding LDMs in the middle of a match */
- if (posDiff > 0)
- return;
-
/* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
U32 candidateMatchLength = matchEndPosInBlock - matchStartPosInBlock - posDiff;
- if (candidateMatchLength < ZSTD_LDM_MINMATCH_MIN)
- return;
U32 candidateOffCode = matchOffset + posDiff + ZSTD_REP_MOVE;
+ /* Ensure that current block position is not outside of the match */
+ if (currPosInBlock < matchStartPosInBlock ||
+ currPosInBlock >= matchEndPosInBlock ||
+ posDiff > 0 || /* As a next evolution we can enable adding LDMs in the middle of a match */
+ candidateMatchLength < ZSTD_LDM_MINMATCH_MIN)
+ return;
+
if (*nbMatches == 0) {
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
From 65f9cfeeec29724b5d48da088f7f325af1cfc01a Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 30 Sep 2020 11:25:51 -0400
Subject: [PATCH 24/51] Add extra bounds check to prevent heap access after
free ASAN error
---
lib/compress/zstd_opt.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 1c1700328..d6c728462 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -986,11 +986,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
* since the base shifts back 131072 bytes (1 block) after the first block. The consequence is that
* we should insert 35373 bytes into the 8th block, rather than 35373 bytes into the 7th block.
*/
- if (ms->ldmSeqStore.size > 0) {
+ if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos != ms->ldmSeqStore.size) {
if (ms->ldmSeqStore.base != base) {
int baseDiff = (int)(ms->ldmSeqStore.base - base);
ms->ldmSeqStore.seq[ms->ldmSeqStore.pos].litLength += baseDiff;
- ms->ldmSeqStore.base = ms->window.base;
+ ms->ldmSeqStore.base = base;
}
ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
From 4793ae3b8429dbd1d59410a62df0dff0990f6861 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 30 Sep 2020 12:54:45 -0400
Subject: [PATCH 25/51] Prevent duplicate LDMs from being inserted
---
lib/compress/zstd_opt.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index d6c728462..088282ca2 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -868,6 +868,10 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
* the ldm match down as necessary.
*/
if (candidateMatchLength == matches[*nbMatches-1].len) {
+ if (candidateOffCode == matches[*nbMatches-1].off) {
+ /* No need to insert the match if it's the exact same */
+ return;
+ }
U32 candidateMatchIdx = *nbMatches;
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
From cfd2aec1b71cb8d34ab3926a2150be8147d869b9 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 30 Sep 2020 13:25:02 -0400
Subject: [PATCH 26/51] Add unit tests into playTests.sh
---
tests/playTests.sh | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/tests/playTests.sh b/tests/playTests.sh
index 7f75d8506..ee3ef42f0 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -1207,6 +1207,7 @@ roundTripTest -g1000K "1 --single-thread --long"
roundTripTest -g517K "6 --single-thread --long"
roundTripTest -g516K "16 --single-thread --long"
roundTripTest -g518K "19 --single-thread --long"
+roundTripTest -g2M "22 --single-thread --ultra --long"
fileRoundTripTest -g5M "3 --single-thread --long"
@@ -1216,6 +1217,7 @@ then
println "\n===> zstdmt round-trip tests "
roundTripTest -g4M "1 -T0"
roundTripTest -g8M "3 -T2"
+ roundTripTest -g8M "3 -T0 --long"
roundTripTest -g8000K "2 --threads=2"
fileRoundTripTest -g4M "19 -T2 -B1M"
@@ -1334,6 +1336,33 @@ roundTripTest -g1M -P50 "1 --single-thread --long=29" " --long=28 --memory=512MB
roundTripTest -g1M -P50 "1 --single-thread --long=29" " --zstd=wlog=28 --memory=512MB"
+println "\n===> zstd long distance matching with optimal parser compressed size tests "
+optCSize16=$(datagen -g511K | zstd -16 -c | wc -c)
+longCSize16=$(datagen -g511K | zstd -16 --long -c | wc -c)
+optCSize19=$(datagen -g2M | zstd -19 -c | wc -c)
+longCSize19=$(datagen -g2M | zstd -19 --long -c | wc -c)
+optCSize19wlog23=$(datagen -g2M | zstd -19 -c --zstd=wlog=23 | wc -c)
+longCSize19wlog23=$(datagen -g2M | zstd -19 -c --long=23 | wc -c)
+optCSize19wlog27=$(datagen -g5M | zstd -19 -c --zstd=wlog=27 | wc -c)
+longCSize19wlog27=$(datagen -g5M | zstd -19 -c --long=27 | wc -c)
+optCSize22=$(datagen -g900K | zstd -22 --ultra -c | wc -c)
+longCSize22=$(datagen -g900K | zstd -22 --ultra --long -c | wc -c)
+if [ "$longCSize16" -gt "$optCSize16" ]; then
+ echo using --long on compression level 16 should not cause compressed size regression
+ exit 1
+elif [ "$longCSize19" -gt "$optCSize19" ]; then
+ echo using --long on compression level 19 should not cause compressed size regression
+ exit 1
+elif [ "$longCSize19wlog23" -gt "$optCSize19wlog23" ]; then
+ echo using --long on compression level 19 with wLog=23 should not cause compressed size regression
+ exit 1
+elif [ "$longCSize19wlog27" -gt "$optCSize19wlog27" ]; then
+ echo using --long on compression level 19 with wLog=27 should not cause compressed size regression
+ exit 1
+elif [ "$longCSize22" -gt "$optCSize22" ]; then
+ echo using --long on compression level 22 should not cause compressed size regression
+ exit 1
+fi
if [ "$1" != "--test-large-data" ]; then
From ef823e02996b25fcb4166b017d174ff788d95763 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 30 Sep 2020 17:20:47 -0400
Subject: [PATCH 27/51] Remove rawSeqStore.base and add
rawSeqStore.posInSequence
---
lib/compress/zstd_compress.c | 2 +-
lib/compress/zstd_compress_internal.h | 2 +-
lib/compress/zstdmt_compress.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 4958239cf..3a5ad0255 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2354,7 +2354,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
src, srcSize);
assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
} else if (zc->appliedParams.ldmParams.enableLdm) {
- rawSeqStore_t ldmSeqStore = {NULL, NULL, 0, 0, 0};
+ rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0, 0};
ldmSeqStore.seq = zc->ldmSequences;
ldmSeqStore.capacity = zc->maxNbLdmSequences;
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index 9eba078b4..da5720e95 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -94,8 +94,8 @@ typedef struct {
typedef struct {
rawSeq* seq; /* The start of the sequences */
- BYTE const* base; /* The match state window base when LDMs were generated */
size_t pos; /* The position where reading stopped. <= size. */
+ size_t posInSequence; /* The position to start at within the sequence when starting a new block */
size_t size; /* The number of sequences. <= capacity. */
size_t capacity; /* The capacity starting from `seq` pointer */
} rawSeqStore_t;
diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
index 6b3e8bee5..f789ae5bf 100644
--- a/lib/compress/zstdmt_compress.c
+++ b/lib/compress/zstdmt_compress.c
@@ -266,7 +266,7 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
/* ===== Seq Pool Wrapper ====== */
-static rawSeqStore_t kNullRawSeqStore = {NULL, NULL, 0, 0, 0};
+static rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
typedef ZSTDMT_bufferPool ZSTDMT_seqPool;
@@ -277,7 +277,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
static rawSeqStore_t bufferToSeq(buffer_t buffer)
{
- rawSeqStore_t seq = {NULL, NULL, 0, 0, 0};
+ rawSeqStore_t seq = {NULL, 0, 0, 0, 0};
seq.seq = (rawSeq*)buffer.start;
seq.capacity = buffer.capacity / sizeof(rawSeq);
return seq;
From a1ef2db5b25e6f8a0564fcf6fd961d60015fe878 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 30 Sep 2020 19:14:31 -0400
Subject: [PATCH 28/51] Add ldm_calculateMatchRange() function
---
lib/compress/zstd_compress_internal.h | 5 +-
lib/compress/zstd_opt.c | 92 ++++++++++++++++++++-------
2 files changed, 71 insertions(+), 26 deletions(-)
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index da5720e95..770adefc1 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -94,8 +94,9 @@ typedef struct {
typedef struct {
rawSeq* seq; /* The start of the sequences */
- size_t pos; /* The position where reading stopped. <= size. */
- size_t posInSequence; /* The position to start at within the sequence when starting a new block */
+ size_t pos; /* The index in this seqStore where reading stopped. <= size. */
+ size_t posInSequence; /* The position within the rawSeq at index 'pos' where reading
+ stopped. */
size_t size; /* The number of sequences. <= capacity. */
size_t capacity; /* The capacity starting from `seq` pointer */
} rawSeqStore_t;
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 088282ca2..9e38996e3 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,6 +768,67 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM helper functions
*********************************/
+/* Moves forward in rawSeqStore by nbBytes bytes, which will updating the fields
+ * 'pos' and 'posInSequence' accordingly.
+ */
+static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
+ while (nbBytes && ldmSeqStore->pos < ldmSeqStore->size) {
+ rawSeq currSeq;
+ currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+
+ if (nbBytes <= currSeq.litLength) {
+ ldmSeqStore->posInSequence += nbBytes;
+ return;
+ } else {
+ nbBytes -= currSeq.litLength;
+ }
+
+ if (nbBytes < currSeq.matchLength) {
+ ldmSeqStore->posInSequence += nbBytes;
+ return;
+ } else {
+ nbBytes -= currSeq.matchLength;
+ ldmSeqStore->pos++;
+ ldmSeqStore->posInSequence = 0;
+ }
+ }
+}
+
+static void ldm_calculateMatchRange(rawSeqStore_t* ldmSeqStore,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32* matchOffset, U32 currPosInBlock,
+ U32 remainingBytes, U32 currBlockEndPos) {
+ rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ U32 blockPosInSequence = ldmSeqStore->posInSequence + currPosInBlock;
+ U32 literalsBytesLeft = blockPosInSequence < currSeq.litLength ?
+ currSeq.litLength - blockPosInSequence : 0;
+ /* In this case, the match is further in the block than currPosInBlock */
+ if (literalsBytesLeft) {
+ if (literalsBytesLeft >= remainingBytes) {
+ /* If there are more literal bytes than bytes remaining in block, no ldm */
+ *matchStartPosInBlock = UINT_MAX;
+ *matchEndPosInBlock = UINT_MAX;
+ ldmSeqStore->pos++;
+ ldmSeqStore->posInSequence = 0;
+ return;
+ }
+ }
+
+ *matchStartPosInBlock = currPosInBlock + literalsBytesLeft;
+ *matchEndPosInBlock = *matchStartPosInBlock + currSeq.matchLength;
+ *matchOffset = currSeq.offset;
+
+ /* Match ends after the block ends, we can't use the whole match */
+ if (*matchEndPosInBlock > currBlockEndPos) {
+ *matchEndPosInBlock = currBlockEndPos;
+ ldmSeqStore->posInSequence += (currBlockEndPos - currPosInBlock);
+ } else {
+ /* We can use the entire match */
+ ldmSeqStore->posInSequence = 0;
+ ldmSeqStore->pos++;
+ }
+}
+
/* Skips past srcSize bytes in an ldm seqstore */
static void ldm_skipBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t bytesToSkip) {
while (bytesToSkip > 0 && ldmSeqStore->pos < ldmSeqStore->size) {
@@ -828,13 +889,14 @@ static void ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
return;
}
- seq = ldm_splitSequenceAndUpdateSeqStore(ldmSeqStore, remainingBytes);
+ /*seq = ldm_splitSequenceAndUpdateSeqStore(ldmSeqStore, remainingBytes);
if (seq.offset == 0) {
*matchStartPosInBlock = UINT_MAX;
*matchEndPosInBlock = UINT_MAX;
return;
- }
+ }*/
+ ldm_calculateMatchRange(ldmSeqStore, matchStartPosInBlock, matchEndPosInBlock, matchOffset, remainingBytes);
*matchStartPosInBlock = currPosInBlock + seq.litLength;
*matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
*matchOffset = seq.offset;
@@ -905,7 +967,7 @@ static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32
* over the end of an ldm match. As such, we need to correct for these "overshoots"
*/
U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
- ldm_skipBytesInSeqStore(ldmSeqStore, posOvershoot);
+ ldm_moveForwardBytesInSeqStore(ldmSeqStore, posOvershoot);
}
ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
matchEndPosInBlock, matchOffset,
@@ -972,25 +1034,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
- /* It seems that if the ldm seqstore was calculated using a different base, we actually have to
- * apply a correction to line it up with the block itself. This applies to multi-threaded cases
- * where the block it can be the case that the LDMs were generated starting at a different
- * block. By adding baseDiff to the litLength of seq, we pad out that base difference.
- *
- * For example, I found that when compressing dickens from silesia, the first LDM according to the seqStore is:
- * (of:951277 ml:1362 ll: 952876)
- *
- * And as such, we might expect to insert the match in the 7th block at:
- * pos_in_block 35373 == 952877 - 131072 * 7
- * I.e., at position 35373 the 7th block.
- *
- * Surprisingly, the correct place to insert is in the 8th block at
- * pos_in_block 35373 = 1083948 - 131072 * 8
- *
- * since the base shifts back 131072 bytes (1 block) after the first block. The consequence is that
- * we should insert 35373 bytes into the 8th block, rather than 35373 bytes into the 7th block.
- */
- if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos != ms->ldmSeqStore.size) {
+ /*if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos != ms->ldmSeqStore.size) {
if (ms->ldmSeqStore.base != base) {
int baseDiff = (int)(ms->ldmSeqStore.base - base);
ms->ldmSeqStore.seq[ms->ldmSeqStore.pos].litLength += baseDiff;
@@ -999,7 +1043,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
(U32)(ip-istart), (U32)(iend-ip));
- }
+ }*/
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
@@ -1260,7 +1304,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
if (ldmEndPosInBlock < srcSize) {
/* This can occur if after adding the final match in an ldm seq store within this block,
ip goes to the end of the block without activating a check for ldm_getNextMatch */
- ldm_skipBytesInSeqStore(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
+ ldm_moveForwardBytesInSeqStore(ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
}
/* Return the last literals size */
return (size_t)(iend - anchor);
From 7348b40a87c61307c026ae5291202f22327059e9 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 30 Sep 2020 19:45:40 -0400
Subject: [PATCH 29/51] Adjustments to ldm_calculateMatchRange() to calculate
bounds correctly
---
lib/compress/zstd_opt.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 9e38996e3..5f7466b9b 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -799,29 +799,29 @@ static void ldm_calculateMatchRange(rawSeqStore_t* ldmSeqStore,
U32* matchOffset, U32 currPosInBlock,
U32 remainingBytes, U32 currBlockEndPos) {
rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- U32 blockPosInSequence = ldmSeqStore->posInSequence + currPosInBlock;
- U32 literalsBytesLeft = blockPosInSequence < currSeq.litLength ?
- currSeq.litLength - blockPosInSequence : 0;
- /* In this case, the match is further in the block than currPosInBlock */
+ U32 literalsBytesLeft = (ldmSeqStore->posInSequence < currSeq.litLength) ?
+ currSeq.litLength - ldmSeqStore->posInSequence :
+ 0;
+ /* In this case, the match is further in the block than currPosInBlock, and we are
+ currently in the literals section of the LDM */
if (literalsBytesLeft) {
if (literalsBytesLeft >= remainingBytes) {
/* If there are more literal bytes than bytes remaining in block, no ldm */
*matchStartPosInBlock = UINT_MAX;
*matchEndPosInBlock = UINT_MAX;
- ldmSeqStore->pos++;
- ldmSeqStore->posInSequence = 0;
+ ldm_moveForwardBytesInSeqStore(ldmSeqStore, remainingBytes);
return;
}
}
- *matchStartPosInBlock = currPosInBlock + literalsBytesLeft;
+ *matchStartPosInBlock = currPosInBlock + currSeq.litLength;
*matchEndPosInBlock = *matchStartPosInBlock + currSeq.matchLength;
*matchOffset = currSeq.offset;
/* Match ends after the block ends, we can't use the whole match */
if (*matchEndPosInBlock > currBlockEndPos) {
*matchEndPosInBlock = currBlockEndPos;
- ldmSeqStore->posInSequence += (currBlockEndPos - currPosInBlock);
+ ldm_moveForwardBytesInSeqStore(ldmSeqStore, currBlockEndPos - currPosInBlock);
} else {
/* We can use the entire match */
ldmSeqStore->posInSequence = 0;
From 0718aa70df196b5854ce4e40c4d5abf8e846ad19 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Thu, 1 Oct 2020 10:12:21 -0400
Subject: [PATCH 30/51] Refactor existing functions to use posInSequence
---
lib/compress/zstd_opt.c | 153 +++++++++++++++++++++-------------------
1 file changed, 81 insertions(+), 72 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 5f7466b9b..bafff8261 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,67 +768,6 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM helper functions
*********************************/
-/* Moves forward in rawSeqStore by nbBytes bytes, which will updating the fields
- * 'pos' and 'posInSequence' accordingly.
- */
-static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
- while (nbBytes && ldmSeqStore->pos < ldmSeqStore->size) {
- rawSeq currSeq;
- currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
-
- if (nbBytes <= currSeq.litLength) {
- ldmSeqStore->posInSequence += nbBytes;
- return;
- } else {
- nbBytes -= currSeq.litLength;
- }
-
- if (nbBytes < currSeq.matchLength) {
- ldmSeqStore->posInSequence += nbBytes;
- return;
- } else {
- nbBytes -= currSeq.matchLength;
- ldmSeqStore->pos++;
- ldmSeqStore->posInSequence = 0;
- }
- }
-}
-
-static void ldm_calculateMatchRange(rawSeqStore_t* ldmSeqStore,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock,
- U32* matchOffset, U32 currPosInBlock,
- U32 remainingBytes, U32 currBlockEndPos) {
- rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- U32 literalsBytesLeft = (ldmSeqStore->posInSequence < currSeq.litLength) ?
- currSeq.litLength - ldmSeqStore->posInSequence :
- 0;
- /* In this case, the match is further in the block than currPosInBlock, and we are
- currently in the literals section of the LDM */
- if (literalsBytesLeft) {
- if (literalsBytesLeft >= remainingBytes) {
- /* If there are more literal bytes than bytes remaining in block, no ldm */
- *matchStartPosInBlock = UINT_MAX;
- *matchEndPosInBlock = UINT_MAX;
- ldm_moveForwardBytesInSeqStore(ldmSeqStore, remainingBytes);
- return;
- }
- }
-
- *matchStartPosInBlock = currPosInBlock + currSeq.litLength;
- *matchEndPosInBlock = *matchStartPosInBlock + currSeq.matchLength;
- *matchOffset = currSeq.offset;
-
- /* Match ends after the block ends, we can't use the whole match */
- if (*matchEndPosInBlock > currBlockEndPos) {
- *matchEndPosInBlock = currBlockEndPos;
- ldm_moveForwardBytesInSeqStore(ldmSeqStore, currBlockEndPos - currPosInBlock);
- } else {
- /* We can use the entire match */
- ldmSeqStore->posInSequence = 0;
- ldmSeqStore->pos++;
- }
-}
-
/* Skips past srcSize bytes in an ldm seqstore */
static void ldm_skipBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t bytesToSkip) {
while (bytesToSkip > 0 && ldmSeqStore->pos < ldmSeqStore->size) {
@@ -876,6 +815,79 @@ static rawSeq ldm_splitSequenceAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore, U32
return currSeq;
}
+/* Moves forward in rawSeqStore by nbBytes bytes, which will updating the fields
+ * 'pos' and 'posInSequence' accordingly.
+ */
+static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
+ while (nbBytes && ldmSeqStore->pos < ldmSeqStore->size) {
+ rawSeq currSeq;
+ currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+
+ if (nbBytes <= currSeq.litLength) {
+ ldmSeqStore->posInSequence += nbBytes;
+ return;
+ } else {
+ ldmSeqStore->posInSequence += currSeq.litLength;
+ nbBytes -= currSeq.litLength;
+ }
+
+ if (nbBytes < currSeq.matchLength) {
+ ldmSeqStore->posInSequence += nbBytes;
+ return;
+ } else {
+ nbBytes -= currSeq.matchLength;
+ /* We have moved through this entire sequence - move the read pos
+ forward to the next sequence, and reset posInSequence */
+ ldmSeqStore->pos++;
+ ldmSeqStore->posInSequence = 0;
+ }
+ }
+}
+
+/* Calculates the beginning and end of a match, and updates ldmSeqStore as
+ * necessary.
+ * posInSequence can be either within the literals section, or within a match.
+ * If
+ */
+static void ldm_calculateMatchRange(rawSeqStore_t* ldmSeqStore,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32* matchOffset, U32 currPosInBlock,
+ U32 blockBytesRemaining) {
+ rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ U32 currBlockEndPos = currPosInBlock + blockBytesRemaining;
+ U32 literalsBytesRemaining = (ldmSeqStore->posInSequence < currSeq.litLength) ?
+ currSeq.litLength - ldmSeqStore->posInSequence :
+ 0;
+
+ /* In this case, the match is further in the block than currPosInBlock, and we are
+ currently in the literals section of the LDM */
+ if (literalsBytesRemaining) {
+ if (literalsBytesRemaining >= blockBytesRemaining) {
+ /* If there are more literal bytes than bytes remaining in block, no ldm */
+ *matchStartPosInBlock = UINT_MAX;
+ *matchEndPosInBlock = UINT_MAX;
+ ldm_moveForwardBytesInSeqStore(ldmSeqStore, blockBytesRemaining);
+ return;
+ }
+ }
+
+ /* Matches may be < MINMATCH by this process. In that case, we will reject them
+ when we are deciding whether or not to add the ldm */
+ *matchStartPosInBlock = currPosInBlock + literalsBytesRemaining;
+ *matchEndPosInBlock = *matchStartPosInBlock + currSeq.matchLength;
+ *matchOffset = currSeq.offset;
+
+ if (*matchEndPosInBlock > currBlockEndPos) {
+ /* Match ends after the block ends, we can't use the whole match */
+ *matchEndPosInBlock = currBlockEndPos;
+ ldm_moveForwardBytesInSeqStore(ldmSeqStore, currBlockEndPos - currPosInBlock);
+ } else {
+ /* We can use the entire match */
+ ldmSeqStore->posInSequence = 0;
+ ldmSeqStore->pos++;
+ }
+}
+
/* Fetch the next match in the ldm seq store */
static void ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
U32* matchStartPosInBlock, U32* matchEndPosInBlock,
@@ -896,10 +908,7 @@ static void ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
return;
}*/
- ldm_calculateMatchRange(ldmSeqStore, matchStartPosInBlock, matchEndPosInBlock, matchOffset, remainingBytes);
- *matchStartPosInBlock = currPosInBlock + seq.litLength;
- *matchEndPosInBlock = *matchStartPosInBlock + seq.matchLength;
- *matchOffset = seq.offset;
+ ldm_calculateMatchRange(ldmSeqStore, matchStartPosInBlock, matchEndPosInBlock, matchOffset, currPosInBlock, remainingBytes);
return;
}
@@ -970,8 +979,8 @@ static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32
ldm_moveForwardBytesInSeqStore(ldmSeqStore, posOvershoot);
}
ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
- matchEndPosInBlock, matchOffset,
- currPosInBlock, remainingBytes);
+ matchEndPosInBlock, matchOffset,
+ currPosInBlock, remainingBytes);
}
ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
}
@@ -1034,16 +1043,16 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
- /*if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos != ms->ldmSeqStore.size) {
- if (ms->ldmSeqStore.base != base) {
+ if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos != ms->ldmSeqStore.size) {
+ /*if (ms->ldmSeqStore.base != base) {
int baseDiff = (int)(ms->ldmSeqStore.base - base);
ms->ldmSeqStore.seq[ms->ldmSeqStore.pos].litLength += baseDiff;
ms->ldmSeqStore.base = base;
- }
+ }*/
ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
(U32)(ip-istart), (U32)(iend-ip));
- }*/
+ }
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
@@ -1304,7 +1313,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
if (ldmEndPosInBlock < srcSize) {
/* This can occur if after adding the final match in an ldm seq store within this block,
ip goes to the end of the block without activating a check for ldm_getNextMatch */
- ldm_moveForwardBytesInSeqStore(ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
+ ldm_moveForwardBytesInSeqStore(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
}
/* Return the last literals size */
return (size_t)(iend - anchor);
From 7dee62c2876b568e215aa63660c2d173d1e5ba1f Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Thu, 1 Oct 2020 10:13:06 -0400
Subject: [PATCH 31/51] Reset ldmSeqStore after initStats_ultra() pass for
btultra2
---
lib/compress/zstd_ldm.c | 1 -
lib/compress/zstd_opt.c | 2 ++
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 743344036..60a6e5878 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -578,7 +578,6 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
if (cParams->strategy >= ZSTD_btopt) {
size_t lastLLSize;
ms->ldmSeqStore = *rawSeqStore;
- ms->ldmSeqStore.base = ms->window.base;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
/* ldm seqstore will have changed during blockCompressor() call, make sure we copy those changes */
*rawSeqStore = ms->ldmSeqStore;
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index bafff8261..bb87e0580 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -1364,6 +1364,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
const void* src, size_t srcSize)
{
U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */
+ rawSeqStore_t tmpSeqStore = ms->ldmSeqStore;
ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep));
DEBUGLOG(4, "ZSTD_initStats_ultra (srcSize=%zu)", srcSize);
@@ -1380,6 +1381,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
ms->window.dictLimit += (U32)srcSize;
ms->window.lowLimit = ms->window.dictLimit;
ms->nextToUpdate = ms->window.dictLimit;
+ ms->ldmSeqStore = tmpSeqStore;
/* re-inforce weight of collected statistics */
ZSTD_upscaleStats(&ms->opt);
From 37617e23d7ec76a60072df3d34f2e3f52d408edc Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Thu, 1 Oct 2020 11:35:48 -0400
Subject: [PATCH 32/51] Correct matchLength calculation and remove unnecessary
functions
---
lib/compress/zstd_compress.c | 2 +-
lib/compress/zstd_opt.c | 165 +++++++++++------------------------
2 files changed, 52 insertions(+), 115 deletions(-)
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 3a5ad0255..f298cd895 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2336,7 +2336,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
if (curr > ms->nextToUpdate + 384)
ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
}
-
+
/* select and store sequences */
{ ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
size_t lastLLSize;
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index bb87e0580..7dfd1af64 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,54 +768,7 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM helper functions
*********************************/
-/* Skips past srcSize bytes in an ldm seqstore */
-static void ldm_skipBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t bytesToSkip) {
- while (bytesToSkip > 0 && ldmSeqStore->pos < ldmSeqStore->size) {
- rawSeq* seq = ldmSeqStore->seq + ldmSeqStore->pos;
- if (bytesToSkip <= seq->litLength) {
- /* Skip past srcSize literals */
- seq->litLength -= (U32)bytesToSkip;
- return;
- }
- bytesToSkip -= seq->litLength;
- seq->litLength = 0;
- if (bytesToSkip < seq->matchLength) {
- seq->matchLength -= (U32)bytesToSkip;
- return;
- }
- bytesToSkip -= seq->matchLength;
- seq->matchLength = 0;
- ldmSeqStore->pos++;
- }
-}
-
-/* Splits a sequence if it's across the boundary. May update pos in the seq store too
- * Pretty much the same function as maybeSplitSequence() in zstd_ldm.c
- */
-static rawSeq ldm_splitSequenceAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore, U32 remainingBytes) {
- rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- /* Case where don't split the match*/
- if (remainingBytes >= currSeq.litLength + currSeq.matchLength) {
- ldmSeqStore->pos++;
- return currSeq;
- }
- /* Need a split */
- if (remainingBytes <= currSeq.litLength) {
- currSeq.offset = 0;
- } else if (remainingBytes < currSeq.litLength + currSeq.matchLength) {
- currSeq.matchLength = remainingBytes - currSeq.litLength;
- }
-
- /* After deriving currSeq which is the sequence before the block boundary,
- * we now must skip past the remaining number of bytes unaccounted for,
- * and update the entry at pos in the seqStore, which represents the second half
- * of the sequence after the block boundary
- */
- ldm_skipBytesInSeqStore(ldmSeqStore, remainingBytes);
- return currSeq;
-}
-
-/* Moves forward in rawSeqStore by nbBytes bytes, which will updating the fields
+/* Moves forward in rawSeqStore by nbBytes, which will update the fields
* 'pos' and 'posInSequence' accordingly.
*/
static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
@@ -844,37 +797,48 @@ static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nb
}
}
-/* Calculates the beginning and end of a match, and updates ldmSeqStore as
- * necessary.
- * posInSequence can be either within the literals section, or within a match.
- * If
+/* Calculates the beginning and end of a match, and updates 'pos' and 'posInSequence'
+ * of the ldmSeqStore.
*/
-static void ldm_calculateMatchRange(rawSeqStore_t* ldmSeqStore,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock,
- U32* matchOffset, U32 currPosInBlock,
- U32 blockBytesRemaining) {
- rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- U32 currBlockEndPos = currPosInBlock + blockBytesRemaining;
- U32 literalsBytesRemaining = (ldmSeqStore->posInSequence < currSeq.litLength) ?
- currSeq.litLength - ldmSeqStore->posInSequence :
- 0;
+static void ldm_calculateNextMatch(rawSeqStore_t* ldmSeqStore,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32* matchOffset, U32 currPosInBlock,
+ U32 blockBytesRemaining) {
+ rawSeq currSeq;
+ U32 currBlockEndPos;
+ U32 literalsBytesRemaining;
+ U32 matchBytesRemaining;
- /* In this case, the match is further in the block than currPosInBlock, and we are
- currently in the literals section of the LDM */
- if (literalsBytesRemaining) {
- if (literalsBytesRemaining >= blockBytesRemaining) {
- /* If there are more literal bytes than bytes remaining in block, no ldm */
- *matchStartPosInBlock = UINT_MAX;
- *matchEndPosInBlock = UINT_MAX;
- ldm_moveForwardBytesInSeqStore(ldmSeqStore, blockBytesRemaining);
- return;
- }
+ /* Setting match end position to MAX to ensure we never use an LDM during this block */
+ if (ldmSeqStore->pos >= ldmSeqStore->size) {
+ *matchStartPosInBlock = UINT_MAX;
+ *matchEndPosInBlock = UINT_MAX;
+ return;
+ }
+
+ /* Calculate appropriate bytes left in matchLength and litLength after adjusting
+ based on ldmSeqStore->posInSequence */
+ currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ currBlockEndPos = currPosInBlock + blockBytesRemaining;
+ literalsBytesRemaining = (ldmSeqStore->posInSequence < currSeq.litLength) ?
+ currSeq.litLength - ldmSeqStore->posInSequence :
+ 0;
+ matchBytesRemaining = (literalsBytesRemaining == 0) ?
+ currSeq.matchLength - (ldmSeqStore->posInSequence - currSeq.litLength) :
+ currSeq.matchLength;
+
+ /* If there are more literal bytes than bytes remaining in block, no ldm */
+ if (literalsBytesRemaining >= blockBytesRemaining) {
+ *matchStartPosInBlock = UINT_MAX;
+ *matchEndPosInBlock = UINT_MAX;
+ ldm_moveForwardBytesInSeqStore(ldmSeqStore, blockBytesRemaining);
+ return;
}
/* Matches may be < MINMATCH by this process. In that case, we will reject them
when we are deciding whether or not to add the ldm */
*matchStartPosInBlock = currPosInBlock + literalsBytesRemaining;
- *matchEndPosInBlock = *matchStartPosInBlock + currSeq.matchLength;
+ *matchEndPosInBlock = *matchStartPosInBlock + matchBytesRemaining;
*matchOffset = currSeq.offset;
if (*matchEndPosInBlock > currBlockEndPos) {
@@ -882,36 +846,12 @@ static void ldm_calculateMatchRange(rawSeqStore_t* ldmSeqStore,
*matchEndPosInBlock = currBlockEndPos;
ldm_moveForwardBytesInSeqStore(ldmSeqStore, currBlockEndPos - currPosInBlock);
} else {
- /* We can use the entire match */
+ /* If we can use the whole match point the ldmSeqStore at the next match */
ldmSeqStore->posInSequence = 0;
ldmSeqStore->pos++;
}
}
-/* Fetch the next match in the ldm seq store */
-static void ldm_getNextMatch(rawSeqStore_t* ldmSeqStore,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock,
- U32* matchOffset, U32 currPosInBlock,
- U32 remainingBytes) {
- rawSeq seq;
- /* Setting match end position to MAX will ensure we never use an LDM during this block */
- if (ldmSeqStore->pos >= ldmSeqStore->size) {
- *matchStartPosInBlock = UINT_MAX;
- *matchEndPosInBlock = UINT_MAX;
- return;
- }
-
- /*seq = ldm_splitSequenceAndUpdateSeqStore(ldmSeqStore, remainingBytes);
- if (seq.offset == 0) {
- *matchStartPosInBlock = UINT_MAX;
- *matchEndPosInBlock = UINT_MAX;
- return;
- }*/
-
- ldm_calculateMatchRange(ldmSeqStore, matchStartPosInBlock, matchEndPosInBlock, matchOffset, currPosInBlock, remainingBytes);
- return;
-}
-
/* Adds an LDM if it's long enough */
static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
@@ -933,8 +873,8 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
matches[*nbMatches].off = candidateOffCode;
(*nbMatches)++;
} else if ((candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
- /* Maintain order of matches, which is first - increasing in matchlength,
- * and secondly - decreasing in offCode. Since matches in ldm seq store are likely
+ /* Maintain order of matches, which is firstly - increasing in matchlength,
+ * and secondly - decreasing in offCode. Since matches from the ldm seq store are likely
* to be the longest match found, we simply start at the end of the array and sift
* the ldm match down as necessary.
*/
@@ -973,12 +913,12 @@ static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32
if (currPosInBlock > *matchEndPosInBlock) {
/* The position at which ldm_handleLdm() is called is not necessarily
* at the end of a match from the ldm seq store, and will often be some bytes
- * over the end of an ldm match. As such, we need to correct for these "overshoots"
+ * over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
*/
U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
ldm_moveForwardBytesInSeqStore(ldmSeqStore, posOvershoot);
}
- ldm_getNextMatch(ldmSeqStore, matchStartPosInBlock,
+ ldm_calculateNextMatch(ldmSeqStore, matchStartPosInBlock,
matchEndPosInBlock, matchOffset,
currPosInBlock, remainingBytes);
}
@@ -1043,16 +983,13 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
- if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos != ms->ldmSeqStore.size) {
- /*if (ms->ldmSeqStore.base != base) {
- int baseDiff = (int)(ms->ldmSeqStore.base - base);
- ms->ldmSeqStore.seq[ms->ldmSeqStore.pos].litLength += baseDiff;
- ms->ldmSeqStore.base = base;
- }*/
- ldm_getNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ /* Get first match from ldm seq store if long mode is enabled */
+ if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
+ ldm_calculateNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
(U32)(ip-istart), (U32)(iend-ip));
}
+
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
@@ -1068,7 +1005,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
- if (ms->ldmSeqStore.size != 0) {
+ if (ms->ldmSeqStore.size != 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
ldm_handleLdm(&ms->ldmSeqStore, matches,
&nbMatches, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
@@ -1190,11 +1127,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 matchNb;
- if (ms->ldmSeqStore.size != 0) {
+ if (ms->ldmSeqStore.size != 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
ldm_handleLdm(&ms->ldmSeqStore, matches,
- &nbMatches, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(inr-istart), (U32)(iend-inr));
+ &nbMatches, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(inr-istart), (U32)(iend-inr));
}
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -1312,7 +1249,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
if (ldmEndPosInBlock < srcSize) {
/* This can occur if after adding the final match in an ldm seq store within this block,
- ip goes to the end of the block without activating a check for ldm_getNextMatch */
+ ip goes to the end of the block without activating a check for ldm_calculateNextMatch */
ldm_moveForwardBytesInSeqStore(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
}
/* Return the last literals size */
From 1a687b3fcb853b9437d33c853800192131b08f95 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Thu, 1 Oct 2020 11:40:52 -0400
Subject: [PATCH 33/51] Improve documentation of relevant structs
---
lib/compress/zstd_compress_internal.h | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index 770adefc1..954af31f9 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -82,23 +82,23 @@ typedef struct {
} ZSTD_entropyCTables_t;
typedef struct {
- U32 off;
- U32 len;
+ U32 off; /* Offset code for the match */
+ U32 len; /* Raw length of match */
} ZSTD_match_t;
typedef struct {
- U32 offset;
- U32 litLength;
- U32 matchLength;
+ U32 offset; /* Offset of sequence */
+ U32 litLength; /* Length of literals prior to match */
+ U32 matchLength; /* Raw length of match */
} rawSeq;
typedef struct {
- rawSeq* seq; /* The start of the sequences */
- size_t pos; /* The index in this seqStore where reading stopped. <= size. */
- size_t posInSequence; /* The position within the rawSeq at index 'pos' where reading
- stopped. */
- size_t size; /* The number of sequences. <= capacity. */
- size_t capacity; /* The capacity starting from `seq` pointer */
+ rawSeq* seq; /* The start of the sequences */
+ size_t pos; /* The index in seq where reading stopped. pos <= size. */
+ size_t posInSequence; /* The position within the sequence at seq[pos] where reading
+ stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */
+ size_t size; /* The number of sequences. <= capacity. */
+ size_t capacity; /* The capacity starting from `seq` pointer */
} rawSeqStore_t;
typedef struct {
From 10647924f1c0e5daa35a43c8a1af848d09185b09 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Thu, 1 Oct 2020 11:47:35 -0400
Subject: [PATCH 34/51] Make function descriptions more accurate
---
lib/compress/zstd_compress.c | 2 +-
lib/compress/zstd_compress_internal.h | 2 +-
lib/compress/zstd_ldm.c | 3 +-
lib/compress/zstd_opt.c | 49 ++++++++++++++-------------
4 files changed, 29 insertions(+), 27 deletions(-)
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index f298cd895..3a5ad0255 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2336,7 +2336,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
if (curr > ms->nextToUpdate + 384)
ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
}
-
+
/* select and store sequences */
{ ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);
size_t lastLLSize;
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index 954af31f9..179e4f7bb 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -82,7 +82,7 @@ typedef struct {
} ZSTD_entropyCTables_t;
typedef struct {
- U32 off; /* Offset code for the match */
+ U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */
U32 len; /* Raw length of match */
} ZSTD_match_t;
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 60a6e5878..341877858 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -579,8 +579,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
size_t lastLLSize;
ms->ldmSeqStore = *rawSeqStore;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
- /* ldm seqstore will have changed during blockCompressor() call, make sure we copy those changes */
- *rawSeqStore = ms->ldmSeqStore;
+ *rawSeqStore = ms->ldmSeqStore; /* Persist changes to ldmSeqStore during blockCompressor() */
return lastLLSize;
}
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 7dfd1af64..7efae9b87 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,14 +768,13 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM helper functions
*********************************/
-/* Moves forward in rawSeqStore by nbBytes, which will update the fields
- * 'pos' and 'posInSequence' accordingly.
+/* ldm_moveForwardBytesInSeqStore():
+ * Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
*/
static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
while (nbBytes && ldmSeqStore->pos < ldmSeqStore->size) {
rawSeq currSeq;
currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
-
if (nbBytes <= currSeq.litLength) {
ldmSeqStore->posInSequence += nbBytes;
return;
@@ -783,7 +782,6 @@ static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nb
ldmSeqStore->posInSequence += currSeq.litLength;
nbBytes -= currSeq.litLength;
}
-
if (nbBytes < currSeq.matchLength) {
ldmSeqStore->posInSequence += nbBytes;
return;
@@ -797,13 +795,14 @@ static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nb
}
}
-/* Calculates the beginning and end of a match, and updates 'pos' and 'posInSequence'
- * of the ldmSeqStore.
+/* ldm_getNextMatchAndUpdateSeqStore():
+ * Calculates the beginning and end of the next match in the current block.
+ * Updates 'pos' and 'posInSequence' of the ldmSeqStore.
*/
-static void ldm_calculateNextMatch(rawSeqStore_t* ldmSeqStore,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock,
- U32* matchOffset, U32 currPosInBlock,
- U32 blockBytesRemaining) {
+static void ldm_getNextMatchAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32* matchOffset, U32 currPosInBlock,
+ U32 blockBytesRemaining) {
rawSeq currSeq;
U32 currBlockEndPos;
U32 literalsBytesRemaining;
@@ -827,7 +826,7 @@ static void ldm_calculateNextMatch(rawSeqStore_t* ldmSeqStore,
currSeq.matchLength - (ldmSeqStore->posInSequence - currSeq.litLength) :
currSeq.matchLength;
- /* If there are more literal bytes than bytes remaining in block, no ldm */
+ /* If there are more literal bytes than bytes remaining in block, no ldm is possible */
if (literalsBytesRemaining >= blockBytesRemaining) {
*matchStartPosInBlock = UINT_MAX;
*matchEndPosInBlock = UINT_MAX;
@@ -852,7 +851,10 @@ static void ldm_calculateNextMatch(rawSeqStore_t* ldmSeqStore,
}
}
-/* Adds an LDM if it's long enough */
+/* ldm_maybeAddLdm():
+ * Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
+ * and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
+ */
static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 matchStartPosInBlock, U32 matchEndPosInBlock,
U32 matchOffset, U32 currPosInBlock) {
@@ -865,7 +867,7 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
if (currPosInBlock < matchStartPosInBlock ||
currPosInBlock >= matchEndPosInBlock ||
posDiff > 0 || /* As a next evolution we can enable adding LDMs in the middle of a match */
- candidateMatchLength < ZSTD_LDM_MINMATCH_MIN)
+ candidateMatchLength < MINMATCH)
return;
if (*nbMatches == 0) {
@@ -879,17 +881,18 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
* the ldm match down as necessary.
*/
if (candidateMatchLength == matches[*nbMatches-1].len) {
+ U32 candidateMatchIdx;
if (candidateOffCode == matches[*nbMatches-1].off) {
/* No need to insert the match if it's the exact same */
return;
}
- U32 candidateMatchIdx = *nbMatches;
+ candidateMatchIdx = *nbMatches;
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
if (candidateOffCode != matches[*nbMatches-1].off) {
while (candidateMatchIdx > 0 &&
- matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
- matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
+ matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
+ matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
ZSTD_match_t tmp = matches[candidateMatchIdx - 1];
matches[candidateMatchIdx - 1] = matches[candidateMatchIdx];
matches[candidateMatchIdx] = tmp;
@@ -918,9 +921,9 @@ static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32
U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
ldm_moveForwardBytesInSeqStore(ldmSeqStore, posOvershoot);
}
- ldm_calculateNextMatch(ldmSeqStore, matchStartPosInBlock,
- matchEndPosInBlock, matchOffset,
- currPosInBlock, remainingBytes);
+ ldm_getNextMatchAndUpdateSeqStore(ldmSeqStore, matchStartPosInBlock,
+ matchEndPosInBlock, matchOffset,
+ currPosInBlock, remainingBytes);
}
ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
}
@@ -985,9 +988,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
/* Get first match from ldm seq store if long mode is enabled */
if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
- ldm_calculateNextMatch(&ms->ldmSeqStore, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend-ip));
+ ldm_getNextMatchAndUpdateSeqStore(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend-ip));
}
/* init */
@@ -1249,7 +1252,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
if (ldmEndPosInBlock < srcSize) {
/* This can occur if after adding the final match in an ldm seq store within this block,
- ip goes to the end of the block without activating a check for ldm_calculateNextMatch */
+ ip reaches end of the block without calling ldm_getNextMatchAndUpdateSeqStore() */
ldm_moveForwardBytesInSeqStore(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
}
/* Return the last literals size */
From 429dec4f42619f469c93f2e09373c3243a98bf40 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Thu, 1 Oct 2020 12:07:18 -0400
Subject: [PATCH 35/51] Add DEBUGLOG() calls in ldm helpers
---
lib/compress/zstd_opt.c | 8 ++++++--
tests/playTests.sh | 5 -----
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 7efae9b87..a7618c872 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -849,6 +849,8 @@ static void ldm_getNextMatchAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
ldmSeqStore->posInSequence = 0;
ldmSeqStore->pos++;
}
+ DEBUGLOG(6, "ldm_getNextMatchAndUpdateSeqStore(): got an ldm that beginning at pos: %u, end at pos: %u, with offset: %u",
+ *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset);
}
/* ldm_maybeAddLdm():
@@ -870,6 +872,8 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
candidateMatchLength < MINMATCH)
return;
+ DEBUGLOG(6, "ldm_maybeAddLdm(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
+ candidateOffCode, candidateMatchLength, currPosInBlock);
if (*nbMatches == 0) {
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
@@ -985,14 +989,14 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 ldmStartPosInBlock = 0;
U32 ldmEndPosInBlock = 0;
U32 ldmOffset = 0;
-
+
/* Get first match from ldm seq store if long mode is enabled */
if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
ldm_getNextMatchAndUpdateSeqStore(&ms->ldmSeqStore, &ldmStartPosInBlock,
&ldmEndPosInBlock, &ldmOffset,
(U32)(ip-istart), (U32)(iend-ip));
}
-
+
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
diff --git a/tests/playTests.sh b/tests/playTests.sh
index ee3ef42f0..3959a8f3a 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -1343,8 +1343,6 @@ optCSize19=$(datagen -g2M | zstd -19 -c | wc -c)
longCSize19=$(datagen -g2M | zstd -19 --long -c | wc -c)
optCSize19wlog23=$(datagen -g2M | zstd -19 -c --zstd=wlog=23 | wc -c)
longCSize19wlog23=$(datagen -g2M | zstd -19 -c --long=23 | wc -c)
-optCSize19wlog27=$(datagen -g5M | zstd -19 -c --zstd=wlog=27 | wc -c)
-longCSize19wlog27=$(datagen -g5M | zstd -19 -c --long=27 | wc -c)
optCSize22=$(datagen -g900K | zstd -22 --ultra -c | wc -c)
longCSize22=$(datagen -g900K | zstd -22 --ultra --long -c | wc -c)
if [ "$longCSize16" -gt "$optCSize16" ]; then
@@ -1356,9 +1354,6 @@ elif [ "$longCSize19" -gt "$optCSize19" ]; then
elif [ "$longCSize19wlog23" -gt "$optCSize19wlog23" ]; then
echo using --long on compression level 19 with wLog=23 should not cause compressed size regression
exit 1
-elif [ "$longCSize19wlog27" -gt "$optCSize19wlog27" ]; then
- echo using --long on compression level 19 with wLog=27 should not cause compressed size regression
- exit 1
elif [ "$longCSize22" -gt "$optCSize22" ]; then
echo using --long on compression level 22 should not cause compressed size regression
exit 1
From c87d2e586619ff9d5b91021fab0f56b9dea0eecd Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Thu, 1 Oct 2020 16:14:41 -0400
Subject: [PATCH 36/51] Prefix new static ldm helpers with ZSTD_opt
---
lib/compress/zstd_opt.c | 99 +++++++++++++++++++++--------------------
1 file changed, 51 insertions(+), 48 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index a7618c872..fa3587bed 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -764,17 +764,17 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
}
}
-/*-*******************************
-* LDM helper functions
-*********************************/
+/*************************
+* LDM helper functions *
+*************************/
-/* ldm_moveForwardBytesInSeqStore():
+/* ZSTD_opt_skipBytesInLdmSeqStore():
* Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
*/
-static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
+static void ZSTD_opt_skipBytesInLdmSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
while (nbBytes && ldmSeqStore->pos < ldmSeqStore->size) {
- rawSeq currSeq;
- currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ assert(ldmSeqStore->posInSequence <= currSeq.matchLength + currSeq.litLength);
if (nbBytes <= currSeq.litLength) {
ldmSeqStore->posInSequence += nbBytes;
return;
@@ -795,14 +795,14 @@ static void ldm_moveForwardBytesInSeqStore(rawSeqStore_t* ldmSeqStore, size_t nb
}
}
-/* ldm_getNextMatchAndUpdateSeqStore():
+/* ZSTD_opt_getNextLdmAndUpdateSeqStore():
* Calculates the beginning and end of the next match in the current block.
* Updates 'pos' and 'posInSequence' of the ldmSeqStore.
*/
-static void ldm_getNextMatchAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock,
- U32* matchOffset, U32 currPosInBlock,
- U32 blockBytesRemaining) {
+static void ZSTD_opt_getNextLdmAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock,
+ U32* matchOffset, U32 currPosInBlock,
+ U32 blockBytesRemaining) {
rawSeq currSeq;
U32 currBlockEndPos;
U32 literalsBytesRemaining;
@@ -814,10 +814,10 @@ static void ldm_getNextMatchAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
*matchEndPosInBlock = UINT_MAX;
return;
}
-
/* Calculate appropriate bytes left in matchLength and litLength after adjusting
based on ldmSeqStore->posInSequence */
currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ assert(ldmSeqStore->posInSequence <= currSeq.litLength + currSeq.matchLength);
currBlockEndPos = currPosInBlock + blockBytesRemaining;
literalsBytesRemaining = (ldmSeqStore->posInSequence < currSeq.litLength) ?
currSeq.litLength - ldmSeqStore->posInSequence :
@@ -830,7 +830,7 @@ static void ldm_getNextMatchAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
if (literalsBytesRemaining >= blockBytesRemaining) {
*matchStartPosInBlock = UINT_MAX;
*matchEndPosInBlock = UINT_MAX;
- ldm_moveForwardBytesInSeqStore(ldmSeqStore, blockBytesRemaining);
+ ZSTD_opt_skipBytesInLdmSeqStore(ldmSeqStore, blockBytesRemaining);
return;
}
@@ -843,36 +843,37 @@ static void ldm_getNextMatchAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
if (*matchEndPosInBlock > currBlockEndPos) {
/* Match ends after the block ends, we can't use the whole match */
*matchEndPosInBlock = currBlockEndPos;
- ldm_moveForwardBytesInSeqStore(ldmSeqStore, currBlockEndPos - currPosInBlock);
+ ZSTD_opt_skipBytesInLdmSeqStore(ldmSeqStore, currBlockEndPos - currPosInBlock);
} else {
/* If we can use the whole match point the ldmSeqStore at the next match */
ldmSeqStore->posInSequence = 0;
ldmSeqStore->pos++;
}
- DEBUGLOG(6, "ldm_getNextMatchAndUpdateSeqStore(): got an ldm that beginning at pos: %u, end at pos: %u, with offset: %u",
+ DEBUGLOG(6, "ZSTD_opt_getNextLdmAndUpdateSeqStore(): got an ldm that beginning at pos: %u, end at pos: %u, with offset: %u",
*matchStartPosInBlock, *matchEndPosInBlock, *matchOffset);
}
-/* ldm_maybeAddLdm():
+/* ZSTD_opt_maybeAddLdm():
* Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
* and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
*/
-static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
- U32 matchStartPosInBlock, U32 matchEndPosInBlock,
- U32 matchOffset, U32 currPosInBlock) {
+static void ZSTD_opt_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
+ U32 matchStartPosInBlock, U32 matchEndPosInBlock,
+ U32 matchOffset, U32 currPosInBlock) {
U32 posDiff = currPosInBlock - matchStartPosInBlock;
/* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
U32 candidateMatchLength = matchEndPosInBlock - matchStartPosInBlock - posDiff;
U32 candidateOffCode = matchOffset + posDiff + ZSTD_REP_MOVE;
/* Ensure that current block position is not outside of the match */
- if (currPosInBlock < matchStartPosInBlock ||
- currPosInBlock >= matchEndPosInBlock ||
- posDiff > 0 || /* As a next evolution we can enable adding LDMs in the middle of a match */
- candidateMatchLength < MINMATCH)
+ if (currPosInBlock < matchStartPosInBlock
+ || currPosInBlock >= matchEndPosInBlock
+ || posDiff > 0 /* As a next evolution we can enable adding LDMs in the middle of a match */
+ || candidateMatchLength < MINMATCH) {
return;
+ }
- DEBUGLOG(6, "ldm_maybeAddLdm(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
+ DEBUGLOG(6, "ZSTD_opt_maybeAddLdm(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
candidateOffCode, candidateMatchLength, currPosInBlock);
if (*nbMatches == 0) {
matches[*nbMatches].len = candidateMatchLength;
@@ -881,7 +882,7 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
} else if ((candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
/* Maintain order of matches, which is firstly - increasing in matchlength,
* and secondly - decreasing in offCode. Since matches from the ldm seq store are likely
- * to be the longest match found, we simply start at the end of the array and sift
+ * to be the longest match found, we simply start at the end of the array and bubble
* the ldm match down as necessary.
*/
if (candidateMatchLength == matches[*nbMatches-1].len) {
@@ -912,24 +913,26 @@ static void ldm_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
}
}
-/* Wrapper function to update and call ldm functions as necessary */
-static void ldm_handleLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
- U32 currPosInBlock, U32 remainingBytes) {
+/* ZSTD_opt_processLdm():
+ * Wrapper function to update ldm seq store and call ldm functions as necessary.
+ */
+static void ZSTD_opt_processLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
+ U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
+ U32 currPosInBlock, U32 remainingBytes) {
if (currPosInBlock >= *matchEndPosInBlock) {
if (currPosInBlock > *matchEndPosInBlock) {
- /* The position at which ldm_handleLdm() is called is not necessarily
+ /* The position at which ZSTD_opt_processLdm() is called is not necessarily
* at the end of a match from the ldm seq store, and will often be some bytes
* over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
*/
U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
- ldm_moveForwardBytesInSeqStore(ldmSeqStore, posOvershoot);
+ ZSTD_opt_skipBytesInLdmSeqStore(ldmSeqStore, posOvershoot);
}
- ldm_getNextMatchAndUpdateSeqStore(ldmSeqStore, matchStartPosInBlock,
+ ZSTD_opt_getNextLdmAndUpdateSeqStore(ldmSeqStore, matchStartPosInBlock,
matchEndPosInBlock, matchOffset,
currPosInBlock, remainingBytes);
}
- ldm_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
+ ZSTD_opt_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
}
@@ -992,11 +995,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
/* Get first match from ldm seq store if long mode is enabled */
if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
- ldm_getNextMatchAndUpdateSeqStore(&ms->ldmSeqStore, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend-ip));
+ ZSTD_opt_getNextLdmAndUpdateSeqStore(&ms->ldmSeqStore, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend-ip));
}
-
+
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
@@ -1013,10 +1016,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const ll0 = !litlen;
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
if (ms->ldmSeqStore.size != 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
- ldm_handleLdm(&ms->ldmSeqStore, matches,
- &nbMatches, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend - ip));
+ ZSTD_opt_processLdm(&ms->ldmSeqStore, matches,
+ &nbMatches, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(ip-istart), (U32)(iend - ip));
}
if (!nbMatches) { ip++; continue; }
@@ -1135,10 +1138,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
if (ms->ldmSeqStore.size != 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
- ldm_handleLdm(&ms->ldmSeqStore, matches,
- &nbMatches, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(inr-istart), (U32)(iend-inr));
+ ZSTD_opt_processLdm(&ms->ldmSeqStore, matches,
+ &nbMatches, &ldmStartPosInBlock,
+ &ldmEndPosInBlock, &ldmOffset,
+ (U32)(inr-istart), (U32)(iend-inr));
}
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -1256,8 +1259,8 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
if (ldmEndPosInBlock < srcSize) {
/* This can occur if after adding the final match in an ldm seq store within this block,
- ip reaches end of the block without calling ldm_getNextMatchAndUpdateSeqStore() */
- ldm_moveForwardBytesInSeqStore(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
+ ip reaches end of the block without calling ZSTD_opt_getNextLdmAndUpdateSeqStore() */
+ ZSTD_opt_skipBytesInLdmSeqStore(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
}
/* Return the last literals size */
return (size_t)(iend - anchor);
From b8bfc4e63deb241f058f90e22aad5bb49a3ef262 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Fri, 2 Oct 2020 09:49:35 -0400
Subject: [PATCH 37/51] Add cSize regression test to fuzzer.c
---
lib/compress/zstd_ldm.c | 2 ++
lib/compress/zstd_opt.c | 3 +++
tests/fuzzer.c | 38 ++++++++++++++++++++++++++++++++++++++
tests/playTests.sh | 2 +-
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 341877858..356549f36 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -575,6 +575,8 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
BYTE const* const iend = istart + srcSize;
/* Input positions */
BYTE const* ip = istart;
+
+ /* If using opt parser, use LDMs only as candidates rather than always accepting them */
if (cParams->strategy >= ZSTD_btopt) {
size_t lastLLSize;
ms->ldmSeqStore = *rawSeqStore;
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index fa3587bed..5211fc917 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -774,7 +774,9 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
static void ZSTD_opt_skipBytesInLdmSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
while (nbBytes && ldmSeqStore->pos < ldmSeqStore->size) {
rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
+ /* posInSequence necessarily must never represent a value beyond the sequence */
assert(ldmSeqStore->posInSequence <= currSeq.matchLength + currSeq.litLength);
+
if (nbBytes <= currSeq.litLength) {
ldmSeqStore->posInSequence += nbBytes;
return;
@@ -782,6 +784,7 @@ static void ZSTD_opt_skipBytesInLdmSeqStore(rawSeqStore_t* ldmSeqStore, size_t n
ldmSeqStore->posInSequence += currSeq.litLength;
nbBytes -= currSeq.litLength;
}
+
if (nbBytes < currSeq.matchLength) {
ldmSeqStore->posInSequence += nbBytes;
return;
diff --git a/tests/fuzzer.c b/tests/fuzzer.c
index 8b10078ac..82d2f119e 100644
--- a/tests/fuzzer.c
+++ b/tests/fuzzer.c
@@ -780,6 +780,44 @@ static int basicUnitTests(U32 const seed, double compressibility)
}
DISPLAYLEVEL(3, "OK \n");
+ DISPLAYLEVEL(3, "test%3i : testing ldm no regressions in size for opt parser : ", testNb++);
+ {
+ size_t cSizeLdm;
+ size_t cSizeNoLdm;
+ ZSTD_CCtx* const cctx = ZSTD_createCCtx();
+
+ RDG_genBuffer(CNBuffer, CNBuffSize, 0.5, 0.5, seed);
+
+ /* Enable checksum to verify round trip. */
+ CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));
+ CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1));
+ CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19));
+
+ /* Round trip once with ldm. */
+ cSizeLdm = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
+ CHECK_Z(cSizeLdm);
+ CHECK_Z(ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSizeLdm));
+
+ ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
+ CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));
+ CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 0));
+ CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19));
+
+ /* Round trip once without ldm. */
+ cSizeNoLdm = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
+ CHECK_Z(cSizeNoLdm);
+ CHECK_Z(ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSizeNoLdm));
+
+ if (cSizeLdm > cSizeNoLdm) {
+ DISPLAY("Using long mode should not cause regressions for btopt+\n");
+ testResult = 1;
+ goto _output_error;
+ }
+
+ ZSTD_freeCCtx(cctx);
+ }
+ DISPLAYLEVEL(3, "OK \n");
+
/* Note: this test takes 0.5 seconds to run */
DISPLAYLEVEL(3, "test%3i : testing refPrefx vs refPrefx + ldm (size comparison) : ", testNb++);
{
diff --git a/tests/playTests.sh b/tests/playTests.sh
index 3959a8f3a..49371040e 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -1217,7 +1217,7 @@ then
println "\n===> zstdmt round-trip tests "
roundTripTest -g4M "1 -T0"
roundTripTest -g8M "3 -T2"
- roundTripTest -g8M "3 -T0 --long"
+ roundTripTest -g8M "19 -T0 --long"
roundTripTest -g8000K "2 --threads=2"
fileRoundTripTest -g4M "19 -T2 -B1M"
From d8b43a42023ee5bdbc1f093d4d418aad00b443cc Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Fri, 2 Oct 2020 13:47:54 -0400
Subject: [PATCH 38/51] Add explicit conversion of size_t to U32
---
lib/compress/zstd_opt.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 5211fc917..dcd9e1929 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -784,7 +784,7 @@ static void ZSTD_opt_skipBytesInLdmSeqStore(rawSeqStore_t* ldmSeqStore, size_t n
ldmSeqStore->posInSequence += currSeq.litLength;
nbBytes -= currSeq.litLength;
}
-
+
if (nbBytes < currSeq.matchLength) {
ldmSeqStore->posInSequence += nbBytes;
return;
@@ -823,10 +823,10 @@ static void ZSTD_opt_getNextLdmAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
assert(ldmSeqStore->posInSequence <= currSeq.litLength + currSeq.matchLength);
currBlockEndPos = currPosInBlock + blockBytesRemaining;
literalsBytesRemaining = (ldmSeqStore->posInSequence < currSeq.litLength) ?
- currSeq.litLength - ldmSeqStore->posInSequence :
+ currSeq.litLength - (U32)ldmSeqStore->posInSequence :
0;
matchBytesRemaining = (literalsBytesRemaining == 0) ?
- currSeq.matchLength - (ldmSeqStore->posInSequence - currSeq.litLength) :
+ currSeq.matchLength - ((U32)ldmSeqStore->posInSequence - currSeq.litLength) :
currSeq.matchLength;
/* If there are more literal bytes than bytes remaining in block, no ldm is possible */
From e96ea5d1478a8cbd29b8062907158fc826d24582 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Fri, 2 Oct 2020 15:27:06 -0400
Subject: [PATCH 39/51] Fix static analyze fuzzer.c error
---
tests/fuzzer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/fuzzer.c b/tests/fuzzer.c
index 82d2f119e..d18cb48c7 100644
--- a/tests/fuzzer.c
+++ b/tests/fuzzer.c
@@ -811,7 +811,7 @@ static int basicUnitTests(U32 const seed, double compressibility)
if (cSizeLdm > cSizeNoLdm) {
DISPLAY("Using long mode should not cause regressions for btopt+\n");
testResult = 1;
- goto _output_error;
+ goto _end;
}
ZSTD_freeCCtx(cctx);
From 88f72ed942d6ebdca5e551ca292d4dcc0820514b Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Fri, 2 Oct 2020 19:08:10 -0400
Subject: [PATCH 40/51] Correct incorrect offcode calculation
---
lib/compress/zstd_opt.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index dcd9e1929..69e73cb47 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -866,7 +866,7 @@ static void ZSTD_opt_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
U32 posDiff = currPosInBlock - matchStartPosInBlock;
/* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
U32 candidateMatchLength = matchEndPosInBlock - matchStartPosInBlock - posDiff;
- U32 candidateOffCode = matchOffset + posDiff + ZSTD_REP_MOVE;
+ U32 candidateOffCode = matchOffset + ZSTD_REP_MOVE;
/* Ensure that current block position is not outside of the match */
if (currPosInBlock < matchStartPosInBlock
@@ -1146,6 +1146,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
&ldmEndPosInBlock, &ldmOffset,
(U32)(inr-istart), (U32)(iend-inr));
}
+
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
continue;
From ddf8a3f1b91f91d16e00da9735169f4d1c0acdfe Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sun, 4 Oct 2020 21:46:47 -0400
Subject: [PATCH 41/51] Enable inclusion of mid-flight LDMs in opt parser
---
lib/compress/zstd_opt.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 69e73cb47..07b30f5f9 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -871,7 +871,6 @@ static void ZSTD_opt_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
/* Ensure that current block position is not outside of the match */
if (currPosInBlock < matchStartPosInBlock
|| currPosInBlock >= matchEndPosInBlock
- || posDiff > 0 /* As a next evolution we can enable adding LDMs in the middle of a match */
|| candidateMatchLength < MINMATCH) {
return;
}
From 031b7ec15fd4f0be2e62a67518ff6da9d7c19838 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sun, 4 Oct 2020 21:47:25 -0400
Subject: [PATCH 42/51] Disable LDM minMatch adjustment when using opt parser
---
lib/compress/zstd_ldm.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 356549f36..81dc3da19 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -27,13 +27,6 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params,
DEBUGLOG(4, "ZSTD_ldm_adjustParameters");
if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG;
if (!params->minMatchLength) params->minMatchLength = LDM_MIN_MATCH_LENGTH;
- if (cParams->strategy >= ZSTD_btopt) {
- /* Get out of the way of the optimal parser */
- U32 const minMatch = MAX(cParams->targetLength, params->minMatchLength);
- assert(minMatch >= ZSTD_LDM_MINMATCH_MIN);
- assert(minMatch <= ZSTD_LDM_MINMATCH_MAX);
- params->minMatchLength = minMatch;
- }
if (params->hashLog == 0) {
params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - LDM_HASH_RLOG);
assert(params->hashLog <= ZSTD_HASHLOG_MAX);
From 0325d878f230c2d394463b969f91d63bea8f66cc Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Sun, 4 Oct 2020 21:48:39 -0400
Subject: [PATCH 43/51] Remove bubbling down matches with longer offCode and
same matchLen
---
lib/compress/zstd_opt.c | 35 ++++++-----------------------------
1 file changed, 6 insertions(+), 29 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 07b30f5f9..b737d6bdd 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -882,36 +882,13 @@ static void ZSTD_opt_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
matches[*nbMatches].off = candidateOffCode;
(*nbMatches)++;
} else if ((candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
- /* Maintain order of matches, which is firstly - increasing in matchlength,
- * and secondly - decreasing in offCode. Since matches from the ldm seq store are likely
- * to be the longest match found, we simply start at the end of the array and bubble
- * the ldm match down as necessary.
- */
- if (candidateMatchLength == matches[*nbMatches-1].len) {
- U32 candidateMatchIdx;
- if (candidateOffCode == matches[*nbMatches-1].off) {
- /* No need to insert the match if it's the exact same */
- return;
- }
- candidateMatchIdx = *nbMatches;
- matches[*nbMatches].len = candidateMatchLength;
- matches[*nbMatches].off = candidateOffCode;
- if (candidateOffCode != matches[*nbMatches-1].off) {
- while (candidateMatchIdx > 0 &&
- matches[candidateMatchIdx].off > matches[candidateMatchIdx - 1].off &&
- matches[candidateMatchIdx].len == matches[candidateMatchIdx - 1].len) {
- ZSTD_match_t tmp = matches[candidateMatchIdx - 1];
- matches[candidateMatchIdx - 1] = matches[candidateMatchIdx];
- matches[candidateMatchIdx] = tmp;
- --candidateMatchIdx;
- }
- }
- (*nbMatches)++;
- } else {
- matches[*nbMatches].len = candidateMatchLength;
- matches[*nbMatches].off = candidateOffCode;
- (*nbMatches)++;
+ /* No need to insert the match if it's the exact same, or offCode is larger with same matchLen */
+ if (candidateMatchLength == matches[*nbMatches-1].len && candidateOffCode >= matches[*nbMatches-1].off) {
+ return;
}
+ matches[*nbMatches].len = candidateMatchLength;
+ matches[*nbMatches].off = candidateOffCode;
+ (*nbMatches)++;
}
}
From 0731b94e7c326584fc9f4b02139925ad20bc5e25 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Mon, 5 Oct 2020 10:50:49 -0400
Subject: [PATCH 44/51] Use kNullRawSeqStore constant in zstdmt_compress.c
---
lib/compress/zstdmt_compress.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
index f789ae5bf..06462fe5a 100644
--- a/lib/compress/zstdmt_compress.c
+++ b/lib/compress/zstdmt_compress.c
@@ -277,7 +277,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
static rawSeqStore_t bufferToSeq(buffer_t buffer)
{
- rawSeqStore_t seq = {NULL, 0, 0, 0, 0};
+ rawSeqStore_t seq = kNullRawSeqStore;
seq.seq = (rawSeq*)buffer.start;
seq.capacity = buffer.capacity / sizeof(rawSeq);
return seq;
From a5500cf2af8810a124141b46cb623e42f59800a0 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Mon, 5 Oct 2020 18:10:10 -0400
Subject: [PATCH 45/51] Refactor separate ldm variables all into one struct
---
lib/compress/zstd_ldm.c | 2 +-
lib/compress/zstd_opt.c | 139 +++++++++++++++++++---------------------
2 files changed, 67 insertions(+), 74 deletions(-)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 81dc3da19..623245567 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -574,7 +574,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
size_t lastLLSize;
ms->ldmSeqStore = *rawSeqStore;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
- *rawSeqStore = ms->ldmSeqStore; /* Persist changes to ldmSeqStore during blockCompressor() */
+ *rawSeqStore = ms->ldmSeqStore;
return lastLLSize;
}
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index b737d6bdd..472f9e8a8 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,10 +768,17 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM helper functions *
*************************/
-/* ZSTD_opt_skipBytesInLdmSeqStore():
+typedef struct {
+ rawSeqStore_t* seqStore; /* Reference to struct containing external candidates */
+ U32 startPosInBlock; /* Start position of the current match candidate */
+ U32 endPosInBlock; /* End position of the current match candidate */
+ U32 offset; /* Offset of the match candidate */
+} ZSTD_optLdm_t;
+
+/* ZSTD_opt_skipRawSeqStoreBytes():
* Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
*/
-static void ZSTD_opt_skipBytesInLdmSeqStore(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
+static void ZSTD_opt_skipRawSeqStoreBytes(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
while (nbBytes && ldmSeqStore->pos < ldmSeqStore->size) {
rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
/* posInSequence necessarily must never represent a value beyond the sequence */
@@ -798,84 +805,81 @@ static void ZSTD_opt_skipBytesInLdmSeqStore(rawSeqStore_t* ldmSeqStore, size_t n
}
}
-/* ZSTD_opt_getNextLdmAndUpdateSeqStore():
+/* ZSTD_opt_getNextMatchAndUpdateSeqStore():
* Calculates the beginning and end of the next match in the current block.
* Updates 'pos' and 'posInSequence' of the ldmSeqStore.
*/
-static void ZSTD_opt_getNextLdmAndUpdateSeqStore(rawSeqStore_t* ldmSeqStore,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock,
- U32* matchOffset, U32 currPosInBlock,
- U32 blockBytesRemaining) {
+static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
+ U32 blockBytesRemaining) {
rawSeq currSeq;
U32 currBlockEndPos;
U32 literalsBytesRemaining;
U32 matchBytesRemaining;
/* Setting match end position to MAX to ensure we never use an LDM during this block */
- if (ldmSeqStore->pos >= ldmSeqStore->size) {
- *matchStartPosInBlock = UINT_MAX;
- *matchEndPosInBlock = UINT_MAX;
+ if (optLdm->seqStore->pos >= optLdm->seqStore->size) {
+ optLdm->startPosInBlock = UINT_MAX;
+ optLdm->endPosInBlock = UINT_MAX;
return;
}
/* Calculate appropriate bytes left in matchLength and litLength after adjusting
based on ldmSeqStore->posInSequence */
- currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- assert(ldmSeqStore->posInSequence <= currSeq.litLength + currSeq.matchLength);
+ currSeq = optLdm->seqStore->seq[optLdm->seqStore->pos];
+ assert(optLdm->seqStore->posInSequence <= currSeq.litLength + currSeq.matchLength);
currBlockEndPos = currPosInBlock + blockBytesRemaining;
- literalsBytesRemaining = (ldmSeqStore->posInSequence < currSeq.litLength) ?
- currSeq.litLength - (U32)ldmSeqStore->posInSequence :
+ literalsBytesRemaining = (optLdm->seqStore->posInSequence < currSeq.litLength) ?
+ currSeq.litLength - (U32)optLdm->seqStore->posInSequence :
0;
matchBytesRemaining = (literalsBytesRemaining == 0) ?
- currSeq.matchLength - ((U32)ldmSeqStore->posInSequence - currSeq.litLength) :
+ currSeq.matchLength - ((U32)optLdm->seqStore->posInSequence - currSeq.litLength) :
currSeq.matchLength;
/* If there are more literal bytes than bytes remaining in block, no ldm is possible */
if (literalsBytesRemaining >= blockBytesRemaining) {
- *matchStartPosInBlock = UINT_MAX;
- *matchEndPosInBlock = UINT_MAX;
- ZSTD_opt_skipBytesInLdmSeqStore(ldmSeqStore, blockBytesRemaining);
+ optLdm->startPosInBlock = UINT_MAX;
+ optLdm->endPosInBlock = UINT_MAX;
+ ZSTD_opt_skipRawSeqStoreBytes(optLdm->seqStore, blockBytesRemaining);
return;
}
/* Matches may be < MINMATCH by this process. In that case, we will reject them
when we are deciding whether or not to add the ldm */
- *matchStartPosInBlock = currPosInBlock + literalsBytesRemaining;
- *matchEndPosInBlock = *matchStartPosInBlock + matchBytesRemaining;
- *matchOffset = currSeq.offset;
+ optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining;
+ optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining;
+ optLdm->offset = currSeq.offset;
- if (*matchEndPosInBlock > currBlockEndPos) {
+ if (optLdm->endPosInBlock > currBlockEndPos) {
/* Match ends after the block ends, we can't use the whole match */
- *matchEndPosInBlock = currBlockEndPos;
- ZSTD_opt_skipBytesInLdmSeqStore(ldmSeqStore, currBlockEndPos - currPosInBlock);
+ optLdm->endPosInBlock = currBlockEndPos;
+ ZSTD_opt_skipRawSeqStoreBytes(optLdm->seqStore, currBlockEndPos - currPosInBlock);
} else {
/* If we can use the whole match point the ldmSeqStore at the next match */
- ldmSeqStore->posInSequence = 0;
- ldmSeqStore->pos++;
+ optLdm->seqStore->posInSequence = 0;
+ optLdm->seqStore->pos++;
}
- DEBUGLOG(6, "ZSTD_opt_getNextLdmAndUpdateSeqStore(): got an ldm that beginning at pos: %u, end at pos: %u, with offset: %u",
- *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset);
+ DEBUGLOG(6, "ZSTD_opt_getNextMatchAndUpdateSeqStore(): got an ldm that beginning at pos: %u, end at pos: %u, with offset: %u",
+ optLdm->startPosInBlock, optLdm->endPosInBlock, optLdm->offset);
}
-/* ZSTD_opt_maybeAddLdm():
+/* ZSTD_opt_maybeAddMatch():
* Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
* and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
*/
-static void ZSTD_opt_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
- U32 matchStartPosInBlock, U32 matchEndPosInBlock,
- U32 matchOffset, U32 currPosInBlock) {
- U32 posDiff = currPosInBlock - matchStartPosInBlock;
+static void ZSTD_opt_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
+ ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
+ U32 posDiff = currPosInBlock - optLdm->startPosInBlock;
/* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
- U32 candidateMatchLength = matchEndPosInBlock - matchStartPosInBlock - posDiff;
- U32 candidateOffCode = matchOffset + ZSTD_REP_MOVE;
+ U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
+ U32 candidateOffCode = optLdm->offset + ZSTD_REP_MOVE;
/* Ensure that current block position is not outside of the match */
- if (currPosInBlock < matchStartPosInBlock
- || currPosInBlock >= matchEndPosInBlock
+ if (currPosInBlock < optLdm->startPosInBlock
+ || currPosInBlock >= optLdm->endPosInBlock
|| candidateMatchLength < MINMATCH) {
return;
}
- DEBUGLOG(6, "ZSTD_opt_maybeAddLdm(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
+ DEBUGLOG(6, "ZSTD_opt_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
candidateOffCode, candidateMatchLength, currPosInBlock);
if (*nbMatches == 0) {
matches[*nbMatches].len = candidateMatchLength;
@@ -892,29 +896,29 @@ static void ZSTD_opt_maybeAddLdm(ZSTD_match_t* matches, U32* nbMatches,
}
}
-/* ZSTD_opt_processLdm():
+/* ZSTD_opt_processMatchCandidate():
* Wrapper function to update ldm seq store and call ldm functions as necessary.
*/
-static void ZSTD_opt_processLdm(rawSeqStore_t* ldmSeqStore, ZSTD_match_t* matches, U32* nbMatches,
- U32* matchStartPosInBlock, U32* matchEndPosInBlock, U32* matchOffset,
+static void ZSTD_opt_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
U32 currPosInBlock, U32 remainingBytes) {
- if (currPosInBlock >= *matchEndPosInBlock) {
- if (currPosInBlock > *matchEndPosInBlock) {
- /* The position at which ZSTD_opt_processLdm() is called is not necessarily
+ if (optLdm->seqStore->size == 0 && optLdm->seqStore->pos >= optLdm->seqStore->size) {
+ return;
+ }
+
+ if (currPosInBlock >= optLdm->endPosInBlock) {
+ if (currPosInBlock > optLdm->endPosInBlock) {
+ /* The position at which ZSTD_opt_processMatchCandidate() is called is not necessarily
* at the end of a match from the ldm seq store, and will often be some bytes
* over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
*/
- U32 posOvershoot = currPosInBlock - *matchEndPosInBlock;
- ZSTD_opt_skipBytesInLdmSeqStore(ldmSeqStore, posOvershoot);
+ U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock;
+ ZSTD_opt_skipRawSeqStoreBytes(optLdm->seqStore, posOvershoot);
}
- ZSTD_opt_getNextLdmAndUpdateSeqStore(ldmSeqStore, matchStartPosInBlock,
- matchEndPosInBlock, matchOffset,
- currPosInBlock, remainingBytes);
+ ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);
}
- ZSTD_opt_maybeAddLdm(matches, nbMatches, *matchStartPosInBlock, *matchEndPosInBlock, *matchOffset, currPosInBlock);
+ ZSTD_opt_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock);
}
-
/*-*******************************
* Optimal parser
*********************************/
@@ -968,15 +972,12 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ZSTD_match_t* const matches = optStatePtr->matchTable;
ZSTD_optimal_t lastSequence;
- U32 ldmStartPosInBlock = 0;
- U32 ldmEndPosInBlock = 0;
- U32 ldmOffset = 0;
+ /* Make a copy so that ms->ldmSeqStore stays immutable during compressBlock() */
+ ZSTD_optLdm_t optLdm = {&ms->ldmSeqStore, 0, 0, 0};
/* Get first match from ldm seq store if long mode is enabled */
if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
- ZSTD_opt_getNextLdmAndUpdateSeqStore(&ms->ldmSeqStore, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend-ip));
+ ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));
}
/* init */
@@ -994,12 +995,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
- if (ms->ldmSeqStore.size != 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
- ZSTD_opt_processLdm(&ms->ldmSeqStore, matches,
- &nbMatches, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(ip-istart), (U32)(iend - ip));
- }
+ ZSTD_opt_processMatchCandidate(&optLdm, matches, &nbMatches,
+ (U32)(ip-istart), (U32)(iend - ip));
if (!nbMatches) { ip++; continue; }
/* initialize opt[0] */
@@ -1115,13 +1112,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
U32 matchNb;
-
- if (ms->ldmSeqStore.size != 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
- ZSTD_opt_processLdm(&ms->ldmSeqStore, matches,
- &nbMatches, &ldmStartPosInBlock,
- &ldmEndPosInBlock, &ldmOffset,
- (U32)(inr-istart), (U32)(iend-inr));
- }
+ ZSTD_opt_processMatchCandidate(&optLdm, matches, &nbMatches,
+ (U32)(inr-istart), (U32)(iend-inr));
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
@@ -1236,12 +1228,13 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
ZSTD_setBasePrices(optStatePtr, optLevel);
}
} /* while (ip < ilimit) */
-
- if (ldmEndPosInBlock < srcSize) {
+
+ if (optLdm.endPosInBlock < srcSize) {
/* This can occur if after adding the final match in an ldm seq store within this block,
ip reaches end of the block without calling ZSTD_opt_getNextLdmAndUpdateSeqStore() */
- ZSTD_opt_skipBytesInLdmSeqStore(&ms->ldmSeqStore, srcSize - ldmEndPosInBlock);
+ ZSTD_opt_skipRawSeqStoreBytes(optLdm.seqStore, srcSize - optLdm.endPosInBlock);
}
+
/* Return the last literals size */
return (size_t)(iend - anchor);
}
From 0fac8e07e1d8e35288b35e349714aad83082a413 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Tue, 6 Oct 2020 13:43:13 -0400
Subject: [PATCH 46/51] Refactor usage of ms->ldmSeqStore so that it is not
modified during compressBlock(), and simplify skipRawSeqStoreBytes
---
lib/compress/zstd_ldm.c | 26 ++++++++++-
lib/compress/zstd_opt.c | 100 ++++++++++++++++------------------------
2 files changed, 64 insertions(+), 62 deletions(-)
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 623245567..ae381c3e5 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -555,6 +555,26 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
return sequence;
}
+/* ZSTD_ldm_skipRawSeqStoreBytes():
+ * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'.
+ */
+static void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
+ U32 currPos = rawSeqStore->posInSequence + nbBytes;
+ while (currPos && rawSeqStore->pos < rawSeqStore->size) {
+ rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
+ if (currPos >= currSeq.litLength + currSeq.matchLength) {
+ currPos -= currSeq.litLength + currSeq.matchLength;
+ rawSeqStore->pos++;
+ if (currPos == 0) {
+ rawSeqStore->posInSequence = 0;
+ }
+ } else {
+ rawSeqStore->posInSequence = currPos;
+ break;
+ }
+ }
+}
+
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize)
@@ -574,7 +594,11 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
size_t lastLLSize;
ms->ldmSeqStore = *rawSeqStore;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
- *rawSeqStore = ms->ldmSeqStore;
+ ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize);
+ if (rawSeqStore->pos >= rawSeqStore->size) {
+ /* If we're done with rawSeqStore, invalidate the one in matchState as well */
+ ms->ldmSeqStore.pos = rawSeqStore->size;
+ }
return lastLLSize;
}
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 472f9e8a8..0baba0b18 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -768,39 +768,30 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
* LDM helper functions *
*************************/
+/* Struct containing info needed to make decision about ldm inclusion */
typedef struct {
- rawSeqStore_t* seqStore; /* Reference to struct containing external candidates */
+ rawSeqStore_t seqStore; /* External match candidates store for this block */
U32 startPosInBlock; /* Start position of the current match candidate */
U32 endPosInBlock; /* End position of the current match candidate */
U32 offset; /* Offset of the match candidate */
} ZSTD_optLdm_t;
-/* ZSTD_opt_skipRawSeqStoreBytes():
+/* ZSTD_optLdm_skipRawSeqStoreBytes():
* Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
*/
-static void ZSTD_opt_skipRawSeqStoreBytes(rawSeqStore_t* ldmSeqStore, size_t nbBytes) {
- while (nbBytes && ldmSeqStore->pos < ldmSeqStore->size) {
- rawSeq currSeq = ldmSeqStore->seq[ldmSeqStore->pos];
- /* posInSequence necessarily must never represent a value beyond the sequence */
- assert(ldmSeqStore->posInSequence <= currSeq.matchLength + currSeq.litLength);
-
- if (nbBytes <= currSeq.litLength) {
- ldmSeqStore->posInSequence += nbBytes;
- return;
+static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
+ U32 currPos = rawSeqStore->posInSequence + nbBytes;
+ while (currPos && rawSeqStore->pos < rawSeqStore->size) {
+ rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
+ if (currPos >= currSeq.litLength + currSeq.matchLength) {
+ currPos -= currSeq.litLength + currSeq.matchLength;
+ rawSeqStore->pos++;
+ if (currPos == 0) {
+ rawSeqStore->posInSequence = 0;
+ }
} else {
- ldmSeqStore->posInSequence += currSeq.litLength;
- nbBytes -= currSeq.litLength;
- }
-
- if (nbBytes < currSeq.matchLength) {
- ldmSeqStore->posInSequence += nbBytes;
- return;
- } else {
- nbBytes -= currSeq.matchLength;
- /* We have moved through this entire sequence - move the read pos
- forward to the next sequence, and reset posInSequence */
- ldmSeqStore->pos++;
- ldmSeqStore->posInSequence = 0;
+ rawSeqStore->posInSequence = currPos;
+ break;
}
}
}
@@ -817,28 +808,28 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
U32 matchBytesRemaining;
/* Setting match end position to MAX to ensure we never use an LDM during this block */
- if (optLdm->seqStore->pos >= optLdm->seqStore->size) {
+ if (optLdm->seqStore.pos >= optLdm->seqStore.size || optLdm->seqStore.size == 0) {
optLdm->startPosInBlock = UINT_MAX;
optLdm->endPosInBlock = UINT_MAX;
return;
}
/* Calculate appropriate bytes left in matchLength and litLength after adjusting
based on ldmSeqStore->posInSequence */
- currSeq = optLdm->seqStore->seq[optLdm->seqStore->pos];
- assert(optLdm->seqStore->posInSequence <= currSeq.litLength + currSeq.matchLength);
+ currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos];
+ assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength);
currBlockEndPos = currPosInBlock + blockBytesRemaining;
- literalsBytesRemaining = (optLdm->seqStore->posInSequence < currSeq.litLength) ?
- currSeq.litLength - (U32)optLdm->seqStore->posInSequence :
+ literalsBytesRemaining = (optLdm->seqStore.posInSequence < currSeq.litLength) ?
+ currSeq.litLength - (U32)optLdm->seqStore.posInSequence :
0;
matchBytesRemaining = (literalsBytesRemaining == 0) ?
- currSeq.matchLength - ((U32)optLdm->seqStore->posInSequence - currSeq.litLength) :
+ currSeq.matchLength - ((U32)optLdm->seqStore.posInSequence - currSeq.litLength) :
currSeq.matchLength;
/* If there are more literal bytes than bytes remaining in block, no ldm is possible */
if (literalsBytesRemaining >= blockBytesRemaining) {
optLdm->startPosInBlock = UINT_MAX;
optLdm->endPosInBlock = UINT_MAX;
- ZSTD_opt_skipRawSeqStoreBytes(optLdm->seqStore, blockBytesRemaining);
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, blockBytesRemaining);
return;
}
@@ -851,21 +842,18 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
if (optLdm->endPosInBlock > currBlockEndPos) {
/* Match ends after the block ends, we can't use the whole match */
optLdm->endPosInBlock = currBlockEndPos;
- ZSTD_opt_skipRawSeqStoreBytes(optLdm->seqStore, currBlockEndPos - currPosInBlock);
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, currBlockEndPos - currPosInBlock);
} else {
- /* If we can use the whole match point the ldmSeqStore at the next match */
- optLdm->seqStore->posInSequence = 0;
- optLdm->seqStore->pos++;
+ /* Consume nb of bytes equal to size of sequence left */
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, literalsBytesRemaining + matchBytesRemaining);
}
- DEBUGLOG(6, "ZSTD_opt_getNextMatchAndUpdateSeqStore(): got an ldm that beginning at pos: %u, end at pos: %u, with offset: %u",
- optLdm->startPosInBlock, optLdm->endPosInBlock, optLdm->offset);
}
-/* ZSTD_opt_maybeAddMatch():
+/* ZSTD_optLdm_maybeAddMatch():
* Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
* and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
*/
-static void ZSTD_opt_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
+static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
U32 posDiff = currPosInBlock - optLdm->startPosInBlock;
/* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
@@ -879,7 +867,7 @@ static void ZSTD_opt_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
return;
}
- DEBUGLOG(6, "ZSTD_opt_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
+ DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
candidateOffCode, candidateMatchLength, currPosInBlock);
if (*nbMatches == 0) {
matches[*nbMatches].len = candidateMatchLength;
@@ -896,27 +884,27 @@ static void ZSTD_opt_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
}
}
-/* ZSTD_opt_processMatchCandidate():
+/* ZSTD_optLdm_processMatchCandidate():
* Wrapper function to update ldm seq store and call ldm functions as necessary.
*/
-static void ZSTD_opt_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
+static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
U32 currPosInBlock, U32 remainingBytes) {
- if (optLdm->seqStore->size == 0 && optLdm->seqStore->pos >= optLdm->seqStore->size) {
+ if (optLdm->seqStore.size == 0 && optLdm->seqStore.pos >= optLdm->seqStore.size) {
return;
}
if (currPosInBlock >= optLdm->endPosInBlock) {
if (currPosInBlock > optLdm->endPosInBlock) {
- /* The position at which ZSTD_opt_processMatchCandidate() is called is not necessarily
+ /* The position at which ZSTD_optLdm_processMatchCandidate() is called is not necessarily
* at the end of a match from the ldm seq store, and will often be some bytes
* over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
*/
U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock;
- ZSTD_opt_skipRawSeqStoreBytes(optLdm->seqStore, posOvershoot);
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot);
}
ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);
}
- ZSTD_opt_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock);
+ ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock);
}
/*-*******************************
@@ -971,14 +959,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
ZSTD_match_t* const matches = optStatePtr->matchTable;
ZSTD_optimal_t lastSequence;
-
- /* Make a copy so that ms->ldmSeqStore stays immutable during compressBlock() */
- ZSTD_optLdm_t optLdm = {&ms->ldmSeqStore, 0, 0, 0};
+ ZSTD_optLdm_t optLdm = {ms->ldmSeqStore, 0, 0, 0}; /* ms->ldmSeqStore itself is immutable in this function */
/* Get first match from ldm seq store if long mode is enabled */
- if (ms->ldmSeqStore.size > 0 && ms->ldmSeqStore.pos < ms->ldmSeqStore.size) {
- ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));
- }
+ ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
@@ -995,7 +979,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
- ZSTD_opt_processMatchCandidate(&optLdm, matches, &nbMatches,
+ ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
(U32)(ip-istart), (U32)(iend - ip));
if (!nbMatches) { ip++; continue; }
@@ -1112,7 +1096,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
U32 matchNb;
- ZSTD_opt_processMatchCandidate(&optLdm, matches, &nbMatches,
+ ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
(U32)(inr-istart), (U32)(iend-inr));
if (!nbMatches) {
@@ -1228,13 +1212,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
ZSTD_setBasePrices(optStatePtr, optLevel);
}
} /* while (ip < ilimit) */
-
- if (optLdm.endPosInBlock < srcSize) {
- /* This can occur if after adding the final match in an ldm seq store within this block,
- ip reaches end of the block without calling ZSTD_opt_getNextLdmAndUpdateSeqStore() */
- ZSTD_opt_skipRawSeqStoreBytes(optLdm.seqStore, srcSize - optLdm.endPosInBlock);
- }
-
+
/* Return the last literals size */
return (size_t)(iend - anchor);
}
From 0c515590d81efd2f6655a0f0c992ab33ff76bcdd Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Tue, 6 Oct 2020 13:44:44 -0400
Subject: [PATCH 47/51] Replace offCode of largest match if ldm's offCode is
superior
---
lib/compress/zstd_opt.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 0baba0b18..80b8e28c9 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -874,8 +874,11 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
matches[*nbMatches].off = candidateOffCode;
(*nbMatches)++;
} else if ((candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
- /* No need to insert the match if it's the exact same, or offCode is larger with same matchLen */
- if (candidateMatchLength == matches[*nbMatches-1].len && candidateOffCode >= matches[*nbMatches-1].off) {
+ if (candidateMatchLength == matches[*nbMatches-1].len) {
+ /* No need to insert match with same matchLength. At most, replace offCode if it is smaller. */
+ if (candidateOffCode < matches[*nbMatches-1].off) {
+ matches[*nbMatches-1].off = candidateOffCode;
+ }
return;
}
matches[*nbMatches].len = candidateMatchLength;
From abce708a562b1c73baebadef469c86e590f3633a Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Tue, 6 Oct 2020 16:16:41 -0400
Subject: [PATCH 48/51] Move posInSequence correction to correct location
---
doc/zstd_manual.html | 105 +++++++++++++++++++++++++---------------
lib/compress/zstd_ldm.c | 12 +++--
lib/compress/zstd_opt.c | 18 ++++---
3 files changed, 83 insertions(+), 52 deletions(-)
diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
index fe58f78cb..d894befb6 100644
--- a/doc/zstd_manual.html
+++ b/doc/zstd_manual.html
@@ -1,10 +1,10 @@
-zstd 1.4.5 Manual
+zstd 1.4.6 Manual
-zstd 1.4.5 Manual
+zstd 1.4.6 Manual
Contents
@@ -24,19 +24,20 @@
- experimental API (static linking only)
- Frame size functions
- Memory management
-- Advanced compression functions
-- Advanced decompression functions
-- Advanced streaming functions
-- ! ZSTD_initCStream_usingDict() :
-- ! ZSTD_initCStream_advanced() :
-- ! ZSTD_initCStream_usingCDict() :
-- ! ZSTD_initCStream_usingCDict_advanced() :
-- This function is deprecated, and is equivalent to:
+- This API is temporary and is expected to change or disappear in the future!
+- Advanced compression functions
+- Advanced decompression functions
+- Advanced streaming functions
+- ! ZSTD_initCStream_usingDict() :
+- ! ZSTD_initCStream_advanced() :
+- ! ZSTD_initCStream_usingCDict() :
+- ! ZSTD_initCStream_usingCDict_advanced() :
- This function is deprecated, and is equivalent to:
-- Buffer-less and synchronous inner streaming functions
-- Buffer-less streaming compression (synchronous mode)
-- Buffer-less streaming decompression (synchronous mode)
-- Block level API
+- This function is deprecated, and is equivalent to:
+- Buffer-less and synchronous inner streaming functions
+- Buffer-less streaming compression (synchronous mode)
+- Buffer-less streaming decompression (synchronous mode)
+- Block level API
Introduction
@@ -72,8 +73,14 @@
Version
-unsigned ZSTD_versionNumber(void); /**< to check runtime library version */
-
+unsigned ZSTD_versionNumber(void);
+ Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE).
+
+
+const char* ZSTD_versionString(void);
+ Return runtime library version, like "1.4.5". Requires v1.3.0+.
+
+
Simple API
size_t ZSTD_compress( void* dst, size_t dstCapacity,
@@ -308,16 +315,20 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */
/* multi-threading parameters */
- /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
- * They return an error otherwise. */
+ /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
+ * Otherwise, trying to set any other value than default (0) will be a no-op and return an error.
+ * In a situation where it's unknown if the linked library supports multi-threading or not,
+ * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property.
+ */
ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel.
- * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() :
+ * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() :
* ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,
- * while compression work is performed in parallel, within worker threads.
+ * while compression is performed in parallel, within worker thread(s).
* (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :
* in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).
* More workers improve speed, but also increase memory usage.
- * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */
+ * Default value is `0`, aka "single-threaded mode" : no worker is spawned,
+ * compression is performed inside Caller's thread, and all invocations are blocking */
ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1.
* Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.
* 0 means default, which is dynamically determined based on compression parameters.
@@ -346,6 +357,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
* ZSTD_c_literalCompressionMode
* ZSTD_c_targetCBlockSize
* ZSTD_c_srcSizeHint
+ * ZSTD_c_enableDedicatedDictSearch
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly;
* also, the enums values themselves are unstable and can still change.
@@ -356,7 +368,8 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
ZSTD_c_experimentalParam4=1001,
ZSTD_c_experimentalParam5=1002,
ZSTD_c_experimentalParam6=1003,
- ZSTD_c_experimentalParam7=1004
+ ZSTD_c_experimentalParam7=1004,
+ ZSTD_c_experimentalParam8=1005
} ZSTD_cParameter;
typedef struct {
@@ -456,11 +469,13 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
* At the time of this writing, they include :
* ZSTD_d_format
* ZSTD_d_stableOutBuffer
+ * ZSTD_d_forceIgnoreChecksum
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly
*/
ZSTD_d_experimentalParam1=1000,
- ZSTD_d_experimentalParam2=1001
+ ZSTD_d_experimentalParam2=1001,
+ ZSTD_d_experimentalParam3=1002
} ZSTD_dParameter;
@@ -591,8 +606,9 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
- Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
- output->pos must be <= dstCapacity, input->pos must be <= srcSize
- output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
+ - endOp must be a valid directive
- When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
- - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
+ - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available,
and then immediately returns, just indicating that there is some data remaining to be flushed.
The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
- Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
@@ -951,6 +967,12 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
* Decoder cannot recognise automatically this format, requiring this instruction. */
} ZSTD_format_e;
+typedef enum {
+ /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */
+ ZSTD_d_validateChecksum = 0,
+ ZSTD_d_ignoreChecksum = 1
+} ZSTD_forceIgnoreChecksum_e;
+
typedef enum {
/* Note: this enum and the behavior it controls are effectively internal
* implementation details of the compressor. They are expected to continue
@@ -1148,7 +1170,10 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< t
-Advanced compression functions
+This API is temporary and is expected to change or disappear in the future!
+
+
+Advanced compression functions
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
Create a digested dictionary for compression
@@ -1264,8 +1289,10 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
Similar to ZSTD_CCtx_setParameter.
Set one compression parameter, selected by enum ZSTD_cParameter.
- Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
- @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ Parameters must be applied to a ZSTD_CCtx using
+ ZSTD_CCtx_setParametersUsingCCtxParams().
+ @result : a code representing success or failure (which can be tested with
+ ZSTD_isError()).
@@ -1298,7 +1325,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
-Advanced decompression functions
+Advanced decompression functions
unsigned ZSTD_isFrame(const void* buffer, size_t size);
Tells if the content of `buffer` starts with a valid Frame Identifier.
@@ -1360,7 +1387,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
-Advanced streaming functions
Warning : most of these functions are now redundant with the Advanced API.
+Advanced streaming functions
Warning : most of these functions are now redundant with the Advanced API.
Once Advanced API reaches "stable" status,
redundant functions will be deprecated, and then at some point removed.
@@ -1382,7 +1409,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
int compressionLevel,
unsigned long long pledgedSrcSize);
-! ZSTD_initCStream_usingDict() :
This function is deprecated, and is equivalent to:
+! ZSTD_initCStream_usingDict() :
This function is deprecated, and is equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
@@ -1395,7 +1422,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
-! ZSTD_initCStream_advanced() :
This function is deprecated, and is approximately equivalent to:
+! ZSTD_initCStream_advanced() :
This function is deprecated, and is approximately equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
// Pseudocode: Set each zstd parameter and leave the rest as-is.
for ((param, value) : params) {
@@ -1411,7 +1438,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
-! ZSTD_initCStream_usingCDict() :
This function is deprecated, and equivalent to:
+! ZSTD_initCStream_usingCDict() :
This function is deprecated, and equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
ZSTD_CCtx_refCDict(zcs, cdict);
@@ -1420,7 +1447,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
-! ZSTD_initCStream_usingCDict_advanced() :
This function is DEPRECATED, and is approximately equivalent to:
+! ZSTD_initCStream_usingCDict_advanced() :
This function is DEPRECATED, and is approximately equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
// Pseudocode: Set each zstd frame parameter and leave the rest as-is.
for ((fParam, value) : fParams) {
@@ -1488,7 +1515,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
*/
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
-This function is deprecated, and is equivalent to:
+This function is deprecated, and is equivalent to:
ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
ZSTD_DCtx_refDDict(zds, ddict);
@@ -1497,7 +1524,7 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
-This function is deprecated, and is equivalent to:
+This function is deprecated, and is equivalent to:
ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
re-use decompression parameters from previous init; saves dictionary loading
@@ -1505,14 +1532,14 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
-Buffer-less and synchronous inner streaming functions
+Buffer-less and synchronous inner streaming functions
This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
But it's also a complex one, with several restrictions, documented below.
Prefer normal streaming API for an easier experience.
-Buffer-less streaming compression (synchronous mode)
+Buffer-less streaming compression (synchronous mode)
A ZSTD_CCtx object is required to track streaming operations.
Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
ZSTD_CCtx object can be re-used multiple times within successive compression operations.
@@ -1548,7 +1575,7 @@ size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
-Buffer-less streaming decompression (synchronous mode)
+Buffer-less streaming decompression (synchronous mode)
A ZSTD_DCtx object is required to track streaming operations.
Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
A ZSTD_DCtx object can be re-used multiple times.
@@ -1644,7 +1671,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
-Block level API
+Block level API
Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes).
But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes.
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index ae381c3e5..4bfaa5414 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -559,20 +559,22 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
* Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'.
*/
static void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
- U32 currPos = rawSeqStore->posInSequence + nbBytes;
+ U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
while (currPos && rawSeqStore->pos < rawSeqStore->size) {
rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
if (currPos >= currSeq.litLength + currSeq.matchLength) {
currPos -= currSeq.litLength + currSeq.matchLength;
rawSeqStore->pos++;
- if (currPos == 0) {
- rawSeqStore->posInSequence = 0;
- }
} else {
rawSeqStore->posInSequence = currPos;
break;
}
}
+ if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {
+ rawSeqStore->posInSequence = 0;
+ }
+ assert(rawSeqStore->posInSequence <=
+ rawSeqStore->seq[rawSeqStore->pos].litLength + rawSeqStore->seq[rawSeqStore->pos].matchLength);
}
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
@@ -597,7 +599,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize);
if (rawSeqStore->pos >= rawSeqStore->size) {
/* If we're done with rawSeqStore, invalidate the one in matchState as well */
- ms->ldmSeqStore.pos = rawSeqStore->size;
+ ms->ldmSeqStore.size = 0;
}
return lastLLSize;
}
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 80b8e28c9..30e07f889 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -780,20 +780,22 @@ typedef struct {
* Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
*/
static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
- U32 currPos = rawSeqStore->posInSequence + nbBytes;
+ U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
while (currPos && rawSeqStore->pos < rawSeqStore->size) {
rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
if (currPos >= currSeq.litLength + currSeq.matchLength) {
currPos -= currSeq.litLength + currSeq.matchLength;
rawSeqStore->pos++;
- if (currPos == 0) {
- rawSeqStore->posInSequence = 0;
- }
} else {
rawSeqStore->posInSequence = currPos;
break;
}
}
+ if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {
+ rawSeqStore->posInSequence = 0;
+ }
+ assert(rawSeqStore->posInSequence <=
+ rawSeqStore->seq[rawSeqStore->pos].litLength + rawSeqStore->seq[rawSeqStore->pos].matchLength);
}
/* ZSTD_opt_getNextMatchAndUpdateSeqStore():
@@ -854,7 +856,7 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
* and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
*/
static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
- ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
+ ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
U32 posDiff = currPosInBlock - optLdm->startPosInBlock;
/* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
@@ -891,7 +893,7 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
* Wrapper function to update ldm seq store and call ldm functions as necessary.
*/
static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
- U32 currPosInBlock, U32 remainingBytes) {
+ U32 currPosInBlock, U32 remainingBytes) {
if (optLdm->seqStore.size == 0 && optLdm->seqStore.pos >= optLdm->seqStore.size) {
return;
}
@@ -983,7 +985,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const ll0 = !litlen;
U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
- (U32)(ip-istart), (U32)(iend - ip));
+ (U32)(ip-istart), (U32)(iend - ip));
if (!nbMatches) { ip++; continue; }
/* initialize opt[0] */
@@ -1100,7 +1102,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 matchNb;
ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
- (U32)(inr-istart), (U32)(iend-inr));
+ (U32)(inr-istart), (U32)(iend-inr));
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
From a6165c1b2849ff7a5f79688225a5ff2f7962b218 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Tue, 6 Oct 2020 19:43:48 -0400
Subject: [PATCH 49/51] Change matchState_t::ldmSeqStore to pointer
---
doc/zstd_manual.html | 105 ++++++++++----------------
lib/compress/zstd_compress.c | 1 +
lib/compress/zstd_compress_internal.h | 2 +-
lib/compress/zstd_ldm.c | 10 +--
lib/compress/zstd_opt.c | 27 ++++---
5 files changed, 58 insertions(+), 87 deletions(-)
diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
index d894befb6..fe58f78cb 100644
--- a/doc/zstd_manual.html
+++ b/doc/zstd_manual.html
@@ -1,10 +1,10 @@
-zstd 1.4.6 Manual
+zstd 1.4.5 Manual
-zstd 1.4.6 Manual
+zstd 1.4.5 Manual
Contents
@@ -24,20 +24,19 @@
- experimental API (static linking only)
- Frame size functions
- Memory management
-- This API is temporary and is expected to change or disappear in the future!
-- Advanced compression functions
-- Advanced decompression functions
-- Advanced streaming functions
-- ! ZSTD_initCStream_usingDict() :
-- ! ZSTD_initCStream_advanced() :
-- ! ZSTD_initCStream_usingCDict() :
-- ! ZSTD_initCStream_usingCDict_advanced() :
+- Advanced compression functions
+- Advanced decompression functions
+- Advanced streaming functions
+- ! ZSTD_initCStream_usingDict() :
+- ! ZSTD_initCStream_advanced() :
+- ! ZSTD_initCStream_usingCDict() :
+- ! ZSTD_initCStream_usingCDict_advanced() :
+- This function is deprecated, and is equivalent to:
- This function is deprecated, and is equivalent to:
-- This function is deprecated, and is equivalent to:
-- Buffer-less and synchronous inner streaming functions
-- Buffer-less streaming compression (synchronous mode)
-- Buffer-less streaming decompression (synchronous mode)
-- Block level API
+- Buffer-less and synchronous inner streaming functions
+- Buffer-less streaming compression (synchronous mode)
+- Buffer-less streaming decompression (synchronous mode)
+- Block level API
Introduction
@@ -73,14 +72,8 @@
Version
-unsigned ZSTD_versionNumber(void);
- Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE).
-
-
-const char* ZSTD_versionString(void);
- Return runtime library version, like "1.4.5". Requires v1.3.0+.
-
-
+unsigned ZSTD_versionNumber(void); /**< to check runtime library version */
+
Simple API
size_t ZSTD_compress( void* dst, size_t dstCapacity,
@@ -315,20 +308,16 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */
/* multi-threading parameters */
- /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
- * Otherwise, trying to set any other value than default (0) will be a no-op and return an error.
- * In a situation where it's unknown if the linked library supports multi-threading or not,
- * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property.
- */
+ /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
+ * They return an error otherwise. */
ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel.
- * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() :
+ * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() :
* ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,
- * while compression is performed in parallel, within worker thread(s).
+ * while compression work is performed in parallel, within worker threads.
* (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :
* in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).
* More workers improve speed, but also increase memory usage.
- * Default value is `0`, aka "single-threaded mode" : no worker is spawned,
- * compression is performed inside Caller's thread, and all invocations are blocking */
+ * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */
ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1.
* Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.
* 0 means default, which is dynamically determined based on compression parameters.
@@ -357,7 +346,6 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
* ZSTD_c_literalCompressionMode
* ZSTD_c_targetCBlockSize
* ZSTD_c_srcSizeHint
- * ZSTD_c_enableDedicatedDictSearch
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly;
* also, the enums values themselves are unstable and can still change.
@@ -368,8 +356,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
ZSTD_c_experimentalParam4=1001,
ZSTD_c_experimentalParam5=1002,
ZSTD_c_experimentalParam6=1003,
- ZSTD_c_experimentalParam7=1004,
- ZSTD_c_experimentalParam8=1005
+ ZSTD_c_experimentalParam7=1004
} ZSTD_cParameter;
typedef struct {
@@ -469,13 +456,11 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
* At the time of this writing, they include :
* ZSTD_d_format
* ZSTD_d_stableOutBuffer
- * ZSTD_d_forceIgnoreChecksum
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly
*/
ZSTD_d_experimentalParam1=1000,
- ZSTD_d_experimentalParam2=1001,
- ZSTD_d_experimentalParam3=1002
+ ZSTD_d_experimentalParam2=1001
} ZSTD_dParameter;
@@ -606,9 +591,8 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
- Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
- output->pos must be <= dstCapacity, input->pos must be <= srcSize
- output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
- - endOp must be a valid directive
- When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
- - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available,
+ - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
and then immediately returns, just indicating that there is some data remaining to be flushed.
The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
- Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
@@ -967,12 +951,6 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
* Decoder cannot recognise automatically this format, requiring this instruction. */
} ZSTD_format_e;
-typedef enum {
- /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */
- ZSTD_d_validateChecksum = 0,
- ZSTD_d_ignoreChecksum = 1
-} ZSTD_forceIgnoreChecksum_e;
-
typedef enum {
/* Note: this enum and the behavior it controls are effectively internal
* implementation details of the compressor. They are expected to continue
@@ -1170,10 +1148,7 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< t
-This API is temporary and is expected to change or disappear in the future!
-
-
-Advanced compression functions
+Advanced compression functions
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
Create a digested dictionary for compression
@@ -1289,10 +1264,8 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
Similar to ZSTD_CCtx_setParameter.
Set one compression parameter, selected by enum ZSTD_cParameter.
- Parameters must be applied to a ZSTD_CCtx using
- ZSTD_CCtx_setParametersUsingCCtxParams().
- @result : a code representing success or failure (which can be tested with
- ZSTD_isError()).
+ Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
+ @result : 0, or an error code (which can be tested with ZSTD_isError()).
@@ -1325,7 +1298,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
-Advanced decompression functions
+Advanced decompression functions
unsigned ZSTD_isFrame(const void* buffer, size_t size);
Tells if the content of `buffer` starts with a valid Frame Identifier.
@@ -1387,7 +1360,7 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
-Advanced streaming functions
Warning : most of these functions are now redundant with the Advanced API.
+Advanced streaming functions
Warning : most of these functions are now redundant with the Advanced API.
Once Advanced API reaches "stable" status,
redundant functions will be deprecated, and then at some point removed.
@@ -1409,7 +1382,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
int compressionLevel,
unsigned long long pledgedSrcSize);
-! ZSTD_initCStream_usingDict() :
This function is deprecated, and is equivalent to:
+! ZSTD_initCStream_usingDict() :
This function is deprecated, and is equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
@@ -1422,7 +1395,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
-! ZSTD_initCStream_advanced() :
This function is deprecated, and is approximately equivalent to:
+! ZSTD_initCStream_advanced() :
This function is deprecated, and is approximately equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
// Pseudocode: Set each zstd parameter and leave the rest as-is.
for ((param, value) : params) {
@@ -1438,7 +1411,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
-! ZSTD_initCStream_usingCDict() :
This function is deprecated, and equivalent to:
+! ZSTD_initCStream_usingCDict() :
This function is deprecated, and equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
ZSTD_CCtx_refCDict(zcs, cdict);
@@ -1447,7 +1420,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
-! ZSTD_initCStream_usingCDict_advanced() :
This function is DEPRECATED, and is approximately equivalent to:
+! ZSTD_initCStream_usingCDict_advanced() :
This function is DEPRECATED, and is approximately equivalent to:
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
// Pseudocode: Set each zstd frame parameter and leave the rest as-is.
for ((fParam, value) : fParams) {
@@ -1515,7 +1488,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
*/
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
-This function is deprecated, and is equivalent to:
+This function is deprecated, and is equivalent to:
ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
ZSTD_DCtx_refDDict(zds, ddict);
@@ -1524,7 +1497,7 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
-This function is deprecated, and is equivalent to:
+This function is deprecated, and is equivalent to:
ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
re-use decompression parameters from previous init; saves dictionary loading
@@ -1532,14 +1505,14 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
-Buffer-less and synchronous inner streaming functions
+Buffer-less and synchronous inner streaming functions
This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
But it's also a complex one, with several restrictions, documented below.
Prefer normal streaming API for an easier experience.
-Buffer-less streaming compression (synchronous mode)
+Buffer-less streaming compression (synchronous mode)
A ZSTD_CCtx object is required to track streaming operations.
Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
ZSTD_CCtx object can be re-used multiple times within successive compression operations.
@@ -1575,7 +1548,7 @@ size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
-Buffer-less streaming decompression (synchronous mode)
+Buffer-less streaming decompression (synchronous mode)
A ZSTD_DCtx object is required to track streaming operations.
Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
A ZSTD_DCtx object can be re-used multiple times.
@@ -1671,7 +1644,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
-Block level API
+Block level API
Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes).
But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes.
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 3a5ad0255..3109f1753 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2371,6 +2371,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
assert(ldmSeqStore.pos == ldmSeqStore.size);
} else { /* not long range mode */
ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
+ ms->ldmSeqStore = NULL;
lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
}
{ const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index 179e4f7bb..f59370a29 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -167,7 +167,7 @@ struct ZSTD_matchState_t {
optState_t opt; /* optimal parser state */
const ZSTD_matchState_t* dictMatchState;
ZSTD_compressionParameters cParams;
- rawSeqStore_t ldmSeqStore;
+ const rawSeqStore_t* ldmSeqStore;
};
typedef struct {
diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
index 4bfaa5414..cc338e697 100644
--- a/lib/compress/zstd_ldm.c
+++ b/lib/compress/zstd_ldm.c
@@ -573,8 +573,6 @@ static void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbB
if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {
rawSeqStore->posInSequence = 0;
}
- assert(rawSeqStore->posInSequence <=
- rawSeqStore->seq[rawSeqStore->pos].litLength + rawSeqStore->seq[rawSeqStore->pos].matchLength);
}
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
@@ -591,20 +589,16 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
/* Input positions */
BYTE const* ip = istart;
+ DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize);
/* If using opt parser, use LDMs only as candidates rather than always accepting them */
if (cParams->strategy >= ZSTD_btopt) {
size_t lastLLSize;
- ms->ldmSeqStore = *rawSeqStore;
+ ms->ldmSeqStore = rawSeqStore;
lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize);
- if (rawSeqStore->pos >= rawSeqStore->size) {
- /* If we're done with rawSeqStore, invalidate the one in matchState as well */
- ms->ldmSeqStore.size = 0;
- }
return lastLLSize;
}
- DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize);
assert(rawSeqStore->pos <= rawSeqStore->size);
assert(rawSeqStore->size <= rawSeqStore->capacity);
/* Loop through each sequence and apply the block compressor to the lits */
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 30e07f889..29242523c 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -770,10 +770,10 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
/* Struct containing info needed to make decision about ldm inclusion */
typedef struct {
- rawSeqStore_t seqStore; /* External match candidates store for this block */
- U32 startPosInBlock; /* Start position of the current match candidate */
- U32 endPosInBlock; /* End position of the current match candidate */
- U32 offset; /* Offset of the match candidate */
+ rawSeqStore_t seqStore; /* External match candidates store for this block */
+ U32 startPosInBlock; /* Start position of the current match candidate */
+ U32 endPosInBlock; /* End position of the current match candidate */
+ U32 offset; /* Offset of the match candidate */
} ZSTD_optLdm_t;
/* ZSTD_optLdm_skipRawSeqStoreBytes():
@@ -794,8 +794,6 @@ static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t
if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {
rawSeqStore->posInSequence = 0;
}
- assert(rawSeqStore->posInSequence <=
- rawSeqStore->seq[rawSeqStore->pos].litLength + rawSeqStore->seq[rawSeqStore->pos].matchLength);
}
/* ZSTD_opt_getNextMatchAndUpdateSeqStore():
@@ -810,7 +808,7 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
U32 matchBytesRemaining;
/* Setting match end position to MAX to ensure we never use an LDM during this block */
- if (optLdm->seqStore.pos >= optLdm->seqStore.size || optLdm->seqStore.size == 0) {
+ if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
optLdm->startPosInBlock = UINT_MAX;
optLdm->endPosInBlock = UINT_MAX;
return;
@@ -894,7 +892,7 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
*/
static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
U32 currPosInBlock, U32 remainingBytes) {
- if (optLdm->seqStore.size == 0 && optLdm->seqStore.pos >= optLdm->seqStore.size) {
+ if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
return;
}
@@ -964,7 +962,14 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
ZSTD_match_t* const matches = optStatePtr->matchTable;
ZSTD_optimal_t lastSequence;
- ZSTD_optLdm_t optLdm = {ms->ldmSeqStore, 0, 0, 0}; /* ms->ldmSeqStore itself is immutable in this function */
+ ZSTD_optLdm_t optLdm;
+
+ if (ms->ldmSeqStore) {
+ optLdm.seqStore = *ms->ldmSeqStore;
+ optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;
+ } else {
+ optLdm.seqStore.size = optLdm.seqStore.pos = 0;
+ }
/* Get first match from ldm seq store if long mode is enabled */
ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));
@@ -1217,7 +1222,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
ZSTD_setBasePrices(optStatePtr, optLevel);
}
} /* while (ip < ilimit) */
-
+
/* Return the last literals size */
return (size_t)(iend - anchor);
}
@@ -1267,7 +1272,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
const void* src, size_t srcSize)
{
U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */
- rawSeqStore_t tmpSeqStore = ms->ldmSeqStore;
ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep));
DEBUGLOG(4, "ZSTD_initStats_ultra (srcSize=%zu)", srcSize);
@@ -1284,7 +1288,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
ms->window.dictLimit += (U32)srcSize;
ms->window.lowLimit = ms->window.dictLimit;
ms->nextToUpdate = ms->window.dictLimit;
- ms->ldmSeqStore = tmpSeqStore;
/* re-inforce weight of collected statistics */
ZSTD_upscaleStats(&ms->opt);
From b9c8033cde4336fff66db993d954a283b6c0b1ae Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 7 Oct 2020 16:59:25 -0400
Subject: [PATCH 50/51] Define kNullRawSeqStore for every file
---
lib/compress/zstd_compress.c | 2 +-
lib/compress/zstd_compress_internal.h | 2 ++
lib/compress/zstd_opt.c | 10 ++--------
lib/compress/zstdmt_compress.c | 2 --
4 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 3109f1753..25b63965c 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2354,7 +2354,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
src, srcSize);
assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
} else if (zc->appliedParams.ldmParams.enableLdm) {
- rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0, 0};
+ rawSeqStore_t ldmSeqStore = kNullRawSeqStore;
ldmSeqStore.seq = zc->ldmSequences;
ldmSeqStore.capacity = zc->maxNbLdmSequences;
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index f59370a29..9b65b3c4a 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -101,6 +101,8 @@ typedef struct {
size_t capacity; /* The capacity starting from `seq` pointer */
} rawSeqStore_t;
+UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
+
typedef struct {
int price;
U32 off;
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 29242523c..8ba7aba38 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -964,14 +964,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ZSTD_optimal_t lastSequence;
ZSTD_optLdm_t optLdm;
- if (ms->ldmSeqStore) {
- optLdm.seqStore = *ms->ldmSeqStore;
- optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;
- } else {
- optLdm.seqStore.size = optLdm.seqStore.pos = 0;
- }
-
- /* Get first match from ldm seq store if long mode is enabled */
+ optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore;
+ optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;
ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));
/* init */
diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
index 06462fe5a..e19184677 100644
--- a/lib/compress/zstdmt_compress.c
+++ b/lib/compress/zstdmt_compress.c
@@ -266,8 +266,6 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
/* ===== Seq Pool Wrapper ====== */
-static rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
-
typedef ZSTDMT_bufferPool ZSTDMT_seqPool;
static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
From d6911b86bea2132ffae3d3841d35c4215e6b4609 Mon Sep 17 00:00:00 2001
From: senhuang42
Date: Wed, 7 Oct 2020 23:44:36 -0400
Subject: [PATCH 51/51] Require LDM matches to be strictly greater in length
---
lib/compress/zstd_opt.c | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c
index 8ba7aba38..e55c459de 100644
--- a/lib/compress/zstd_opt.c
+++ b/lib/compress/zstd_opt.c
@@ -867,20 +867,9 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
return;
}
- DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
- candidateOffCode, candidateMatchLength, currPosInBlock);
- if (*nbMatches == 0) {
- matches[*nbMatches].len = candidateMatchLength;
- matches[*nbMatches].off = candidateOffCode;
- (*nbMatches)++;
- } else if ((candidateMatchLength >= matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM) {
- if (candidateMatchLength == matches[*nbMatches-1].len) {
- /* No need to insert match with same matchLength. At most, replace offCode if it is smaller. */
- if (candidateOffCode < matches[*nbMatches-1].off) {
- matches[*nbMatches-1].off = candidateOffCode;
- }
- return;
- }
+ if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) {
+ DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
+ candidateOffCode, candidateMatchLength, currPosInBlock);
matches[*nbMatches].len = candidateMatchLength;
matches[*nbMatches].off = candidateOffCode;
(*nbMatches)++;