fix issue with incompressible sections

This commit is contained in:
Yann Collet
2024-02-23 14:53:56 -08:00
parent cc4530924b
commit 6b11fc436c
2 changed files with 60 additions and 35 deletions
+34 -9
View File
@@ -136,7 +136,7 @@ ZSTD_seqDecompressedSize(seqStore_t const* seqStore,
size_t matchLengthSum = 0; size_t matchLengthSum = 0;
size_t litLengthSum = 0; size_t litLengthSum = 0;
(void)(litLengthSum); /* suppress unused variable warning on some environments */ (void)(litLengthSum); /* suppress unused variable warning on some environments */
while (send-sp > 0) { while (sp < send) {
ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp); ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp);
litLengthSum += seqLen.litLength; litLengthSum += seqLen.litLength;
matchLengthSum += seqLen.matchLength; matchLengthSum += seqLen.matchLength;
@@ -462,7 +462,8 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
const BYTE* llCodePtr = seqStorePtr->llCode; const BYTE* llCodePtr = seqStorePtr->llCode;
const BYTE* mlCodePtr = seqStorePtr->mlCode; const BYTE* mlCodePtr = seqStorePtr->mlCode;
const BYTE* ofCodePtr = seqStorePtr->ofCode; const BYTE* ofCodePtr = seqStorePtr->ofCode;
size_t targetCBlockSize = cctxParams->targetCBlockSize; size_t const minTarget = 2 KB; /* enforce minimum size to avoid undesirable side effects */
size_t const targetCBlockSize = MAX(minTarget, cctxParams->targetCBlockSize);
int writeLitEntropy = entropyMetadata->hufMetadata.hType == set_compressed; int writeLitEntropy = entropyMetadata->hufMetadata.hType == set_compressed;
int writeSeqEntropy = 1; int writeSeqEntropy = 1;
size_t nbSubBlocks = 1; size_t nbSubBlocks = 1;
@@ -470,8 +471,13 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
DEBUGLOG(5, "ZSTD_compressSubBlock_multi (litSize=%u, nbSeq=%u)", DEBUGLOG(5, "ZSTD_compressSubBlock_multi (litSize=%u, nbSeq=%u)",
(unsigned)(lend-lp), (unsigned)(send-sstart)); (unsigned)(lend-lp), (unsigned)(send-sstart));
if (nbSeqs == 0) {
/* special case : no sequence */
nbSeqsPerBlock = 0;
nbSubBlocks = 1;
} else {
/* let's start by a general estimation for the full block */ /* let's start by a general estimation for the full block */
{ size_t const cBlockSizeEstimate = size_t const cBlockSizeEstimate =
ZSTD_estimateSubBlockSize(lp, nbLiterals, ZSTD_estimateSubBlockSize(lp, nbLiterals,
ofCodePtr, llCodePtr, mlCodePtr, nbSeqs, ofCodePtr, llCodePtr, mlCodePtr, nbSeqs,
&nextCBlock->entropy, entropyMetadata, &nextCBlock->entropy, entropyMetadata,
@@ -480,8 +486,13 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
/* quick estimation */ /* quick estimation */
nbSubBlocks = (cBlockSizeEstimate + (targetCBlockSize-1)) / targetCBlockSize; nbSubBlocks = (cBlockSizeEstimate + (targetCBlockSize-1)) / targetCBlockSize;
assert(nbSubBlocks > 0); assert(nbSubBlocks > 0);
if (nbSeqs > nbSubBlocks) {
nbSeqsPerBlock = nbSeqs / nbSubBlocks; nbSeqsPerBlock = nbSeqs / nbSubBlocks;
/* Note: this is very approximative. Obviously, some sub-blocks will be larger and others faster. } else {
nbSeqsPerBlock = 1;
nbSubBlocks = nbSeqs;
}
/* Note: this is very approximative. Obviously, some sub-blocks will be larger and others smaller.
* But the contract of this feature has always been approximative, so for now we'll leverage it for speed. * But the contract of this feature has always been approximative, so for now we'll leverage it for speed.
* It can be refined later, for closer-to-target compressed block size, if it ever matters. */ * It can be refined later, for closer-to-target compressed block size, if it ever matters. */
} }
@@ -498,7 +509,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
int seqEntropyWritten = 0; int seqEntropyWritten = 0;
const size_t decompressedSize = const size_t decompressedSize =
ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, lastSubBlock); ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, lastSubBlock);
const size_t cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata, size_t cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
sp, seqCount, sp, seqCount,
lp, litSize, lp, litSize,
llCodePtr, mlCodePtr, ofCodePtr, llCodePtr, mlCodePtr, ofCodePtr,
@@ -508,7 +519,24 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
&litEntropyWritten, &seqEntropyWritten, &litEntropyWritten, &seqEntropyWritten,
lastBlock && lastSubBlock); lastBlock && lastSubBlock);
FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed"); FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
if (cSize > 0 && cSize < decompressedSize) {
if (cSize == 0 || cSize >= decompressedSize) {
cSize = ZSTD_noCompressBlock(op, (size_t)(oend - op), ip, decompressedSize, lastBlock);
DEBUGLOG(5, "send an uncompressed sub-block of %u bytes", (unsigned)(decompressedSize));
FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
assert(cSize != 0);
/* We have to regenerate the repcodes because we've skipped some sequences */
if (sp < send) {
seqDef const* seq;
repcodes_t rep;
ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
for (seq = sstart; seq < sp; ++seq) {
ZSTD_updateRep(rep.rep, seq->offBase, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
}
ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
}
}
DEBUGLOG(5, "Committed the sub-block"); DEBUGLOG(5, "Committed the sub-block");
assert(ip + decompressedSize <= iend); assert(ip + decompressedSize <= iend);
ip += decompressedSize; ip += decompressedSize;
@@ -518,8 +546,6 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
llCodePtr += seqCount; llCodePtr += seqCount;
mlCodePtr += seqCount; mlCodePtr += seqCount;
ofCodePtr += seqCount; ofCodePtr += seqCount;
litSize = 0;
seqCount = 0;
/* Entropy only needs to be written once */ /* Entropy only needs to be written once */
if (litEntropyWritten) { if (litEntropyWritten) {
writeLitEntropy = 0; writeLitEntropy = 0;
@@ -529,7 +555,6 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
} }
} }
} }
}
if (writeLitEntropy) { if (writeLitEntropy) {
DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten"); DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten");
+1 -1
View File
@@ -1374,7 +1374,7 @@ static int basicUnitTests(U32 const seed, double compressibility)
} }
DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3d: superblock uncompressible data, too many nocompress superblocks : ", testNb++); DISPLAYLEVEL(3, "test%3d : superblock uncompressible data: too many nocompress superblocks : ", testNb++);
{ {
ZSTD_CCtx* const cctx = ZSTD_createCCtx(); ZSTD_CCtx* const cctx = ZSTD_createCCtx();
const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer; const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer;