wip(assembler): round S7 -- workers kept busy: in-game cold full view 17.5 s -> 7.8 s
Two admission blockers found by per-frame decline codes: the near reserve held four slots idle after LOD0 was done (coarse capped at 6), and finished-but- unapplied results counted against the task cap. Admission now counts queued + running tasks; near reserve releases once the walkable ring is ready while stationary (voxel.StreamingDynamicNearReserve, default on). Walkable ring 0.65 -> 0.58 s, full LOD0 2.28 -> 1.44 s, busy workers 2.2 -> 5.6 of 10. Old behaviour behind voxel.StreamingLegacyPendingResultCap. RMC source reviewed (read-only): batching/fast-cook ranked, not yet worth it on measured apply cost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
b9c13c37c0
commit
5eb9ee76ff
7 files changed
+726
-53
No files matched your search
+60
-8
@@ -578,7 +578,12 @@ driven by `EditorBrush*` props.
|
||||
the result through the normal MPSC queue; the game thread reads the token again before applying.
|
||||
`FChunkResult::Epoch` still guards the generation epoch. Desired work is sorted from the true pawn
|
||||
position, with the occupied/support LOD0 tile and the next tile along the heading in an absolute
|
||||
high-priority prefix. Stationary player ≈ free. (Old per-frame O(loaded×desired) scan = 22ms.)
|
||||
high-priority prefix. Admission counts queued/running `ActiveTaskCount`; `PendingTiles` stays until
|
||||
game-thread apply for duplicate suppression and result bookkeeping, but completed MPSC results do
|
||||
not occupy a worker slot. `voxel.StreamingLegacyPendingResultCap=1` restores the old result-inclusive
|
||||
admission count. `voxel.StreamingDynamicNearReserve=1` holds the authored near reserve while moving
|
||||
or before the walkable gate, then releases it to coarse work after the stationary ring is ready.
|
||||
Stationary player ≈ free. (Old per-frame O(loaded×desired) scan = 22ms.)
|
||||
- **LOD** changes HOT-SWAP (`LoadTile` only, never unload-first) → no holes. LOD
|
||||
reconciliation lives in the PERSISTENT per-frame submit loop (same loop as new-chunk loads),
|
||||
NOT as a one-shot on the boundary-cross frame — a one-shot drops every chunk past the task
|
||||
@@ -1454,8 +1459,10 @@ opt-in because it did not beat the legacy order on the gates and the viewer coul
|
||||
presentation: set `voxel.StreamingCoarseFirst=1` to admit coarse desired levels from the maximum LOD
|
||||
down to `max(2, FullResClipLevels)`, favoring tiles ahead of travel and then nearer tiles within each
|
||||
LOD; LOD0/1 refinement follows. Default `0` preserves the S4 LOD0-to-LOD8 order.
|
||||
`voxel.StreamingDynamicNearReserve=1` opts into keeping the authored near-task reserve while the pawn
|
||||
moves or until the stationary walkable ring is ready; default `0` preserves the previous task budget.
|
||||
`voxel.StreamingDynamicNearReserve=1` keeps the authored near-task reserve while the pawn moves or
|
||||
until the stationary walkable ring is ready; this is now the default. Set it to `0` only for the
|
||||
legacy-admission negative control. After the stationary nine-tile ring is ready, coarse work can use
|
||||
the formerly reserved slots.
|
||||
The standalone queue defaults to legacy order; `--coarse-first-stream-order` opts into the S5 tiers
|
||||
and `--legacy-stream-order` explicitly selects the legacy order.
|
||||
|
||||
@@ -1498,12 +1505,10 @@ with a 30 second ceiling; at `0`, the authored budget is unchanged. On the match
|
||||
the boost changed full-set readiness from 17.412 s to 17.346 s and removed count-cap frames, but did
|
||||
not improve end-to-end residency. Keep the normal 4 / 2 ms guard for play.
|
||||
|
||||
The trace found the shared worker pool was not saturated: the 10-slot idle estimate was about 132
|
||||
The S6 trace found the shared pool was not saturated: its 10-slot idle estimate was about 132
|
||||
slot-seconds on legacy order and 73 on gated coarse-first, while game-thread tile applies totaled only
|
||||
about 0.24 seconds during cold residency. Results waited in the result queue, and some frames reached
|
||||
the four-mesh cap, but expanding the apply budget alone did not move the wall clock. The remaining
|
||||
floor is worker-side work supply/admission; this trace does not isolate why available worker slots
|
||||
stay idle. The 1.57 s target remains unmet; the headless trace is not a render-time measurement.
|
||||
about 0.24 seconds. S7's frame-level admission and cumulative worker-task accounting revisited that
|
||||
open question; see §8.28.
|
||||
|
||||
The report records per-LOD worker, queue, result-queue and apply totals, collision latency, frame
|
||||
percentiles, hashes, regressions and the command lines. The standalone 60 m/s viewer now counts
|
||||
@@ -1513,6 +1518,53 @@ W1/W8/W16 world and LOD hashes are unchanged, as are `Epoch`, cancellation, `Mod
|
||||
shutdown-drain and game-thread UObject-creation rules. See
|
||||
[`Standalone/Research/WorldAssemblerM3/Round10/REPORT.md`](Standalone/Research/WorldAssemblerM3/Round10/REPORT.md).
|
||||
|
||||
### 8.28 Shared admission accounting and worker supply — World Assembler S7 / M3 Round 11
|
||||
|
||||
`PendingTiles` is a game-thread result-bookkeeping set: its entry lasts from task submission until
|
||||
`ApplyTileResult`, so it can include work that has finished and is waiting in one of the MPSC result
|
||||
queues. It is not the count of active generation tasks. The S6 admission path used
|
||||
`PendingTiles.Num()` for that cap. On the S7 old-path control, after LOD0 had no missing keys, 877
|
||||
admission frames still had LOD1+ work missing and hit the four-slot near reserve; at a representative
|
||||
frame, occupancy was 6/10 while only four tasks were queued/running and two completed results were
|
||||
waiting to apply. 806 of those 877 frames had a positive completed-result estimate.
|
||||
|
||||
Admission now uses `ActiveTaskCount`, which is incremented before launching the UE task and released
|
||||
by its RAII guard when the worker lambda exits. This still counts queued and running work, but completed
|
||||
results do not consume an admission slot. `voxel.StreamingLegacyPendingResultCap=1` restores the old
|
||||
`PendingTiles` accounting; the test harness's `NearReserveMode=Legacy` also sets
|
||||
`voxel.StreamingDynamicNearReserve=0`, reproducing the S6 path. `StreamingDynamicNearReserve` now
|
||||
defaults to `1`; `StreamingCoarseFirst` remains `0`, and the apply boost remains `0` in the matched
|
||||
measurement.
|
||||
|
||||
On the 2,578-key owner SurfaceWorld trace, the old-path control reached the full set in 17.527 s,
|
||||
walkable ring in 0.650 s, and full LOD0 in 2.281 s. Dynamic admission reached them in 7.780 s,
|
||||
0.581 s, and 1.439 s. Its first-request-to-ready interval was 7.342 s with 41.364 worker-seconds,
|
||||
or 5.63 integrated busy-worker equivalents. Using the S6 10-slot idle formula on that same interval
|
||||
gives 32.06 slot-seconds, versus 133.01 on the S7 old-path control and 132.1 in S6. The ten S7
|
||||
spawn samples that ended with free admission capacity and missing keys all recorded a submission
|
||||
stop at the 10-task cap (one worker could finish before the end-of-pass sample); the frame trace
|
||||
found no near-reserve decline, all-loaded latch, walkable gate failure, or inner `LoadTile` rejection
|
||||
in those passes. Result-aware admission therefore removes the measured cold-set blocker and
|
||||
reproduces the legacy control within 0.7%, but the 7.78 s full-set result still misses the rough
|
||||
4.14 s `worker-seconds / 10 slots` estimate. Across the full 45 s trace, free-capacity frames with
|
||||
missing keys were classified by LOD as near reserve or full cap; none was unclassified.
|
||||
|
||||
The per-frame `running_workers` value is biased high when sampled only at admission/apply boundaries;
|
||||
S7 added cumulative task intervals and found 5.63 busy-worker equivalents over the first-request-to-
|
||||
ready span, with eight sustained overlaps in the reconstructed intervals; a zero-duration endpoint
|
||||
tie briefly counts nine. This locates
|
||||
the remaining gap downstream of an admission refusal, but does not distinguish UE task-pool dispatch
|
||||
from work internal to a tile. Measured worker task time rose 9.7% versus the negative control
|
||||
(16.04 ms versus 14.62 ms per initial tile); hashes match and the trace records elapsed task time,
|
||||
not CPU cycles. During the later +Y move, the loader's `bCoreRegionCompilePending` guard also
|
||||
blocked 10 legacy and 11 dynamic submission passes despite free tasks; each inner-decline record
|
||||
had that flag set. The tick trace reports aggregate `TestWorld->Tick()` only: spawn p95/max was
|
||||
2.262/5.230 ms and walk p95/max was 2.512/28.893 ms; no subsystem marker names the walk
|
||||
maximum. The nine-tile ring and full LOD0 are faster than S6. Tile output hashes did not change, so
|
||||
the recipe version remains unchanged. Null-RHI runs do not prove player-visible enclosure. See
|
||||
[`Standalone/Research/WorldAssemblerM3/Round11/REPORT.md`](Standalone/Research/WorldAssemblerM3/Round11/REPORT.md)
|
||||
for the audit counts, RMC review, quality matrix, commands and binary hashes.
|
||||
|
||||
## 9. Multiplayer model (listen-server first, dedicated-friendly)
|
||||
|
||||
> **Status: transport is DESIGN ONLY — nothing is networked in-tree yet** (no `Replicated`/`HasAuthority`/RPCs; a
|
||||
|
||||
Reference in new issue
Block a user