refactor(compress): move MT stream loop to Rust
Move the multithreaded compressStream2 outer coordinator into the Rust compression module. The C bridge now owns only the private ZSTDMT call and consumed/produced counters, while Rust preserves the progress loop, completion ordering, and error handoff. Keep the MT context mutations, diagnostics, assertions, and buffer-expectation publication in C because they depend on the private context layout. Add callback-driven tests for continue/break, error completion, end trace/reset ordering, and malformed states. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings - ulimit -v 41943040; CARGO_BUILD_JOBS=1 make -j1 - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/cli/Cargo.toml --all-targets - ulimit -v 41943040; CARGO_BUILD_JOBS=1 make -j1 -C tests test - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
This commit is contained in:
@@ -1012,6 +1012,36 @@ typedef char ZSTD_rust_compress_stream2_mt_completion_state_layout[
|
||||
&& sizeof(ZSTD_rust_compressStream2MTCompletionState)
|
||||
== 2 * sizeof(void*))
|
||||
? 1 : -1];
|
||||
typedef size_t (*ZSTD_rust_compressStream2MTStep_f)(
|
||||
void* context, ZSTD_outBuffer* output, ZSTD_inBuffer* input, int endOp);
|
||||
typedef struct {
|
||||
void* callbackContext;
|
||||
ZSTD_rust_compressStream2MTStep_f step;
|
||||
ZSTD_outBuffer* output;
|
||||
ZSTD_inBuffer* input;
|
||||
const ZSTD_rust_compressStream2MTCompletionCallbacks* completionCallbacks;
|
||||
int endOp;
|
||||
} ZSTD_rust_compressStream2MTCoordinatorState;
|
||||
size_t ZSTD_rust_compressStream2MTCoordinator(
|
||||
const ZSTD_rust_compressStream2MTCoordinatorState* state);
|
||||
typedef char ZSTD_rust_compress_stream2_mt_coordinator_state_layout[
|
||||
(offsetof(ZSTD_rust_compressStream2MTCoordinatorState, callbackContext)
|
||||
== 0
|
||||
&& offsetof(ZSTD_rust_compressStream2MTCoordinatorState, step)
|
||||
== sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTCoordinatorState, output)
|
||||
== 2 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTCoordinatorState, input)
|
||||
== 3 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTCoordinatorState,
|
||||
completionCallbacks)
|
||||
== 4 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTCoordinatorState, endOp)
|
||||
== 5 * sizeof(void*)
|
||||
&& sizeof(ZSTD_rust_compressStream2MTStep_f) == sizeof(void*)
|
||||
&& sizeof(ZSTD_rust_compressStream2MTCoordinatorState)
|
||||
== 6 * sizeof(void*))
|
||||
? 1 : -1];
|
||||
int ZSTD_rust_simpleCompress2Level(const void* cctx, size_t srcSize);
|
||||
typedef int (*ZSTD_rust_simpleCompress2Level_f)(const void* cctx, size_t srcSize);
|
||||
typedef struct {
|
||||
@@ -8674,6 +8704,19 @@ static size_t ZSTD_rust_compressStream2MT_reset(void* context)
|
||||
{
|
||||
return ZSTD_CCtx_reset((ZSTD_CCtx*)context, ZSTD_reset_session_only);
|
||||
}
|
||||
|
||||
static size_t ZSTD_rust_compressStream2MT_step(
|
||||
void* context, ZSTD_outBuffer* output, ZSTD_inBuffer* input, int endOp)
|
||||
{
|
||||
ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context;
|
||||
size_t const ipos = input->pos;
|
||||
size_t const opos = output->pos;
|
||||
size_t const flushMin = ZSTDMT_compressStream_generic(
|
||||
cctx->mtctx, output, input, (ZSTD_EndDirective)endOp);
|
||||
cctx->consumedSrcSize += (U64)(input->pos - ipos);
|
||||
cctx->producedCSize += (U64)(output->pos - opos);
|
||||
return flushMin;
|
||||
}
|
||||
#endif /* ZSTD_MULTITHREAD */
|
||||
|
||||
size_t ZSTD_compressStream2_c( ZSTD_CCtx* cctx,
|
||||
@@ -8781,41 +8824,22 @@ size_t ZSTD_compressStream2_c( ZSTD_CCtx* cctx,
|
||||
input->pos -= cctx->stableIn_notConsumed;
|
||||
cctx->stableIn_notConsumed = 0;
|
||||
}
|
||||
for (;;) {
|
||||
size_t const ipos = input->pos;
|
||||
size_t const opos = output->pos;
|
||||
flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
||||
cctx->consumedSrcSize += (U64)(input->pos - ipos);
|
||||
cctx->producedCSize += (U64)(output->pos - opos);
|
||||
{ ZSTD_rust_compressStream2MTLoopPolicyState const state = {
|
||||
(int)endOp,
|
||||
flushMin,
|
||||
input->pos,
|
||||
input->size,
|
||||
ipos,
|
||||
output->pos,
|
||||
output->size,
|
||||
opos
|
||||
};
|
||||
int const loopPolicy =
|
||||
ZSTD_rust_compressStream2MTLoopPolicy(&state);
|
||||
{ ZSTD_rust_compressStream2MTCompletionCallbacks const callbacks = {
|
||||
cctx,
|
||||
ZSTD_rust_compressStream2MT_trace,
|
||||
ZSTD_rust_compressStream2MT_reset
|
||||
};
|
||||
ZSTD_rust_compressStream2MTCompletionState const completionState = {
|
||||
loopPolicy,
|
||||
&callbacks
|
||||
};
|
||||
ZSTD_rust_compressStream2MTCompletion(&completionState);
|
||||
}
|
||||
FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
|
||||
if (loopPolicy == ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_BREAK
|
||||
|| loopPolicy == ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_END_COMPLETE)
|
||||
break;
|
||||
}
|
||||
{ ZSTD_rust_compressStream2MTCompletionCallbacks const callbacks = {
|
||||
cctx,
|
||||
ZSTD_rust_compressStream2MT_trace,
|
||||
ZSTD_rust_compressStream2MT_reset
|
||||
};
|
||||
ZSTD_rust_compressStream2MTCoordinatorState const state = {
|
||||
cctx,
|
||||
ZSTD_rust_compressStream2MT_step,
|
||||
output,
|
||||
input,
|
||||
&callbacks,
|
||||
(int)endOp
|
||||
};
|
||||
flushMin = ZSTD_rust_compressStream2MTCoordinator(&state);
|
||||
}
|
||||
FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
|
||||
DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
|
||||
/* Either we don't require maximum forward progress, we've finished the
|
||||
* flush, or we are out of output space.
|
||||
|
||||
Reference in New Issue
Block a user