Skip to content

Commit f479e1a

Browse files
committed
Reduce streaming decompression memory by 128KB
The split literals buffer patch increased streaming decompression memory by 64KB (shrunk lit buffer from 128KB to 64KB, and added 128KB). This patch removes the added 128KB buffer, because it isn't necessary. The buffer was there because the literals compression code didn't know the true `blockSizeMax` of the frame, and always put split literals so they ended 128KB - 32 from the beginning of the block. Instead, we can pass down the true `blockSizeMax` and ensure that the split literals end up at `blockSizeMax - 32` from the beginning of the block. We already reserve a full `blockSizeMax` bytes in streaming mode, so we won't be overwriting the extDict window.
1 parent 0f255ff commit f479e1a

5 files changed

+124
-102
lines changed

lib/decompress/zstd_decompress.c

+15-5
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
265265
#endif
266266
dctx->noForwardProgress = 0;
267267
dctx->oversizedDuration = 0;
268+
dctx->isFrameDecompression = 1;
268269
#if DYNAMIC_BMI2
269270
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
270271
#endif
@@ -1003,7 +1004,8 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
10031004
switch(blockProperties.blockType)
10041005
{
10051006
case bt_compressed:
1006-
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
1007+
assert(dctx->isFrameDecompression == 1);
1008+
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, not_streaming);
10071009
break;
10081010
case bt_raw :
10091011
/* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
@@ -1319,7 +1321,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
13191321
{
13201322
case bt_compressed:
13211323
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
1322-
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
1324+
assert(dctx->isFrameDecompression == 1);
1325+
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, is_streaming);
13231326
dctx->expected = 0; /* Streaming not supported */
13241327
break;
13251328
case bt_raw :
@@ -1911,6 +1914,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
19111914
|| (reset == ZSTD_reset_session_and_parameters) ) {
19121915
dctx->streamStage = zdss_init;
19131916
dctx->noForwardProgress = 0;
1917+
dctx->isFrameDecompression = 1;
19141918
}
19151919
if ( (reset == ZSTD_reset_parameters)
19161920
|| (reset == ZSTD_reset_session_and_parameters) ) {
@@ -1929,9 +1933,15 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
19291933

19301934
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
19311935
{
1932-
size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1933-
/* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
1934-
unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
1936+
size_t const blockSize = (size_t)MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1937+
/* We need blockSize + WILDCOPY_OVERLENGTH worth of buffer so that if a block
1938+
* ends at windowSize + WILDCOPY_OVERLENGTH + 1 bytes, we can start writing
1939+
* the block at the beginning of the output buffer, and maintain a full window.
1940+
*
1941+
* We need another blockSize worth of buffer so that we can store split
1942+
* literals at the end of the block without overwriting the extDict window.
1943+
*/
1944+
unsigned long long const neededRBSize = windowSize + (blockSize * 2) + (WILDCOPY_OVERLENGTH * 2);
19351945
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
19361946
size_t const minRBSize = (size_t) neededSize;
19371947
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,

0 commit comments

Comments
 (0)