zstd-ruby 1.3.2.0 → 1.3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/BUCK +31 -10
- data/ext/zstdruby/libzstd/common/bitstream.h +1 -1
- data/ext/zstdruby/libzstd/common/mem.h +15 -13
- data/ext/zstdruby/libzstd/common/pool.c +1 -2
- data/ext/zstdruby/libzstd/common/zstd_common.c +10 -4
- data/ext/zstdruby/libzstd/common/zstd_internal.h +52 -170
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +434 -337
- data/ext/zstdruby/libzstd/compress/{zstd_compress.h → zstd_compress_internal.h} +191 -36
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +1 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -2
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +1 -0
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -2
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +66 -50
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +3 -2
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +3 -2
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +504 -676
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +130 -80
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +15 -7
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +41 -31
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -0
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +1 -74
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +1 -74
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -72
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +1 -73
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +1 -77
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +1 -77
- data/ext/zstdruby/libzstd/zstd.h +43 -30
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +4 -4
@@ -11,12 +11,12 @@
|
|
11
11
|
#ifndef ZSTD_OPT_H
|
12
12
|
#define ZSTD_OPT_H
|
13
13
|
|
14
|
-
#include "zstd_compress.h"
|
15
|
-
|
16
14
|
#if defined (__cplusplus)
|
17
15
|
extern "C" {
|
18
16
|
#endif
|
19
17
|
|
18
|
+
#include "zstd.h" /* ZSTD_CCtx, size_t */
|
19
|
+
|
20
20
|
size_t ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
|
21
21
|
size_t ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
|
22
22
|
|
@@ -24,7 +24,7 @@
|
|
24
24
|
#include <string.h> /* memcpy, memset */
|
25
25
|
#include "pool.h" /* threadpool */
|
26
26
|
#include "threading.h" /* mutex */
|
27
|
-
#include "
|
27
|
+
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
28
28
|
#include "zstdmt_compress.h"
|
29
29
|
|
30
30
|
|
@@ -140,9 +140,12 @@ static size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool)
|
|
140
140
|
return poolSize + totalBufferSize;
|
141
141
|
}
|
142
142
|
|
143
|
-
static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* bufPool, size_t bSize)
|
143
|
+
static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const bSize)
|
144
144
|
{
|
145
|
+
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
|
146
|
+
DEBUGLOG(4, "ZSTDMT_setBufferSize: bSize = %u", (U32)bSize);
|
145
147
|
bufPool->bufferSize = bSize;
|
148
|
+
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
146
149
|
}
|
147
150
|
|
148
151
|
/** ZSTDMT_getBuffer() :
|
@@ -150,28 +153,31 @@ static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* bufPool, size_t bSize)
|
|
150
153
|
static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
|
151
154
|
{
|
152
155
|
size_t const bSize = bufPool->bufferSize;
|
153
|
-
DEBUGLOG(5, "ZSTDMT_getBuffer");
|
156
|
+
DEBUGLOG(5, "ZSTDMT_getBuffer: bSize = %u", (U32)bufPool->bufferSize);
|
154
157
|
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
|
155
158
|
if (bufPool->nbBuffers) { /* try to use an existing buffer */
|
156
159
|
buffer_t const buf = bufPool->bTable[--(bufPool->nbBuffers)];
|
157
160
|
size_t const availBufferSize = buf.size;
|
158
161
|
bufPool->bTable[bufPool->nbBuffers] = g_nullBuffer;
|
159
|
-
if ((availBufferSize >= bSize) & (availBufferSize <=
|
162
|
+
if ((availBufferSize >= bSize) & ((availBufferSize>>3) <= bSize)) {
|
160
163
|
/* large enough, but not too much */
|
164
|
+
DEBUGLOG(5, "ZSTDMT_getBuffer: provide buffer %u of size %u",
|
165
|
+
bufPool->nbBuffers, (U32)buf.size);
|
161
166
|
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
162
167
|
return buf;
|
163
168
|
}
|
164
169
|
/* size conditions not respected : scratch this buffer, create new one */
|
165
|
-
DEBUGLOG(5, "existing buffer does not meet size conditions => freeing");
|
170
|
+
DEBUGLOG(5, "ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing");
|
166
171
|
ZSTD_free(buf.start, bufPool->cMem);
|
167
172
|
}
|
168
173
|
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
169
174
|
/* create new buffer */
|
170
|
-
DEBUGLOG(5, "create a new buffer");
|
175
|
+
DEBUGLOG(5, "ZSTDMT_getBuffer: create a new buffer");
|
171
176
|
{ buffer_t buffer;
|
172
177
|
void* const start = ZSTD_malloc(bSize, bufPool->cMem);
|
173
178
|
buffer.start = start; /* note : start can be NULL if malloc fails ! */
|
174
179
|
buffer.size = (start==NULL) ? 0 : bSize;
|
180
|
+
DEBUGLOG(5, "ZSTDMT_getBuffer: created buffer of size %u", (U32)bSize);
|
175
181
|
return buffer;
|
176
182
|
}
|
177
183
|
}
|
@@ -184,12 +190,14 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
|
|
184
190
|
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
|
185
191
|
if (bufPool->nbBuffers < bufPool->totalBuffers) {
|
186
192
|
bufPool->bTable[bufPool->nbBuffers++] = buf; /* stored for later use */
|
193
|
+
DEBUGLOG(5, "ZSTDMT_releaseBuffer: stored buffer of size %u in slot %u",
|
194
|
+
(U32)buf.size, (U32)(bufPool->nbBuffers-1));
|
187
195
|
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
188
196
|
return;
|
189
197
|
}
|
190
198
|
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
191
199
|
/* Reached bufferPool capacity (should not happen) */
|
192
|
-
DEBUGLOG(5, "
|
200
|
+
DEBUGLOG(5, "ZSTDMT_releaseBuffer: pool capacity reached => freeing ");
|
193
201
|
ZSTD_free(buf.start, bufPool->cMem);
|
194
202
|
}
|
195
203
|
|
@@ -302,7 +310,7 @@ static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
|
|
302
310
|
typedef struct {
|
303
311
|
buffer_t src;
|
304
312
|
const void* srcStart;
|
305
|
-
size_t
|
313
|
+
size_t prefixSize;
|
306
314
|
size_t srcSize;
|
307
315
|
buffer_t dstBuff;
|
308
316
|
size_t cSize;
|
@@ -324,11 +332,11 @@ typedef struct {
|
|
324
332
|
void ZSTDMT_compressChunk(void* jobDescription)
|
325
333
|
{
|
326
334
|
ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
|
327
|
-
ZSTD_CCtx* cctx = ZSTDMT_getCCtx(job->cctxPool);
|
328
|
-
const void* const src = (const char*)job->srcStart + job->
|
335
|
+
ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool);
|
336
|
+
const void* const src = (const char*)job->srcStart + job->prefixSize;
|
329
337
|
buffer_t dstBuff = job->dstBuff;
|
330
|
-
DEBUGLOG(5, "job (first:%u) (last:%u) :
|
331
|
-
job->firstChunk, job->lastChunk, (U32)job->
|
338
|
+
DEBUGLOG(5, "ZSTDMT_compressChunk: job (first:%u) (last:%u) : prefixSize %u, srcSize %u ",
|
339
|
+
job->firstChunk, job->lastChunk, (U32)job->prefixSize, (U32)job->srcSize);
|
332
340
|
|
333
341
|
if (cctx==NULL) {
|
334
342
|
job->cSize = ERROR(memory_allocation);
|
@@ -342,38 +350,48 @@ void ZSTDMT_compressChunk(void* jobDescription)
|
|
342
350
|
goto _endJob;
|
343
351
|
}
|
344
352
|
job->dstBuff = dstBuff;
|
353
|
+
DEBUGLOG(5, "ZSTDMT_compressChunk: received dstBuff of size %u", (U32)dstBuff.size);
|
345
354
|
}
|
346
355
|
|
347
|
-
if (job->cdict) {
|
348
|
-
size_t const initError =
|
349
|
-
DEBUGLOG(
|
356
|
+
if (job->cdict) {
|
357
|
+
size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dm_auto, job->cdict, job->params, job->fullFrameSize);
|
358
|
+
DEBUGLOG(4, "ZSTDMT_compressChunk: init using CDict (windowLog=%u)", job->params.cParams.windowLog);
|
359
|
+
assert(job->firstChunk); /* only allowed for first job */
|
350
360
|
if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
|
351
361
|
} else { /* srcStart points at reloaded section */
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
362
|
+
U64 const pledgedSrcSize = job->firstChunk ? job->fullFrameSize : ZSTD_CONTENTSIZE_UNKNOWN;
|
363
|
+
ZSTD_CCtx_params jobParams = job->params; /* do not modify job->params ! copy it, modify the copy */
|
364
|
+
size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_p_forceMaxWindow, !job->firstChunk);
|
365
|
+
if (ZSTD_isError(forceWindowError)) {
|
366
|
+
DEBUGLOG(5, "ZSTD_CCtxParam_setParameter error : %s ", ZSTD_getErrorName(forceWindowError));
|
367
|
+
job->cSize = forceWindowError;
|
368
|
+
goto _endJob;
|
369
|
+
}
|
370
|
+
DEBUGLOG(5, "ZSTDMT_compressChunk: invoking ZSTD_compressBegin_advanced_internal with windowLog = %u ", jobParams.cParams.windowLog);
|
371
|
+
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
|
372
|
+
job->srcStart, job->prefixSize, ZSTD_dm_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
|
373
|
+
NULL,
|
374
|
+
jobParams, pledgedSrcSize);
|
375
|
+
if (ZSTD_isError(initError)) {
|
376
|
+
DEBUGLOG(5, "ZSTD_compressBegin_advanced_internal error : %s ", ZSTD_getErrorName(initError));
|
359
377
|
job->cSize = initError;
|
360
378
|
goto _endJob;
|
361
|
-
|
362
|
-
}
|
363
|
-
if (!job->firstChunk) { /* flush and overwrite frame header when it's not first
|
379
|
+
} }
|
380
|
+
}
|
381
|
+
if (!job->firstChunk) { /* flush and overwrite frame header when it's not first job */
|
364
382
|
size_t const hSize = ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.size, src, 0);
|
365
|
-
if (ZSTD_isError(hSize)) { job->cSize = hSize; goto _endJob; }
|
383
|
+
if (ZSTD_isError(hSize)) { job->cSize = hSize; /* save error code */ goto _endJob; }
|
366
384
|
ZSTD_invalidateRepCodes(cctx);
|
367
385
|
}
|
368
386
|
|
369
|
-
DEBUGLOG(5, "Compressing
|
370
|
-
DEBUG_PRINTHEX(
|
387
|
+
DEBUGLOG(5, "Compressing into dstBuff of size %u", (U32)dstBuff.size);
|
388
|
+
DEBUG_PRINTHEX(6, job->srcStart, 12);
|
371
389
|
job->cSize = (job->lastChunk) ?
|
372
390
|
ZSTD_compressEnd (cctx, dstBuff.start, dstBuff.size, src, job->srcSize) :
|
373
391
|
ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.size, src, job->srcSize);
|
374
|
-
DEBUGLOG(5, "compressed %u bytes into %u bytes (first:%u) (last:%u)",
|
392
|
+
DEBUGLOG(5, "compressed %u bytes into %u bytes (first:%u) (last:%u) ",
|
375
393
|
(unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
|
376
|
-
DEBUGLOG(5, "dstBuff.size : %u ; => %s", (U32)dstBuff.size, ZSTD_getErrorName(job->cSize));
|
394
|
+
DEBUGLOG(5, "dstBuff.size : %u ; => %s ", (U32)dstBuff.size, ZSTD_getErrorName(job->cSize));
|
377
395
|
|
378
396
|
_endJob:
|
379
397
|
ZSTDMT_releaseCCtx(job->cctxPool, cctx);
|
@@ -403,13 +421,14 @@ struct ZSTDMT_CCtx_s {
|
|
403
421
|
ZSTDMT_CCtxPool* cctxPool;
|
404
422
|
ZSTD_pthread_mutex_t jobCompleted_mutex;
|
405
423
|
ZSTD_pthread_cond_t jobCompleted_cond;
|
424
|
+
ZSTD_CCtx_params params;
|
406
425
|
size_t targetSectionSize;
|
407
426
|
size_t inBuffSize;
|
408
427
|
size_t dictSize;
|
409
428
|
size_t targetDictSize;
|
410
429
|
inBuff_t inBuff;
|
411
|
-
ZSTD_CCtx_params params;
|
412
430
|
XXH64_state_t xxhState;
|
431
|
+
unsigned singleThreaded;
|
413
432
|
unsigned jobIDMask;
|
414
433
|
unsigned doneJobID;
|
415
434
|
unsigned nextJobID;
|
@@ -430,20 +449,32 @@ static ZSTDMT_jobDescription* ZSTDMT_allocJobsTable(U32* nbJobsPtr, ZSTD_customM
|
|
430
449
|
nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
|
431
450
|
}
|
432
451
|
|
433
|
-
/*
|
434
|
-
|
452
|
+
/* ZSTDMT_CCtxParam_setNbThreads():
|
453
|
+
* Internal use only */
|
454
|
+
size_t ZSTDMT_CCtxParam_setNbThreads(ZSTD_CCtx_params* params, unsigned nbThreads)
|
435
455
|
{
|
456
|
+
if (nbThreads > ZSTDMT_NBTHREADS_MAX) nbThreads = ZSTDMT_NBTHREADS_MAX;
|
457
|
+
if (nbThreads < 1) nbThreads = 1;
|
436
458
|
params->nbThreads = nbThreads;
|
437
459
|
params->overlapSizeLog = ZSTDMT_OVERLAPLOG_DEFAULT;
|
438
460
|
params->jobSize = 0;
|
439
|
-
return
|
461
|
+
return nbThreads;
|
462
|
+
}
|
463
|
+
|
464
|
+
/* ZSTDMT_getNbThreads():
|
465
|
+
* @return nb threads currently active in mtctx.
|
466
|
+
* mtctx must be valid */
|
467
|
+
size_t ZSTDMT_getNbThreads(const ZSTDMT_CCtx* mtctx)
|
468
|
+
{
|
469
|
+
assert(mtctx != NULL);
|
470
|
+
return mtctx->params.nbThreads;
|
440
471
|
}
|
441
472
|
|
442
473
|
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
|
443
474
|
{
|
444
475
|
ZSTDMT_CCtx* mtctx;
|
445
476
|
U32 nbJobs = nbThreads + 2;
|
446
|
-
DEBUGLOG(3, "ZSTDMT_createCCtx_advanced");
|
477
|
+
DEBUGLOG(3, "ZSTDMT_createCCtx_advanced (nbThreads = %u)", nbThreads);
|
447
478
|
|
448
479
|
if (nbThreads < 1) return NULL;
|
449
480
|
nbThreads = MIN(nbThreads , ZSTDMT_NBTHREADS_MAX);
|
@@ -453,7 +484,7 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
|
|
453
484
|
|
454
485
|
mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem);
|
455
486
|
if (!mtctx) return NULL;
|
456
|
-
|
487
|
+
ZSTDMT_CCtxParam_setNbThreads(&mtctx->params, nbThreads);
|
457
488
|
mtctx->cMem = cMem;
|
458
489
|
mtctx->allJobsCompleted = 1;
|
459
490
|
mtctx->factory = POOL_create_advanced(nbThreads, 0, cMem);
|
@@ -545,17 +576,23 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
|
|
545
576
|
}
|
546
577
|
|
547
578
|
/* Internal only */
|
548
|
-
size_t ZSTDMT_CCtxParam_setMTCtxParameter(
|
549
|
-
|
579
|
+
size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
|
580
|
+
ZSTDMT_parameter parameter, unsigned value) {
|
581
|
+
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter");
|
550
582
|
switch(parameter)
|
551
583
|
{
|
552
|
-
case
|
584
|
+
case ZSTDMT_p_jobSize :
|
585
|
+
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %u", value);
|
586
|
+
if ( (value > 0) /* value==0 => automatic job size */
|
587
|
+
& (value < ZSTDMT_JOBSIZE_MIN) )
|
588
|
+
value = ZSTDMT_JOBSIZE_MIN;
|
553
589
|
params->jobSize = value;
|
554
|
-
return
|
590
|
+
return value;
|
555
591
|
case ZSTDMT_p_overlapSectionLog :
|
592
|
+
if (value > 9) value = 9;
|
556
593
|
DEBUGLOG(4, "ZSTDMT_p_overlapSectionLog : %u", value);
|
557
594
|
params->overlapSizeLog = (value >= 9) ? 9 : value;
|
558
|
-
return
|
595
|
+
return value;
|
559
596
|
default :
|
560
597
|
return ERROR(parameter_unsupported);
|
561
598
|
}
|
@@ -563,9 +600,10 @@ size_t ZSTDMT_CCtxParam_setMTCtxParameter(
|
|
563
600
|
|
564
601
|
size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, unsigned value)
|
565
602
|
{
|
603
|
+
DEBUGLOG(4, "ZSTDMT_setMTCtxParameter");
|
566
604
|
switch(parameter)
|
567
605
|
{
|
568
|
-
case
|
606
|
+
case ZSTDMT_p_jobSize :
|
569
607
|
return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
|
570
608
|
case ZSTDMT_p_overlapSectionLog :
|
571
609
|
return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
|
@@ -601,7 +639,7 @@ static size_t ZSTDMT_compress_advanced_internal(
|
|
601
639
|
size_t const overlapSize = (overlapRLog>=9) ? 0 : (size_t)1 << (params.cParams.windowLog - overlapRLog);
|
602
640
|
unsigned nbChunks = computeNbChunks(srcSize, params.cParams.windowLog, params.nbThreads);
|
603
641
|
size_t const proposedChunkSize = (srcSize + (nbChunks-1)) / nbChunks;
|
604
|
-
size_t const avgChunkSize = ((proposedChunkSize & 0x1FFFF) < 0x7FFF) ? proposedChunkSize + 0xFFFF : proposedChunkSize; /* avoid too small last block */
|
642
|
+
size_t const avgChunkSize = (((proposedChunkSize-1) & 0x1FFFF) < 0x7FFF) ? proposedChunkSize + 0xFFFF : proposedChunkSize; /* avoid too small last block */
|
605
643
|
const char* const srcStart = (const char*)src;
|
606
644
|
size_t remainingSrcSize = srcSize;
|
607
645
|
unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbChunks : (unsigned)(dstCapacity / ZSTD_compressBound(avgChunkSize)); /* presumes avgChunkSize >= 256 KB, which should be the case */
|
@@ -610,7 +648,8 @@ static size_t ZSTDMT_compress_advanced_internal(
|
|
610
648
|
assert(jobParams.nbThreads == 0);
|
611
649
|
assert(mtctx->cctxPool->totalCCtx == params.nbThreads);
|
612
650
|
|
613
|
-
DEBUGLOG(4, "
|
651
|
+
DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: nbChunks=%2u (rawSize=%u bytes; fixedSize=%u) ",
|
652
|
+
nbChunks, (U32)proposedChunkSize, (U32)avgChunkSize);
|
614
653
|
if (nbChunks==1) { /* fallback to single-thread mode */
|
615
654
|
ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
|
616
655
|
if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams);
|
@@ -639,9 +678,9 @@ static size_t ZSTDMT_compress_advanced_internal(
|
|
639
678
|
|
640
679
|
mtctx->jobs[u].src = g_nullBuffer;
|
641
680
|
mtctx->jobs[u].srcStart = srcStart + frameStartPos - dictSize;
|
642
|
-
mtctx->jobs[u].
|
681
|
+
mtctx->jobs[u].prefixSize = dictSize;
|
643
682
|
mtctx->jobs[u].srcSize = chunkSize;
|
644
|
-
mtctx->jobs[u].cdict =
|
683
|
+
mtctx->jobs[u].cdict = (u==0) ? cdict : NULL;
|
645
684
|
mtctx->jobs[u].fullFrameSize = srcSize;
|
646
685
|
mtctx->jobs[u].params = jobParams;
|
647
686
|
/* do not calculate checksum within sections, but write it in header for first section */
|
@@ -659,7 +698,7 @@ static size_t ZSTDMT_compress_advanced_internal(
|
|
659
698
|
XXH64_update(&xxh64, srcStart + frameStartPos, chunkSize);
|
660
699
|
}
|
661
700
|
|
662
|
-
DEBUGLOG(5, "posting job %u
|
701
|
+
DEBUGLOG(5, "ZSTDMT_compress_advanced_internal: posting job %u (%u bytes)", u, (U32)chunkSize);
|
663
702
|
DEBUG_PRINTHEX(6, mtctx->jobs[u].srcStart, 12);
|
664
703
|
POOL_add(mtctx->factory, ZSTDMT_compressChunk, &mtctx->jobs[u]);
|
665
704
|
|
@@ -753,13 +792,14 @@ size_t ZSTDMT_initCStream_internal(
|
|
753
792
|
const ZSTD_CDict* cdict, ZSTD_CCtx_params params,
|
754
793
|
unsigned long long pledgedSrcSize)
|
755
794
|
{
|
756
|
-
DEBUGLOG(4, "ZSTDMT_initCStream_internal");
|
795
|
+
DEBUGLOG(4, "ZSTDMT_initCStream_internal (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
|
757
796
|
/* params are supposed to be fully validated at this point */
|
758
797
|
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
759
798
|
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
760
799
|
assert(zcs->cctxPool->totalCCtx == params.nbThreads);
|
800
|
+
zcs->singleThreaded = (params.nbThreads==1) | (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
|
761
801
|
|
762
|
-
if (
|
802
|
+
if (zcs->singleThreaded) {
|
763
803
|
ZSTD_CCtx_params const singleThreadParams = ZSTDMT_makeJobCCtxParams(params);
|
764
804
|
DEBUGLOG(4, "single thread mode");
|
765
805
|
assert(singleThreadParams.nbThreads == 0);
|
@@ -767,6 +807,7 @@ size_t ZSTDMT_initCStream_internal(
|
|
767
807
|
dict, dictSize, cdict,
|
768
808
|
singleThreadParams, pledgedSrcSize);
|
769
809
|
}
|
810
|
+
DEBUGLOG(4, "multi-threading mode (%u threads)", params.nbThreads);
|
770
811
|
|
771
812
|
if (zcs->allJobsCompleted == 0) { /* previous compression not correctly finished */
|
772
813
|
ZSTDMT_waitForAllJobsCompleted(zcs);
|
@@ -777,7 +818,6 @@ size_t ZSTDMT_initCStream_internal(
|
|
777
818
|
zcs->params = params;
|
778
819
|
zcs->frameContentSize = pledgedSrcSize;
|
779
820
|
if (dict) {
|
780
|
-
DEBUGLOG(4,"cdictLocal: %08X", (U32)(size_t)zcs->cdictLocal);
|
781
821
|
ZSTD_freeCDict(zcs->cdictLocal);
|
782
822
|
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
|
783
823
|
ZSTD_dlm_byCopy, dictMode, /* note : a loadPrefix becomes an internal CDict */
|
@@ -785,20 +825,20 @@ size_t ZSTDMT_initCStream_internal(
|
|
785
825
|
zcs->cdict = zcs->cdictLocal;
|
786
826
|
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
787
827
|
} else {
|
788
|
-
DEBUGLOG(4,"cdictLocal: %08X", (U32)(size_t)zcs->cdictLocal);
|
789
828
|
ZSTD_freeCDict(zcs->cdictLocal);
|
790
829
|
zcs->cdictLocal = NULL;
|
791
830
|
zcs->cdict = cdict;
|
792
831
|
}
|
793
832
|
|
833
|
+
assert(params.overlapSizeLog <= 9);
|
794
834
|
zcs->targetDictSize = (params.overlapSizeLog==0) ? 0 : (size_t)1 << (params.cParams.windowLog - (9 - params.overlapSizeLog));
|
795
|
-
DEBUGLOG(4, "overlapLog
|
796
|
-
DEBUGLOG(4, "overlap Size : %u KB", (U32)(zcs->targetDictSize>>10));
|
835
|
+
DEBUGLOG(4, "overlapLog=%u => %u KB", params.overlapSizeLog, (U32)(zcs->targetDictSize>>10));
|
797
836
|
zcs->targetSectionSize = params.jobSize ? params.jobSize : (size_t)1 << (params.cParams.windowLog + 2);
|
798
|
-
zcs->targetSectionSize
|
799
|
-
zcs->targetSectionSize
|
800
|
-
DEBUGLOG(4, "
|
837
|
+
if (zcs->targetSectionSize < ZSTDMT_JOBSIZE_MIN) zcs->targetSectionSize = ZSTDMT_JOBSIZE_MIN;
|
838
|
+
if (zcs->targetSectionSize < zcs->targetDictSize) zcs->targetSectionSize = zcs->targetDictSize; /* job size must be >= overlap size */
|
839
|
+
DEBUGLOG(4, "Job Size : %u KB (note : set to %u)", (U32)(zcs->targetSectionSize>>10), params.jobSize);
|
801
840
|
zcs->inBuffSize = zcs->targetDictSize + zcs->targetSectionSize;
|
841
|
+
DEBUGLOG(4, "inBuff Size : %u KB", (U32)(zcs->inBuffSize>>10));
|
802
842
|
ZSTDMT_setBufferSize(zcs->bufPool, MAX(zcs->inBuffSize, ZSTD_compressBound(zcs->targetSectionSize)) );
|
803
843
|
zcs->inBuff.buffer = g_nullBuffer;
|
804
844
|
zcs->dictSize = 0;
|
@@ -816,7 +856,7 @@ size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
|
816
856
|
unsigned long long pledgedSrcSize)
|
817
857
|
{
|
818
858
|
ZSTD_CCtx_params cctxParams = mtctx->params;
|
819
|
-
DEBUGLOG(5, "ZSTDMT_initCStream_advanced");
|
859
|
+
DEBUGLOG(5, "ZSTDMT_initCStream_advanced (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
|
820
860
|
cctxParams.cParams = params.cParams;
|
821
861
|
cctxParams.fParams = params.fParams;
|
822
862
|
return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dm_auto, NULL,
|
@@ -838,9 +878,12 @@ size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
|
838
878
|
|
839
879
|
|
840
880
|
/* ZSTDMT_resetCStream() :
|
841
|
-
* pledgedSrcSize
|
881
|
+
* pledgedSrcSize can be zero == unknown (for the time being)
|
882
|
+
* prefer using ZSTD_CONTENTSIZE_UNKNOWN,
|
883
|
+
* as `0` might mean "empty" in the future */
|
842
884
|
size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* zcs, unsigned long long pledgedSrcSize)
|
843
885
|
{
|
886
|
+
if (!pledgedSrcSize) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
844
887
|
if (zcs->params.nbThreads==1)
|
845
888
|
return ZSTD_resetCStream(zcs->cctxPool->cctx[0], pledgedSrcSize);
|
846
889
|
return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, 0, zcs->params,
|
@@ -852,7 +895,7 @@ size_t ZSTDMT_initCStream(ZSTDMT_CCtx* zcs, int compressionLevel) {
|
|
852
895
|
ZSTD_CCtx_params cctxParams = zcs->params;
|
853
896
|
cctxParams.cParams = params.cParams;
|
854
897
|
cctxParams.fParams = params.fParams;
|
855
|
-
return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, NULL, cctxParams,
|
898
|
+
return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
|
856
899
|
}
|
857
900
|
|
858
901
|
|
@@ -860,12 +903,12 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* zcs, size_t srcSize, unsi
|
|
860
903
|
{
|
861
904
|
unsigned const jobID = zcs->nextJobID & zcs->jobIDMask;
|
862
905
|
|
863
|
-
DEBUGLOG(
|
906
|
+
DEBUGLOG(5, "ZSTDMT_createCompressionJob: preparing job %u to compress %u bytes with %u preload ",
|
864
907
|
zcs->nextJobID, (U32)srcSize, (U32)zcs->dictSize);
|
865
908
|
zcs->jobs[jobID].src = zcs->inBuff.buffer;
|
866
909
|
zcs->jobs[jobID].srcStart = zcs->inBuff.buffer.start;
|
867
910
|
zcs->jobs[jobID].srcSize = srcSize;
|
868
|
-
zcs->jobs[jobID].
|
911
|
+
zcs->jobs[jobID].prefixSize = zcs->dictSize;
|
869
912
|
assert(zcs->inBuff.filled >= srcSize + zcs->dictSize);
|
870
913
|
zcs->jobs[jobID].params = zcs->params;
|
871
914
|
/* do not calculate checksum within sections, but write it in header for first section */
|
@@ -911,7 +954,7 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* zcs, size_t srcSize, unsi
|
|
911
954
|
zcs->params.fParams.checksumFlag = 0;
|
912
955
|
} }
|
913
956
|
|
914
|
-
DEBUGLOG(
|
957
|
+
DEBUGLOG(5, "ZSTDMT_createCompressionJob: posting job %u : %u bytes (end:%u) (note : doneJob = %u=>%u)",
|
915
958
|
zcs->nextJobID,
|
916
959
|
(U32)zcs->jobs[jobID].srcSize,
|
917
960
|
zcs->jobs[jobID].lastChunk,
|
@@ -930,6 +973,7 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* zcs, size_t srcSize, unsi
|
|
930
973
|
static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsigned blockToFlush)
|
931
974
|
{
|
932
975
|
unsigned const wJobID = zcs->doneJobID & zcs->jobIDMask;
|
976
|
+
DEBUGLOG(5, "ZSTDMT_flushNextJob");
|
933
977
|
if (zcs->doneJobID == zcs->nextJobID) return 0; /* all flushed ! */
|
934
978
|
ZSTD_PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
|
935
979
|
while (zcs->jobs[wJobID].jobCompleted==0) {
|
@@ -942,7 +986,8 @@ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsi
|
|
942
986
|
{ ZSTDMT_jobDescription job = zcs->jobs[wJobID];
|
943
987
|
if (!job.jobScanned) {
|
944
988
|
if (ZSTD_isError(job.cSize)) {
|
945
|
-
DEBUGLOG(5, "compression error detected "
|
989
|
+
DEBUGLOG(5, "job %u : compression error detected : %s",
|
990
|
+
zcs->doneJobID, ZSTD_getErrorName(job.cSize));
|
946
991
|
ZSTDMT_waitForAllJobsCompleted(zcs);
|
947
992
|
ZSTDMT_releaseAllJobResources(zcs);
|
948
993
|
return job.cSize;
|
@@ -991,15 +1036,18 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|
991
1036
|
{
|
992
1037
|
size_t const newJobThreshold = mtctx->dictSize + mtctx->targetSectionSize;
|
993
1038
|
unsigned forwardInputProgress = 0;
|
1039
|
+
DEBUGLOG(5, "ZSTDMT_compressStream_generic ");
|
994
1040
|
assert(output->pos <= output->size);
|
995
1041
|
assert(input->pos <= input->size);
|
1042
|
+
|
1043
|
+
if (mtctx->singleThreaded) { /* delegate to single-thread (synchronous) */
|
1044
|
+
return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
|
1045
|
+
}
|
1046
|
+
|
996
1047
|
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
|
997
1048
|
/* current frame being ended. Only flush/end are allowed */
|
998
1049
|
return ERROR(stage_wrong);
|
999
1050
|
}
|
1000
|
-
if (mtctx->params.nbThreads==1) { /* delegate to single-thread (synchronous) */
|
1001
|
-
return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
|
1002
|
-
}
|
1003
1051
|
|
1004
1052
|
/* single-pass shortcut (note : synchronous-mode) */
|
1005
1053
|
if ( (mtctx->nextJobID == 0) /* just started */
|
@@ -1068,32 +1116,34 @@ size_t ZSTDMT_compressStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, ZSTD_inBu
|
|
1068
1116
|
}
|
1069
1117
|
|
1070
1118
|
|
1071
|
-
static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx*
|
1119
|
+
static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, unsigned endFrame)
|
1072
1120
|
{
|
1073
|
-
size_t const srcSize =
|
1121
|
+
size_t const srcSize = mtctx->inBuff.filled - mtctx->dictSize;
|
1122
|
+
DEBUGLOG(5, "ZSTDMT_flushStream_internal");
|
1074
1123
|
|
1075
|
-
if ( ((srcSize > 0) || (endFrame && !
|
1076
|
-
&& (
|
1077
|
-
|
1124
|
+
if ( ((srcSize > 0) || (endFrame && !mtctx->frameEnded))
|
1125
|
+
&& (mtctx->nextJobID <= mtctx->doneJobID + mtctx->jobIDMask) ) {
|
1126
|
+
DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job");
|
1127
|
+
CHECK_F( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
|
1078
1128
|
}
|
1079
1129
|
|
1080
1130
|
/* check if there is any data available to flush */
|
1081
|
-
return ZSTDMT_flushNextJob(
|
1131
|
+
return ZSTDMT_flushNextJob(mtctx, output, 1 /* blockToFlush */);
|
1082
1132
|
}
|
1083
1133
|
|
1084
1134
|
|
1085
|
-
size_t ZSTDMT_flushStream(ZSTDMT_CCtx*
|
1135
|
+
size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
|
1086
1136
|
{
|
1087
1137
|
DEBUGLOG(5, "ZSTDMT_flushStream");
|
1088
|
-
if (
|
1089
|
-
return ZSTD_flushStream(
|
1090
|
-
return ZSTDMT_flushStream_internal(
|
1138
|
+
if (mtctx->singleThreaded)
|
1139
|
+
return ZSTD_flushStream(mtctx->cctxPool->cctx[0], output);
|
1140
|
+
return ZSTDMT_flushStream_internal(mtctx, output, 0 /* endFrame */);
|
1091
1141
|
}
|
1092
1142
|
|
1093
|
-
size_t ZSTDMT_endStream(ZSTDMT_CCtx*
|
1143
|
+
size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
|
1094
1144
|
{
|
1095
1145
|
DEBUGLOG(4, "ZSTDMT_endStream");
|
1096
|
-
if (
|
1097
|
-
return ZSTD_endStream(
|
1098
|
-
return ZSTDMT_flushStream_internal(
|
1146
|
+
if (mtctx->singleThreaded)
|
1147
|
+
return ZSTD_endStream(mtctx->cctxPool->cctx[0], output);
|
1148
|
+
return ZSTDMT_flushStream_internal(mtctx, output, 1 /* endFrame */);
|
1099
1149
|
}
|
@@ -50,7 +50,7 @@ ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
|
50
50
|
/* === Streaming functions === */
|
51
51
|
|
52
52
|
ZSTDLIB_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
|
53
|
-
ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize);
|
53
|
+
ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it may change in the future, to mean "empty" */
|
54
54
|
|
55
55
|
ZSTDLIB_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
56
56
|
|
@@ -60,8 +60,8 @@ ZSTDLIB_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output);
|
|
60
60
|
|
61
61
|
/* === Advanced functions and parameters === */
|
62
62
|
|
63
|
-
#ifndef
|
64
|
-
# define
|
63
|
+
#ifndef ZSTDMT_JOBSIZE_MIN
|
64
|
+
# define ZSTDMT_JOBSIZE_MIN (1U << 20) /* 1 MB - Minimum size of each compression job */
|
65
65
|
#endif
|
66
66
|
|
67
67
|
ZSTDLIB_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
|
@@ -84,13 +84,13 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
|
84
84
|
/* ZSTDMT_parameter :
|
85
85
|
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
|
86
86
|
typedef enum {
|
87
|
-
|
88
|
-
ZSTDMT_p_overlapSectionLog
|
87
|
+
ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
|
88
|
+
ZSTDMT_p_overlapSectionLog /* Each job may reload a part of previous job to enhance compressionr ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window */
|
89
89
|
} ZSTDMT_parameter;
|
90
90
|
|
91
91
|
/* ZSTDMT_setMTCtxParameter() :
|
92
92
|
* allow setting individual parameters, one at a time, among a list of enums defined in ZSTDMT_parameter.
|
93
|
-
* The function must be called typically after ZSTD_createCCtx()
|
93
|
+
* The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
|
94
94
|
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
|
95
95
|
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
96
96
|
ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, unsigned value);
|
@@ -112,7 +112,15 @@ ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|
112
112
|
|
113
113
|
size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, unsigned value);
|
114
114
|
|
115
|
-
|
115
|
+
/* ZSTDMT_CCtxParam_setNbThreads()
|
116
|
+
* Set nbThreads, and clamp it correctly,
|
117
|
+
* also reset jobSize and overlapLog */
|
118
|
+
size_t ZSTDMT_CCtxParam_setNbThreads(ZSTD_CCtx_params* params, unsigned nbThreads);
|
119
|
+
|
120
|
+
/* ZSTDMT_getNbThreads():
|
121
|
+
* @return nb threads currently active in mtctx.
|
122
|
+
* mtctx must be valid */
|
123
|
+
size_t ZSTDMT_getNbThreads(const ZSTDMT_CCtx* mtctx);
|
116
124
|
|
117
125
|
/*! ZSTDMT_initCStream_internal() :
|
118
126
|
* Private use only. Init streaming operation.
|