unsigned long long afterTime = GetCurrentClockTimeMicroseconds(); \
unsigned long long elapsedTime = (afterTime-beforeTime); \
if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
- DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread %li took %llu microseconds to acquire mutex %s \n", \
- (long int) pthread_self(), elapsedTime, #mutex); \
+ DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
+ elapsedTime, #mutex); \
} \
} else pthread_mutex_lock(mutex);
buffer_t dstBuff;
int compressionLevel;
unsigned frameID;
+ unsigned long long fullFrameSize;
size_t cSize;
unsigned jobCompleted;
pthread_mutex_t* jobCompleted_mutex;
void ZSTDMT_compressFrame(void* jobDescription)
{
ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
- job->cSize = ZSTD_compressCCtx(job->cctx, job->dstBuff.start, job->dstBuff.size, job->srcStart, job->srcSize, job->compressionLevel);
+ buffer_t dstBuff = job->dstBuff;
+ ZSTD_parameters const params = ZSTD_getParams(job->compressionLevel, job->fullFrameSize, 0);
+ size_t hSize = ZSTD_compressBegin_advanced(job->cctx, NULL, 0, params, job->fullFrameSize);
+ if (ZSTD_isError(hSize)) { job->cSize = hSize; goto _endJob; }
+ hSize = ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, job->srcStart, 0); /* flush frame header */
+ if (ZSTD_isError(hSize)) { job->cSize = hSize; goto _endJob; }
+ if ((job->frameID & 1) == 0) { /* preserve frame header when it is first beginning of frame */
+ dstBuff.start = (char*)dstBuff.start + hSize;
+ dstBuff.size -= hSize;
+ } else
+ hSize = 0;
+
+ job->cSize = (job->frameID>=2) ? /* last chunk signal */
+ ZSTD_compressEnd(job->cctx, dstBuff.start, dstBuff.size, job->srcStart, job->srcSize) :
+ ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, job->srcStart, job->srcSize);
+ if (!ZSTD_isError(job->cSize)) job->cSize += hSize;
DEBUGLOG(5, "frame %u : compressed %u bytes into %u bytes ", (unsigned)job->frameID, (unsigned)job->srcSize, (unsigned)job->cSize);
- pthread_mutex_lock(job->jobCompleted_mutex);
+
+_endJob:
+ PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
job->jobCompleted = 1;
pthread_cond_signal(job->jobCompleted_cond);
pthread_mutex_unlock(job->jobCompleted_mutex);
mtctx->jobs[u].srcStart = srcStart + frameStartPos;
mtctx->jobs[u].srcSize = frameSize;
+ mtctx->jobs[u].fullFrameSize = srcSize;
mtctx->jobs[u].compressionLevel = compressionLevel;
mtctx->jobs[u].dstBuff = dstBuffer;
mtctx->jobs[u].cctx = cctx;
- mtctx->jobs[u].frameID = u;
+ mtctx->jobs[u].frameID = (u>0) | ((u==nbFrames-1)<<1);
mtctx->jobs[u].jobCompleted = 0;
mtctx->jobs[u].jobCompleted_mutex = &mtctx->jobCompleted_mutex;
mtctx->jobs[u].jobCompleted_cond = &mtctx->jobCompleted_cond;
for (frameID=0; frameID<nbFrames; frameID++) {
DEBUGLOG(3, "ready to write frame %u ", frameID);
- pthread_mutex_lock(&mtctx->jobCompleted_mutex);
+ PTHREAD_MUTEX_LOCK(&mtctx->jobCompleted_mutex);
while (mtctx->jobs[frameID].jobCompleted==0) {
DEBUGLOG(4, "waiting for jobCompleted signal from frame %u", frameID);
pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
In which case, it will "discard" the relevant memory section from its history.
Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.
- It's possible to use a NULL,0 src content, in which case, it will write a final empty block to end the frame,
- Without last block mark, frames will be considered unfinished (broken) by decoders.
+ It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.
+ Without last block mark, frames will be considered unfinished (corrupted) by decoders.
- You can then reuse `ZSTD_CCtx` (ZSTD_compressBegin()) to compress some new frame.
+ `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress some new frame.
*/
/*===== Buffer-less streaming compression functions =====*/
memcpy(compressedBuffer, srcBuffer, loadedCompressedSize);
}
-#if 1
+#if 0 /* disable decompression test */
dCompleted=1;
(void)totalDTime; (void)fastestD; (void)crcOrig; /* unused when decompression disabled */
#else
UTIL_sleepMilli(1); /* give processor time to other processes */
UTIL_waitForNextTick(ticksPerSecond);
- UTIL_getTime(&clockStart);
if (!dCompleted) {
U64 clockLoop = g_nbSeconds ? TIMELOOP_MICROSEC : 1;
U32 nbLoops = 0;
+ clock_us_t clockStart;
ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictBufferSize);
if (!ddict) EXM_THROW(2, "ZSTD_createDDict() allocation failure");
+ clockStart = BMK_clockMicroSec();
do {
U32 blockNb;
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
blockTable[blockNb].cPtr, blockTable[blockNb].cSize,
ddict);
if (ZSTD_isError(regenSize)) {
- DISPLAY("ZSTD_decompress_usingDDict() failed on block %u : %s \n",
- blockNb, ZSTD_getErrorName(regenSize));
+ DISPLAY("ZSTD_decompress_usingDDict() failed on block %u of size %u : %s \n",
+ blockNb, (U32)blockTable[blockNb].cSize, ZSTD_getErrorName(regenSize));
clockLoop = 0; /* force immediate test end */
break;
}
blockTable[blockNb].resSize = regenSize;
}
nbLoops++;
- } while (UTIL_clockSpanMicro(clockStart, ticksPerSecond) < clockLoop);
+ } while (BMK_clockMicroSec() - clockStart < clockLoop);
ZSTD_freeDDict(ddict);
- { U64 const clockSpan = UTIL_clockSpanMicro(clockStart, ticksPerSecond);
- if (clockSpan < fastestD*nbLoops) fastestD = clockSpan / nbLoops;
- totalDTime += clockSpan;
+ { clock_us_t const clockSpanMicro = BMK_clockMicroSec() - clockStart;
+ if (clockSpanMicro < fastestD*nbLoops) fastestD = clockSpanMicro / nbLoops;
+ totalDTime += clockSpanMicro;
dCompleted = (totalDTime >= maxTime);
} }