perf(streaming): quiesce retired generations and budget teardown
Publish the retail blocking-for-cells edge before deferred recenter work, freeze old-world presentation/simulation/audio, and advance full-window retirement from exact metered entity and owner cursors. This removes synchronous portal teardown without allowing retained owners to remain observable.
This commit is contained in:
parent
b8f6317fe1
commit
bb16f74fd4
38 changed files with 1691 additions and 170 deletions
|
|
@ -38,6 +38,25 @@ public sealed class RecallTeleportAnimationTests
|
|||
Assert.Equal(["objects", "network", "commands", "spatial"], calls);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LiveFrame_WhileCellsAreBlocked_DrainsNetworkAndCommandsWithoutWorldTicks()
|
||||
{
|
||||
var calls = new List<string>();
|
||||
var availability = new WorldGenerationAvailabilityState();
|
||||
availability.Begin(1);
|
||||
var frame = new RetailLiveFrameCoordinator(
|
||||
new TestLiveObjectFramePhase(_ => calls.Add("objects")),
|
||||
new GpuWorldState(availability: availability),
|
||||
new TestLiveSessionFramePhase(() => calls.Add("network")),
|
||||
new TestPostNetworkCommandFramePhase(() => calls.Add("commands")),
|
||||
new TestLiveSpatialReconcilePhase(() => calls.Add("spatial")),
|
||||
availability);
|
||||
|
||||
frame.Tick(1f / 60f);
|
||||
|
||||
Assert.Equal(["network", "commands"], calls);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LiveFrame_InvalidHostDeltaCannotBlockNetworkDispatch()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Reflection;
|
||||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Streaming;
|
||||
using AcDream.App.Update;
|
||||
using AcDream.App.World;
|
||||
|
||||
|
|
@ -129,6 +130,33 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
observed.Camera.Select(value => value.SimulationDeltaSeconds));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void QuiescedWorld_FreezesScriptClockAndLivenessWhilePortalPhasesContinue()
|
||||
{
|
||||
var calls = new List<string>();
|
||||
var observed = new FrameObservations();
|
||||
var availability = new WorldGenerationAvailabilityState();
|
||||
availability.Begin(7);
|
||||
UpdateFrameOrchestrator frame = Create(
|
||||
calls,
|
||||
observed: observed,
|
||||
availability: availability);
|
||||
|
||||
frame.Tick(new UpdateFrameInput(0.25));
|
||||
frame.Tick(new UpdateFrameInput(0.25));
|
||||
availability.End(7);
|
||||
frame.Tick(new UpdateFrameInput(0.25));
|
||||
|
||||
Assert.Equal([0.0, 0.0, 0.25], observed.PublishedTimes);
|
||||
Assert.Equal(1, calls.Count(call => call == "liveness"));
|
||||
Assert.Equal(3, calls.Count(call => call == "streaming"));
|
||||
Assert.Equal(3, calls.Count(call => call == "network"));
|
||||
Assert.Equal(3, calls.Count(call => call == "teleport"));
|
||||
Assert.Equal(3, calls.Count(call => call == "camera"));
|
||||
Assert.Equal([0.25f, 0.25f, 0.25f], observed.LiveDeltas);
|
||||
Assert.Equal([0.25f, 0.25f, 0.25f], observed.TeleportDeltas);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clock_RejectsFiniteDeltaAboveTheSinglePrecisionConsumerRange()
|
||||
{
|
||||
|
|
@ -200,6 +228,7 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
typeof(ILocalPlayerTeleportFramePhase),
|
||||
typeof(IPlayerModeAutoEntryFramePhase),
|
||||
typeof(ICameraFramePhase),
|
||||
typeof(IWorldGenerationAvailability),
|
||||
];
|
||||
|
||||
FieldInfo[] fields = typeof(UpdateFrameOrchestrator).GetFields(
|
||||
|
|
@ -534,7 +563,8 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
"new LiveEntityLivenessFramePhase(",
|
||||
"session.LocalTeleport,",
|
||||
"new PlayerModeAutoEntryFramePhase(",
|
||||
"cameraFrame);");
|
||||
"cameraFrame,",
|
||||
"live.WorldAvailability);");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -860,7 +890,8 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
RecordingFailureSink? failureSink = null,
|
||||
FrameObservations? observed = null,
|
||||
bool teleportPlace = false,
|
||||
bool inboundCreatedPlayer = false)
|
||||
bool inboundCreatedPlayer = false,
|
||||
IWorldGenerationAvailability? availability = null)
|
||||
{
|
||||
teardown ??= new RecordingTeardown(calls);
|
||||
failureSink ??= new RecordingFailureSink();
|
||||
|
|
@ -875,7 +906,8 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
new RecordingLiveness(calls),
|
||||
new RecordingTeleport(calls, observed, teleportPlace),
|
||||
new RecordingAutoEntry(calls),
|
||||
new RecordingCamera(calls, observed, inboundCreatedPlayer));
|
||||
new RecordingCamera(calls, observed, inboundCreatedPlayer),
|
||||
availability);
|
||||
}
|
||||
|
||||
private sealed class RecordingTeardown(List<string> calls)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue