Merge remote-tracking branch 'upstream/dev' into single-file-lib

This commit is contained in:
Carl Woffenden 2020-04-07 11:13:02 +02:00
commit 7af7735fa3
7 changed files with 119 additions and 39 deletions

View File

@ -100,11 +100,14 @@ static char* readFile(const char* filename, size_t* size) {
buf = malloc(*size); buf = malloc(*size);
if (buf == NULL) { if (buf == NULL) {
fprintf(stderr, "malloc failed\n"); fprintf(stderr, "malloc failed\n");
fclose(f);
return NULL;
} }
bytes_read = fread(buf, 1, *size, f); bytes_read = fread(buf, 1, *size, f);
if (bytes_read != *size) { if (bytes_read != *size) {
fprintf(stderr, "failed to read whole file\n"); fprintf(stderr, "failed to read whole file\n");
fclose(f);
free(buf); free(buf);
return NULL; return NULL;
} }

View File

@ -257,6 +257,17 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src,
return length; 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 * Private declarations
*********************************************/ *********************************************/

View File

@ -24,16 +24,6 @@ extern "C" {
* Constants * 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 / /* Since the workspace is effectively its own little malloc implementation /
* arena, when we run under ASAN, we should similarly insert redzones between * arena, when we run under ASAN, we should similarly insert redzones between
* each internal element of the workspace, so ASAN will catch overruns that * each internal element of the workspace, so ASAN will catch overruns that

View File

@ -111,6 +111,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
dctx->legacyContext = NULL; dctx->legacyContext = NULL;
dctx->previousLegacyVersion = 0; dctx->previousLegacyVersion = 0;
dctx->noForwardProgress = 0; dctx->noForwardProgress = 0;
dctx->oversizedDuration = 0;
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
} }
@ -1498,6 +1499,25 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
/* ***** Decompression ***** */ /* ***** 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) size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
{ {
const char* const src = (const char*)input->src; 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 */ /* Adapt buffer sizes to frame header instructions */
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); 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; ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
DEBUGLOG(4, "inBuff : from %u to %u",
(U32)zds->inBuffSize, (U32)neededInBuffSize); { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
DEBUGLOG(4, "outBuff : from %u to %u", int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
(U32)zds->outBuffSize, (U32)neededOutBuffSize);
if (zds->staticSize) { /* static DCtx */ if (tooSmall || tooLarge) {
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize); size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */ DEBUGLOG(4, "inBuff : from %u to %u",
RETURN_ERROR_IF( (U32)zds->inBuffSize, (U32)neededInBuffSize);
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx), DEBUGLOG(4, "outBuff : from %u to %u",
memory_allocation); (U32)zds->outBuffSize, (U32)neededOutBuffSize);
} else { if (zds->staticSize) { /* static DCtx */
ZSTD_free(zds->inBuff, zds->customMem); DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
zds->inBuffSize = 0; assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
zds->outBuffSize = 0; RETURN_ERROR_IF(
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation); memory_allocation);
} } else {
zds->inBuffSize = neededInBuffSize; ZSTD_free(zds->inBuff, zds->customMem);
zds->outBuff = zds->inBuff + zds->inBuffSize; zds->inBuffSize = 0;
zds->outBuffSize = neededOutBuffSize; 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; zds->streamStage = zdss_read;
/* fall-through */ /* fall-through */

View File

@ -151,6 +151,8 @@ struct ZSTD_DCtx_s
/* workspace */ /* workspace */
BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH]; BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
size_t oversizedDuration;
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */ }; /* typedef'd to ZSTD_DCtx within "zstd.h" */

View File

@ -1387,11 +1387,18 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs,
/* Status */ /* Status */
DISPLAYLEVEL(2, "\r%79s\r", ""); DISPLAYLEVEL(2, "\r%79s\r", "");
DISPLAYLEVEL(2,"%-20s :%6.2f%% (%6llu => %6llu bytes, %s) \n", if (readsize == 0) {
srcFileName, DISPLAYLEVEL(2,"%-20s : (%6llu => %6llu bytes, %s) \n",
(double)compressedfilesize / (readsize+(!readsize)/*avoid div by zero*/) * 100, srcFileName,
(unsigned long long)readsize, (unsigned long long) compressedfilesize, (unsigned long long)readsize, (unsigned long long) compressedfilesize,
dstFileName); 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 */ /* Elapsed Time and CPU Load */
{ clock_t const cpuEnd = clock(); { clock_t const cpuEnd = clock();

View File

@ -525,7 +525,48 @@ 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: 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(); ZSTD_CCtx* const cctx = ZSTD_createCCtx();
const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer; const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer;