Merge remote-tracking branch 'upstream/dev' into single-file-lib
This commit is contained in:
commit
7af7735fa3
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
*********************************************/
|
*********************************************/
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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" */
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user