Merge remote-tracking branch 'upstream/dev' into single-file-lib
commit
7af7735fa3
|
@ -100,11 +100,14 @@ static char* readFile(const char* filename, size_t* size) {
|
|||
buf = malloc(*size);
|
||||
if (buf == NULL) {
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes_read = fread(buf, 1, *size, f);
|
||||
if (bytes_read != *size) {
|
||||
fprintf(stderr, "failed to read whole file\n");
|
||||
fclose(f);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -257,6 +257,17 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src,
|
|||
return length;
|
||||
}
|
||||
|
||||
/* define "workspace is too large" as this number of times larger than needed */
|
||||
#define ZSTD_WORKSPACETOOLARGE_FACTOR 3
|
||||
|
||||
/* when workspace is continuously too large
|
||||
* during at least this number of times,
|
||||
* context's memory usage is considered wasteful,
|
||||
* because it's sized to handle a worst case scenario which rarely happens.
|
||||
* In which case, resize it down to free some memory */
|
||||
#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128
|
||||
|
||||
|
||||
/*-*******************************************
|
||||
* Private declarations
|
||||
*********************************************/
|
||||
|
|
|
@ -24,16 +24,6 @@ extern "C" {
|
|||
* Constants
|
||||
***************************************/
|
||||
|
||||
/* define "workspace is too large" as this number of times larger than needed */
|
||||
#define ZSTD_WORKSPACETOOLARGE_FACTOR 3
|
||||
|
||||
/* when workspace is continuously too large
|
||||
* during at least this number of times,
|
||||
* context's memory usage is considered wasteful,
|
||||
* because it's sized to handle a worst case scenario which rarely happens.
|
||||
* In which case, resize it down to free some memory */
|
||||
#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128
|
||||
|
||||
/* Since the workspace is effectively its own little malloc implementation /
|
||||
* arena, when we run under ASAN, we should similarly insert redzones between
|
||||
* each internal element of the workspace, so ASAN will catch overruns that
|
||||
|
|
|
@ -111,6 +111,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|||
dctx->legacyContext = NULL;
|
||||
dctx->previousLegacyVersion = 0;
|
||||
dctx->noForwardProgress = 0;
|
||||
dctx->oversizedDuration = 0;
|
||||
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
||||
}
|
||||
|
||||
|
@ -1498,6 +1499,25 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|||
|
||||
/* ***** Decompression ***** */
|
||||
|
||||
|
||||
static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
||||
{
|
||||
return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
|
||||
}
|
||||
|
||||
static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
||||
{
|
||||
if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
|
||||
zds->oversizedDuration++;
|
||||
else
|
||||
zds->oversizedDuration = 0;
|
||||
}
|
||||
|
||||
static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
|
||||
{
|
||||
return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
|
||||
}
|
||||
|
||||
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||
{
|
||||
const char* const src = (const char*)input->src;
|
||||
|
@ -1626,29 +1646,35 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||
/* Adapt buffer sizes to frame header instructions */
|
||||
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
||||
size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
|
||||
if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) {
|
||||
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
|
||||
DEBUGLOG(4, "inBuff : from %u to %u",
|
||||
(U32)zds->inBuffSize, (U32)neededInBuffSize);
|
||||
DEBUGLOG(4, "outBuff : from %u to %u",
|
||||
(U32)zds->outBuffSize, (U32)neededOutBuffSize);
|
||||
if (zds->staticSize) { /* static DCtx */
|
||||
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
||||
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
||||
RETURN_ERROR_IF(
|
||||
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
||||
memory_allocation);
|
||||
} else {
|
||||
ZSTD_free(zds->inBuff, zds->customMem);
|
||||
zds->inBuffSize = 0;
|
||||
zds->outBuffSize = 0;
|
||||
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
||||
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
|
||||
}
|
||||
zds->inBuffSize = neededInBuffSize;
|
||||
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
||||
zds->outBuffSize = neededOutBuffSize;
|
||||
} }
|
||||
|
||||
ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
|
||||
|
||||
{ int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
|
||||
int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
|
||||
|
||||
if (tooSmall || tooLarge) {
|
||||
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
|
||||
DEBUGLOG(4, "inBuff : from %u to %u",
|
||||
(U32)zds->inBuffSize, (U32)neededInBuffSize);
|
||||
DEBUGLOG(4, "outBuff : from %u to %u",
|
||||
(U32)zds->outBuffSize, (U32)neededOutBuffSize);
|
||||
if (zds->staticSize) { /* static DCtx */
|
||||
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
||||
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
||||
RETURN_ERROR_IF(
|
||||
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
||||
memory_allocation);
|
||||
} else {
|
||||
ZSTD_free(zds->inBuff, zds->customMem);
|
||||
zds->inBuffSize = 0;
|
||||
zds->outBuffSize = 0;
|
||||
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
||||
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
|
||||
}
|
||||
zds->inBuffSize = neededInBuffSize;
|
||||
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
||||
zds->outBuffSize = neededOutBuffSize;
|
||||
} } }
|
||||
zds->streamStage = zdss_read;
|
||||
/* fall-through */
|
||||
|
||||
|
|
|
@ -151,6 +151,8 @@ struct ZSTD_DCtx_s
|
|||
/* workspace */
|
||||
BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
|
||||
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
|
||||
|
||||
size_t oversizedDuration;
|
||||
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
|
||||
|
||||
|
||||
|
|
|
@ -1387,11 +1387,18 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs,
|
|||
|
||||
/* Status */
|
||||
DISPLAYLEVEL(2, "\r%79s\r", "");
|
||||
DISPLAYLEVEL(2,"%-20s :%6.2f%% (%6llu => %6llu bytes, %s) \n",
|
||||
srcFileName,
|
||||
(double)compressedfilesize / (readsize+(!readsize)/*avoid div by zero*/) * 100,
|
||||
(unsigned long long)readsize, (unsigned long long) compressedfilesize,
|
||||
dstFileName);
|
||||
if (readsize == 0) {
|
||||
DISPLAYLEVEL(2,"%-20s : (%6llu => %6llu bytes, %s) \n",
|
||||
srcFileName,
|
||||
(unsigned long long)readsize, (unsigned long long) compressedfilesize,
|
||||
dstFileName);
|
||||
} else {
|
||||
DISPLAYLEVEL(2,"%-20s :%6.2f%% (%6llu => %6llu bytes, %s) \n",
|
||||
srcFileName,
|
||||
(double)compressedfilesize / readsize * 100,
|
||||
(unsigned long long)readsize, (unsigned long long) compressedfilesize,
|
||||
dstFileName);
|
||||
}
|
||||
|
||||
/* Elapsed Time and CPU Load */
|
||||
{ clock_t const cpuEnd = clock();
|
||||
|
|
|
@ -525,7 +525,48 @@ static int basicUnitTests(U32 const seed, double compressibility)
|
|||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3d: superblock uncompressible data, too many nocompress superblocks : ", testNb++)
|
||||
DISPLAYLEVEL(3, "test%3d: check DCtx size is reduced after many oversized calls : ", testNb++);
|
||||
{
|
||||
size_t const largeFrameSrcSize = 200;
|
||||
size_t const smallFrameSrcSize = 10;
|
||||
size_t const nbFrames = 256;
|
||||
|
||||
size_t i = 0, consumed = 0, produced = 0, prevDCtxSize = 0;
|
||||
int sizeReduced = 0;
|
||||
|
||||
BYTE* const dst = (BYTE*)compressedBuffer;
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
|
||||
/* create a large frame and then a bunch of small frames */
|
||||
size_t srcSize = ZSTD_compress((void*)dst,
|
||||
compressedBufferSize, CNBuffer, largeFrameSrcSize, 3);
|
||||
for (i = 0; i < nbFrames; i++)
|
||||
srcSize += ZSTD_compress((void*)(dst + srcSize),
|
||||
compressedBufferSize - srcSize, CNBuffer,
|
||||
smallFrameSrcSize, 3);
|
||||
|
||||
/* decompressStream and make sure that dctx size was reduced at least once */
|
||||
while (consumed < srcSize) {
|
||||
ZSTD_inBuffer in = {(void*)(dst + consumed), MIN(1, srcSize - consumed), 0};
|
||||
ZSTD_outBuffer out = {(BYTE*)CNBuffer + produced, CNBuffSize - produced, 0};
|
||||
ZSTD_decompressStream(dctx, &out, &in);
|
||||
consumed += in.pos;
|
||||
produced += out.pos;
|
||||
|
||||
/* success! size was reduced from the previous frame */
|
||||
if (prevDCtxSize > ZSTD_sizeof_DCtx(dctx))
|
||||
sizeReduced = 1;
|
||||
|
||||
prevDCtxSize = ZSTD_sizeof_DCtx(dctx);
|
||||
}
|
||||
|
||||
assert(sizeReduced);
|
||||
|
||||
ZSTD_freeDCtx(dctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3d: superblock uncompressible data, too many nocompress superblocks : ", testNb++);
|
||||
{
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer;
|
||||
|
|
Loading…
Reference in New Issue