zstd-ruby 1.3.2.0 → 1.3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/BUCK +31 -10
  4. data/ext/zstdruby/libzstd/common/bitstream.h +1 -1
  5. data/ext/zstdruby/libzstd/common/mem.h +15 -13
  6. data/ext/zstdruby/libzstd/common/pool.c +1 -2
  7. data/ext/zstdruby/libzstd/common/zstd_common.c +10 -4
  8. data/ext/zstdruby/libzstd/common/zstd_internal.h +52 -170
  9. data/ext/zstdruby/libzstd/compress/zstd_compress.c +434 -337
  10. data/ext/zstdruby/libzstd/compress/{zstd_compress.h → zstd_compress_internal.h} +191 -36
  11. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +1 -0
  12. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -2
  13. data/ext/zstdruby/libzstd/compress/zstd_fast.c +1 -0
  14. data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -2
  15. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +66 -50
  16. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +3 -2
  17. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +3 -2
  18. data/ext/zstdruby/libzstd/compress/zstd_opt.c +504 -676
  19. data/ext/zstdruby/libzstd/compress/zstd_opt.h +2 -2
  20. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +130 -80
  21. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +15 -7
  22. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +41 -31
  23. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -0
  24. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +1 -1
  25. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +1 -1
  26. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +1 -74
  27. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +1 -74
  28. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -72
  29. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +1 -73
  30. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +1 -77
  31. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +1 -77
  32. data/ext/zstdruby/libzstd/zstd.h +43 -30
  33. data/lib/zstd-ruby/version.rb +1 -1
  34. 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 "zstd_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
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 <= 10*bSize)) {
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, "buffer pool capacity reached => freeing ");
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 dictSize;
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->dictSize;
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) : dictSize %u, srcSize %u",
331
- job->firstChunk, job->lastChunk, (U32)job->dictSize, (U32)job->srcSize);
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) { /* should only happen for first segment */
348
- size_t const initError = ZSTD_compressBegin_usingCDict_advanced(cctx, job->cdict, job->params.fParams, job->fullFrameSize);
349
- DEBUGLOG(5, "using CDict");
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
- if (!job->firstChunk) job->params.fParams.contentSizeFlag = 0; /* ensure no srcSize control */
353
- { ZSTD_CCtx_params jobParams = job->params;
354
- size_t const forceWindowError =
355
- ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_p_forceMaxWindow, !job->firstChunk);
356
- /* Force loading dictionary in "content-only" mode (no header analysis) */
357
- size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, job->srcStart, job->dictSize, ZSTD_dm_rawContent, jobParams, job->fullFrameSize);
358
- if (ZSTD_isError(initError) || ZSTD_isError(forceWindowError)) {
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 segment */
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(4, job->srcStart, 12);
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
- /* Internal only */
434
- size_t ZSTDMT_initializeCCtxParameters(ZSTD_CCtx_params* params, unsigned nbThreads)
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 0;
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
- ZSTDMT_initializeCCtxParameters(&mtctx->params, nbThreads);
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
- ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, unsigned value) {
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 ZSTDMT_p_sectionSize :
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 0;
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 0;
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 ZSTDMT_p_sectionSize :
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, "nbChunks : %2u (chunkSize : %u bytes) ", nbChunks, (U32)avgChunkSize);
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].dictSize = dictSize;
681
+ mtctx->jobs[u].prefixSize = dictSize;
643
682
  mtctx->jobs[u].srcSize = chunkSize;
644
- mtctx->jobs[u].cdict = mtctx->nextJobID==0 ? cdict : NULL;
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 (%u bytes)", u, (U32)chunkSize);
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 (params.nbThreads==1) {
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 : %u ", params.overlapSizeLog);
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 = MAX(ZSTDMT_SECTION_SIZE_MIN, zcs->targetSectionSize);
799
- zcs->targetSectionSize = MAX(zcs->targetDictSize, zcs->targetSectionSize);
800
- DEBUGLOG(4, "Section Size : %u KB", (U32)(zcs->targetSectionSize>>10));
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 is optional and can be zero == unknown */
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, 0);
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(4, "preparing job %u to compress %u bytes with %u preload ",
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].dictSize = zcs->dictSize;
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(4, "posting job %u : %u bytes (end:%u) (note : doneJob = %u=>%u)",
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* zcs, ZSTD_outBuffer* output, unsigned endFrame)
1119
+ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, unsigned endFrame)
1072
1120
  {
1073
- size_t const srcSize = zcs->inBuff.filled - zcs->dictSize;
1121
+ size_t const srcSize = mtctx->inBuff.filled - mtctx->dictSize;
1122
+ DEBUGLOG(5, "ZSTDMT_flushStream_internal");
1074
1123
 
1075
- if ( ((srcSize > 0) || (endFrame && !zcs->frameEnded))
1076
- && (zcs->nextJobID <= zcs->doneJobID + zcs->jobIDMask) ) {
1077
- CHECK_F( ZSTDMT_createCompressionJob(zcs, srcSize, endFrame) );
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(zcs, output, 1 /* blockToFlush */);
1131
+ return ZSTDMT_flushNextJob(mtctx, output, 1 /* blockToFlush */);
1082
1132
  }
1083
1133
 
1084
1134
 
1085
- size_t ZSTDMT_flushStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
1135
+ size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
1086
1136
  {
1087
1137
  DEBUGLOG(5, "ZSTDMT_flushStream");
1088
- if (zcs->params.nbThreads==1)
1089
- return ZSTD_flushStream(zcs->cctxPool->cctx[0], output);
1090
- return ZSTDMT_flushStream_internal(zcs, output, 0 /* endFrame */);
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* zcs, ZSTD_outBuffer* output)
1143
+ size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
1094
1144
  {
1095
1145
  DEBUGLOG(4, "ZSTDMT_endStream");
1096
- if (zcs->params.nbThreads==1)
1097
- return ZSTD_endStream(zcs->cctxPool->cctx[0], output);
1098
- return ZSTDMT_flushStream_internal(zcs, output, 1 /* endFrame */);
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); /**< pledgedSrcSize is optional and can be zero == unknown */
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 ZSTDMT_SECTION_SIZE_MIN
64
- # define ZSTDMT_SECTION_SIZE_MIN (1U << 20) /* 1 MB - Minimum size of each compression job */
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
- ZSTDMT_p_sectionSize, /* size of input "section". Each section is compressed in parallel. 0 means default, which is dynamically determined within compression functions */
88
- ZSTDMT_p_overlapSectionLog /* Log of overlapped section; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window */
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
- size_t ZSTDMT_initializeCCtxParameters(ZSTD_CCtx_params* params, unsigned nbThreads);
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.