feat(mt): move input-range reuse policy into Rust
Move multithreaded input-range selection and overlap decisions into Rust using an explicit scalar projection. C retains the round-buffer mutation, LDM synchronization, prefix copying, and private job state, while Rust decides whether a reusable section is available and where it begins. Test Plan: - cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1 - cargo clippy --manifest-path rust/Cargo.toml --tests -- -D warnings - make -B -C lib -j2 lib - make -B -C tests -j2 test-cli-tests - make -B -C tests -j2 test-rust-lib-smoke
This commit is contained in:
@@ -276,8 +276,6 @@ unsigned ZSTDMT_rust_computeTargetJobLog(unsigned windowLog, unsigned chainLog,
|
||||
int ZSTDMT_rust_overlapLog(int overlapLog, int strategy);
|
||||
size_t ZSTDMT_rust_computeOverlapSize(unsigned windowLog, unsigned chainLog,
|
||||
int strategy, int overlapLog, int enableLdm);
|
||||
int ZSTDMT_rust_isOverlapped(const void* bufferStart, size_t bufferCapacity,
|
||||
const void* rangeStart, size_t rangeSize);
|
||||
int ZSTDMT_rust_doesOverlapWindow(const void* bufferStart, size_t bufferCapacity,
|
||||
const void* nextSrc, const void* base,
|
||||
const void* dictBase, U32 dictLimit, U32 lowLimit);
|
||||
@@ -302,12 +300,31 @@ typedef struct {
|
||||
const void* start;
|
||||
size_t size;
|
||||
} ZSTDMT_RustInputRange;
|
||||
typedef struct {
|
||||
const void* roundBufferStart;
|
||||
size_t roundBufferCapacity;
|
||||
size_t roundBufferPos;
|
||||
const void* prefixStart;
|
||||
size_t prefixSize;
|
||||
size_t targetSectionSize;
|
||||
const void* inUseStart;
|
||||
size_t inUseSize;
|
||||
} ZSTDMT_RustTryGetInputRangeProjection;
|
||||
typedef struct {
|
||||
unsigned ready;
|
||||
unsigned movePrefix;
|
||||
void* bufferStart;
|
||||
size_t bufferCapacity;
|
||||
size_t roundBufferPos;
|
||||
} ZSTDMT_RustTryGetInputRangeResult;
|
||||
typedef void (*ZSTDMT_jobProjectionFn)(void* opaque, unsigned jobID,
|
||||
ZSTDMT_RustJobProjection* projection);
|
||||
ZSTDMT_RustInputRange ZSTDMT_rust_getInputDataInUse(
|
||||
unsigned firstJobID, unsigned lastJobID, unsigned jobIDMask,
|
||||
size_t roundBufferCapacity, size_t targetSectionSize,
|
||||
void* opaque, ZSTDMT_jobProjectionFn projectJob);
|
||||
ZSTDMT_RustTryGetInputRangeResult ZSTDMT_rust_tryGetInputRange(
|
||||
const ZSTDMT_RustTryGetInputRangeProjection* projection);
|
||||
size_t ZSTDMT_rust_toFlushNow(unsigned doneJobID, unsigned nextJobID,
|
||||
unsigned jobIDMask, void* opaque,
|
||||
ZSTDMT_jobProjectionFn projectJob);
|
||||
@@ -1760,15 +1777,6 @@ static Range ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)
|
||||
return (Range){ range.start, range.size };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-zero iff buffer and range overlap.
|
||||
*/
|
||||
static int ZSTDMT_isOverlapped(Buffer buffer, Range range)
|
||||
{
|
||||
return ZSTDMT_rust_isOverlapped(buffer.start, buffer.capacity,
|
||||
range.start, range.size);
|
||||
}
|
||||
|
||||
static int ZSTDMT_doesOverlapWindow(Buffer buffer, ZSTD_window_t window)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTDMT_doesOverlapWindow");
|
||||
@@ -1811,15 +1819,29 @@ static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, Buffer buffer)
|
||||
static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
|
||||
{
|
||||
Range const inUse = ZSTDMT_getInputDataInUse(mtctx);
|
||||
size_t const spaceLeft = mtctx->roundBuff.capacity - mtctx->roundBuff.pos;
|
||||
size_t const spaceNeeded = mtctx->targetSectionSize;
|
||||
ZSTDMT_RustTryGetInputRangeProjection const projection = {
|
||||
mtctx->roundBuff.buffer,
|
||||
mtctx->roundBuff.capacity,
|
||||
mtctx->roundBuff.pos,
|
||||
mtctx->inBuff.prefix.start,
|
||||
mtctx->inBuff.prefix.size,
|
||||
mtctx->targetSectionSize,
|
||||
inUse.start,
|
||||
inUse.size
|
||||
};
|
||||
ZSTDMT_RustTryGetInputRangeResult const result =
|
||||
ZSTDMT_rust_tryGetInputRange(&projection);
|
||||
Buffer buffer;
|
||||
|
||||
DEBUGLOG(5, "ZSTDMT_tryGetInputRange");
|
||||
assert(mtctx->inBuff.buffer.start == NULL);
|
||||
assert(mtctx->roundBuff.capacity >= spaceNeeded);
|
||||
|
||||
if (spaceLeft < spaceNeeded) {
|
||||
if (!result.ready) {
|
||||
DEBUGLOG(5, "Waiting for buffer...");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (result.movePrefix) {
|
||||
/* ZSTD_invalidateRepCodes() doesn't work for extDict variants.
|
||||
* Simply copy the prefix to the beginning in that case.
|
||||
*/
|
||||
@@ -1828,23 +1850,14 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
|
||||
|
||||
buffer.start = start;
|
||||
buffer.capacity = prefixSize;
|
||||
if (ZSTDMT_isOverlapped(buffer, inUse)) {
|
||||
DEBUGLOG(5, "Waiting for buffer...");
|
||||
return 0;
|
||||
}
|
||||
ZSTDMT_waitForLdmComplete(mtctx, buffer);
|
||||
ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize);
|
||||
mtctx->inBuff.prefix.start = start;
|
||||
mtctx->roundBuff.pos = prefixSize;
|
||||
mtctx->roundBuff.pos = result.roundBufferPos;
|
||||
}
|
||||
buffer.start = mtctx->roundBuff.buffer + mtctx->roundBuff.pos;
|
||||
buffer.capacity = spaceNeeded;
|
||||
|
||||
if (ZSTDMT_isOverlapped(buffer, inUse)) {
|
||||
DEBUGLOG(5, "Waiting for buffer...");
|
||||
return 0;
|
||||
}
|
||||
assert(!ZSTDMT_isOverlapped(buffer, mtctx->inBuff.prefix));
|
||||
buffer.start = (BYTE*)result.bufferStart;
|
||||
buffer.capacity = result.bufferCapacity;
|
||||
|
||||
ZSTDMT_waitForLdmComplete(mtctx, buffer);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user