feat(compress): project MT frame headers into Rust
Pass the non-first multithreaded frame-header operation through an explicit scalar projection so Rust writes the header, advances the compression stage, and invalidates repcodes without calling the public C continue wrapper. Retain job descriptors, pools, synchronization, and CCtx initialization in C. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo fmt --all -- --check - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --lib zstdmt_compress::tests::compression_job -- --nocapture - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --all-targets -- -D warnings - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test - ulimit -v 41943040; make -j1 - ulimit -v 41943040; make -j1 -C tests test-zstream ZSTREAM_TESTTIME=-T2s - ulimit -v 41943040; make -j1 -C tests test-fuzzer FUZZERTEST=-T3s FUZZER_FLAGS=--no-big-tests
This commit is contained in:
@@ -121,10 +121,59 @@ typedef struct {
|
||||
size_t lastBlockSize;
|
||||
} ZSTDMT_chunkProcessResult;
|
||||
|
||||
typedef struct {
|
||||
void* dst;
|
||||
size_t dstCapacity;
|
||||
int* stage;
|
||||
int noDictIDFlag;
|
||||
int checksumFlag;
|
||||
int contentSizeFlag;
|
||||
int format;
|
||||
U32 windowLog;
|
||||
U64 pledgedSrcSizePlusOne;
|
||||
U32 dictID;
|
||||
U32* repCodes;
|
||||
} ZSTDMT_RustCompressionJobFrameHeaderState;
|
||||
typedef char ZSTDMT_compression_job_frame_header_state_layout[
|
||||
(offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, dst) == 0
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, dstCapacity)
|
||||
== sizeof(void*)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, stage)
|
||||
== 2 * sizeof(void*)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, noDictIDFlag)
|
||||
== 3 * sizeof(void*)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, checksumFlag)
|
||||
== 3 * sizeof(void*) + sizeof(int)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, contentSizeFlag)
|
||||
== 3 * sizeof(void*) + 2 * sizeof(int)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, format)
|
||||
== 3 * sizeof(void*) + 3 * sizeof(int)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, windowLog)
|
||||
== 3 * sizeof(void*) + 4 * sizeof(int)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, pledgedSrcSizePlusOne)
|
||||
== (sizeof(void*) == 8 ? 6 * sizeof(void*) : 8 * sizeof(void*))
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, dictID)
|
||||
== (sizeof(void*) == 8 ? 6 * sizeof(void*) : 8 * sizeof(void*))
|
||||
+ sizeof(U64)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobFrameHeaderState, repCodes)
|
||||
== (sizeof(void*) == 8 ? 8 * sizeof(void*) : 11 * sizeof(void*))
|
||||
&& sizeof(ZSTDMT_RustCompressionJobFrameHeaderState)
|
||||
== (sizeof(void*) == 8 ? 72 : 48))
|
||||
? 1 : -1];
|
||||
|
||||
typedef struct {
|
||||
unsigned firstJob;
|
||||
unsigned lastJob;
|
||||
const ZSTDMT_RustCompressionJobFrameHeaderState* frameHeaderState;
|
||||
} ZSTDMT_RustCompressionJobProjection;
|
||||
typedef char ZSTDMT_compression_job_projection_layout[
|
||||
(offsetof(ZSTDMT_RustCompressionJobProjection, firstJob) == 0
|
||||
&& offsetof(ZSTDMT_RustCompressionJobProjection, lastJob) == sizeof(unsigned)
|
||||
&& offsetof(ZSTDMT_RustCompressionJobProjection, frameHeaderState)
|
||||
== 2 * sizeof(unsigned)
|
||||
&& sizeof(ZSTDMT_RustCompressionJobProjection)
|
||||
== 2 * sizeof(unsigned) + sizeof(void*))
|
||||
? 1 : -1];
|
||||
|
||||
typedef struct {
|
||||
int status;
|
||||
@@ -149,7 +198,6 @@ void ZSTDMT_rust_compressionJob(
|
||||
ZSTDMT_compressionJobVoidFn generateSequences,
|
||||
ZSTDMT_compressionJobStepFn beginJob,
|
||||
ZSTDMT_compressionJobVoidFn applySequences,
|
||||
ZSTDMT_compressionJobStepFn writeFrameHeader,
|
||||
ZSTDMT_compressionJobCompressFn compressJob,
|
||||
ZSTDMT_compressionJobVoidFn traceJob,
|
||||
ZSTDMT_compressionJobErrorFn setError,
|
||||
@@ -1355,6 +1403,7 @@ typedef struct {
|
||||
ZSTD_CCtx* cctx;
|
||||
RawSeqStore_t rawSeqStore;
|
||||
Buffer dstBuff;
|
||||
ZSTDMT_RustCompressionJobFrameHeaderState frameHeaderState;
|
||||
} ZSTDMT_compressionJobState;
|
||||
|
||||
static size_t ZSTDMT_compressionJobAcquireResources(void* opaque)
|
||||
@@ -1373,6 +1422,8 @@ static size_t ZSTDMT_compressionJobAcquireResources(void* opaque)
|
||||
if (state->dstBuff.start == NULL) return ERROR(memory_allocation);
|
||||
job->dstBuff = state->dstBuff;
|
||||
}
|
||||
state->frameHeaderState.dst = state->dstBuff.start;
|
||||
state->frameHeaderState.dstCapacity = state->dstBuff.capacity;
|
||||
if (state->jobParams.ldmParams.enableLdm == ZSTD_ps_enable &&
|
||||
state->rawSeqStore.seq == NULL)
|
||||
return ERROR(memory_allocation);
|
||||
@@ -1418,18 +1469,17 @@ static size_t ZSTDMT_compressionJobBegin(void* opaque)
|
||||
ZSTDMT_compressionJobState* const state =
|
||||
(ZSTDMT_compressionJobState*)opaque;
|
||||
ZSTDMT_jobDescription* const job = state->job;
|
||||
size_t initError;
|
||||
|
||||
if (job->cdict) {
|
||||
size_t const initError = ZSTD_compressBegin_advanced_internal(
|
||||
initError = ZSTD_compressBegin_advanced_internal(
|
||||
state->cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict,
|
||||
&state->jobParams, job->fullFrameSize);
|
||||
assert(job->firstJob); /* only allowed for first job */
|
||||
return initError;
|
||||
}
|
||||
|
||||
{ U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
|
||||
} else {
|
||||
U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
|
||||
size_t const forceWindowError = ZSTD_CCtxParams_setParameter(
|
||||
&state->jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
||||
&state->jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
||||
if (ZSTD_isError(forceWindowError)) return forceWindowError;
|
||||
if (!job->firstJob) {
|
||||
size_t const err = ZSTD_CCtxParams_setParameter(
|
||||
@@ -1437,11 +1487,29 @@ static size_t ZSTDMT_compressionJobBegin(void* opaque)
|
||||
if (ZSTD_isError(err)) return err;
|
||||
}
|
||||
DEBUGLOG(6, "ZSTDMT_compressionJob: job %u: loading prefix of size %zu", job->jobID, job->prefix.size);
|
||||
return ZSTD_compressBegin_advanced_internal(
|
||||
initError = ZSTD_compressBegin_advanced_internal(
|
||||
state->cctx, job->prefix.start, job->prefix.size,
|
||||
ZSTD_dct_rawContent, ZSTD_dtlm_fast, NULL, /*cdict*/
|
||||
&state->jobParams, pledgedSrcSize);
|
||||
}
|
||||
|
||||
if (ZSTD_isError(initError)) return initError;
|
||||
state->frameHeaderState.stage = (int*)&state->cctx->stage;
|
||||
state->frameHeaderState.noDictIDFlag =
|
||||
state->cctx->appliedParams.fParams.noDictIDFlag;
|
||||
state->frameHeaderState.checksumFlag =
|
||||
state->cctx->appliedParams.fParams.checksumFlag;
|
||||
state->frameHeaderState.contentSizeFlag =
|
||||
state->cctx->appliedParams.fParams.contentSizeFlag;
|
||||
state->frameHeaderState.format = (int)state->cctx->appliedParams.format;
|
||||
state->frameHeaderState.windowLog =
|
||||
state->cctx->appliedParams.cParams.windowLog;
|
||||
state->frameHeaderState.pledgedSrcSizePlusOne =
|
||||
state->cctx->pledgedSrcSizePlusOne;
|
||||
state->frameHeaderState.dictID = state->cctx->dictID;
|
||||
state->frameHeaderState.repCodes = state->cctx->blockState.prevCBlock == NULL
|
||||
? NULL : state->cctx->blockState.prevCBlock->rep;
|
||||
return initError;
|
||||
}
|
||||
|
||||
static void ZSTDMT_compressionJobApplySequences(void* opaque)
|
||||
@@ -1455,20 +1523,6 @@ static void ZSTDMT_compressionJobApplySequences(void* opaque)
|
||||
&state->rawSeqStore);
|
||||
}
|
||||
|
||||
static size_t ZSTDMT_compressionJobWriteFrameHeader(void* opaque)
|
||||
{
|
||||
ZSTDMT_compressionJobState* const state =
|
||||
(ZSTDMT_compressionJobState*)opaque;
|
||||
ZSTDMT_jobDescription* const job = state->job;
|
||||
size_t const hSize = ZSTD_compressContinue_public(
|
||||
state->cctx, state->dstBuff.start, state->dstBuff.capacity,
|
||||
job->src.start, 0);
|
||||
if (ZSTD_isError(hSize)) return hSize;
|
||||
DEBUGLOG(5, "ZSTDMT_compressionJob: flush and overwrite %u bytes of frame header (not first job)", (U32)hSize);
|
||||
ZSTD_invalidateRepCodes(state->cctx);
|
||||
return hSize;
|
||||
}
|
||||
|
||||
static ZSTDMT_chunkProcessResult ZSTDMT_compressionJobCompress(
|
||||
void* opaque, unsigned lastJob)
|
||||
{
|
||||
@@ -1545,7 +1599,8 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
||||
ZSTDMT_compressionJobState state;
|
||||
ZSTDMT_RustCompressionJobProjection const projection = {
|
||||
job->firstJob,
|
||||
job->lastJob
|
||||
job->lastJob,
|
||||
&state.frameHeaderState
|
||||
};
|
||||
|
||||
ZSTD_memset(&state, 0, sizeof(state));
|
||||
@@ -1560,7 +1615,6 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
||||
ZSTDMT_compressionJobGenerateSequences,
|
||||
ZSTDMT_compressionJobBegin,
|
||||
ZSTDMT_compressionJobApplySequences,
|
||||
ZSTDMT_compressionJobWriteFrameHeader,
|
||||
ZSTDMT_compressionJobCompress,
|
||||
ZSTDMT_compressionJobTrace,
|
||||
ZSTDMT_compressionJobSetError,
|
||||
|
||||
Reference in New Issue
Block a user