feat(streaming): enforce typed completion queues
Replace the flat deferred list, priority scan, unload bypass, and count-only execution cap with exact destination/control/unload/Near/Far FIFOs behind one typed frame meter. Price worker results before adoption, retain exact retry identity, reject stale generations without payload retention, and publish queue pressure through lifecycle diagnostics. Tests: dotnet build AcDream.slnx -c Release --no-restore; dotnet test AcDream.slnx -c Release --no-restore (8138 passed, 5 skipped)
This commit is contained in:
parent
ac45cb1bd7
commit
b8f6317fe1
15 changed files with 1261 additions and 336 deletions
|
|
@ -263,6 +263,34 @@ public class LandblockStreamerTests
|
|||
Assert.Equal(43ul, unloaded.Generation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CompletionSourcePeekPreservesExactResultAndBacklog()
|
||||
{
|
||||
using var streamer = new LandblockStreamer(loadLandblock: _ => null);
|
||||
streamer.Start();
|
||||
streamer.EnqueueUnload(0xABCE0000u, generation: 44);
|
||||
|
||||
for (int i = 0;
|
||||
i < SpinMaxIterations && streamer.BacklogCount == 0;
|
||||
i++)
|
||||
{
|
||||
await Task.Delay(SpinStepMs);
|
||||
}
|
||||
|
||||
Assert.Equal(1, streamer.BacklogCount);
|
||||
Assert.True(streamer.TryPeek(out LandblockStreamResult? firstPeek));
|
||||
Assert.NotNull(firstPeek);
|
||||
Assert.Equal(1, streamer.BacklogCount);
|
||||
Assert.True(streamer.TryPeek(out LandblockStreamResult? secondPeek));
|
||||
Assert.Same(firstPeek, secondPeek);
|
||||
Assert.Equal(1, streamer.BacklogCount);
|
||||
|
||||
Assert.True(streamer.TryRead(out LandblockStreamResult? consumed));
|
||||
Assert.Same(firstPeek, consumed);
|
||||
Assert.Equal(0, streamer.BacklogCount);
|
||||
Assert.False(streamer.TryRead(out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Load_ExecutesLoaderOnWorkerThread()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public class StreamingControllerPriorityApplyTests
|
|||
generation);
|
||||
|
||||
[Fact]
|
||||
public void PriorityLandblock_isApplied_evenWhenBeyondPerFrameCap()
|
||||
public void PriorityLandblock_WinsExecutionOrderAfterBoundedAdmission()
|
||||
{
|
||||
uint priority = StreamingRegion.EncodeLandblockIdForTest(169, 180);
|
||||
var outbox = new Queue<LandblockStreamResult>(new LandblockStreamResult[]
|
||||
|
|
@ -42,14 +42,18 @@ public class StreamingControllerPriorityApplyTests
|
|||
return batch;
|
||||
},
|
||||
applyTerrain: (lb, _) => applied.Add(lb.LandblockId),
|
||||
state: state, nearRadius: 4, farRadius: 12)
|
||||
state: state,
|
||||
nearRadius: 4,
|
||||
farRadius: 12,
|
||||
workBudgetOptions: GenerousBudget())
|
||||
{ MaxCompletionsPerFrame = 4 };
|
||||
|
||||
ctrl.PriorityLandblockId = priority;
|
||||
ctrl.Tick(169, 180);
|
||||
|
||||
Assert.Contains(priority, applied); // priority applied THIS tick
|
||||
Assert.True(applied.Count <= 5); // did not blindly flush the whole outbox
|
||||
Assert.NotEmpty(applied);
|
||||
Assert.Equal(priority, applied[0]);
|
||||
Assert.True(applied.Count <= 5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -98,10 +102,8 @@ public class StreamingControllerPriorityApplyTests
|
|||
public void PriorityNeverArrives_noThrow_noLoss_noDoubleApply()
|
||||
{
|
||||
// While a PriorityLandblockId is set but the matching completion never
|
||||
// arrives (e.g. the load failed), the hunt moves outbox completions into
|
||||
// _deferredApply and they drain at the per-frame budget — same backpressure
|
||||
// as the normal throttle, just relocated — until the caller clears
|
||||
// PriorityLandblockId (the TAS MaxContinue safety net does this on timeout).
|
||||
// arrives (e.g. the load failed), ordinary results still enter the typed
|
||||
// Near/Far queues and advance under the same budget without loss.
|
||||
uint priority = StreamingRegion.EncodeLandblockIdForTest(169, 180);
|
||||
uint otherId0 = StreamingRegion.EncodeLandblockIdForTest(169, 181);
|
||||
uint otherId1 = StreamingRegion.EncodeLandblockIdForTest(169, 182);
|
||||
|
|
@ -149,6 +151,15 @@ public class StreamingControllerPriorityApplyTests
|
|||
Assert.Equal(3, applied.Count);
|
||||
}
|
||||
|
||||
private static StreamingWorkBudgetOptions GenerousBudget() => new(
|
||||
MaxUpdateMilliseconds: 100,
|
||||
MaxCompletionAdmissions: 64,
|
||||
MaxAdoptedCpuBytes: 16 * StreamingWorkBudgetOptions.MiB,
|
||||
MaxEntityOperations: 10_000,
|
||||
MaxGpuUploadBytes: 16 * StreamingWorkBudgetOptions.MiB,
|
||||
MaxGlRetireOperations: 10_000,
|
||||
DestinationReserveFraction: 0.75f);
|
||||
|
||||
[Fact]
|
||||
public void DeferredCompaction_ApplyFailureRetainsExactResultWithoutReplayingCommittedPrefix()
|
||||
{
|
||||
|
|
@ -223,7 +234,15 @@ public class StreamingControllerPriorityApplyTests
|
|||
applyTerrain: (build, _) => applied.Add(build.LandblockId),
|
||||
state: state,
|
||||
nearRadius: 4,
|
||||
farRadius: 12)
|
||||
farRadius: 12,
|
||||
workBudgetOptions: new StreamingWorkBudgetOptions(
|
||||
MaxUpdateMilliseconds: 100,
|
||||
MaxCompletionAdmissions: 4,
|
||||
MaxAdoptedCpuBytes: 1_000_000,
|
||||
MaxEntityOperations: 1_000,
|
||||
MaxGpuUploadBytes: 1_000_000,
|
||||
MaxGlRetireOperations: 1_000,
|
||||
DestinationReserveFraction: 0.75f))
|
||||
{ MaxCompletionsPerFrame = 4, PriorityLandblockId = priority };
|
||||
|
||||
ctrl.Tick(169, 180);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue