docs #429: root cause — 30-77MB/frame LINQ allocation in streamed-mesh completion on the render thread; fix plan + acceptance protocol
Local commit for the implementation handoff; push withheld per owner direction until the fix session. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
ca4bae776c
commit
5b9d0260bb
1 changed files with 29 additions and 0 deletions
|
|
@ -148,6 +148,35 @@ of running per arm (`artifacts/owner-gate/player-present-429-packON.csv`
|
|||
frames spend their extra time (the pack's CPU stage profiler names
|
||||
stages) and where the player position is sampled relative to it.
|
||||
|
||||
**ROOT CAUSE FOUND 2026-08-23 (frame-history run, 33,350 frames with stage
|
||||
attribution — `ACDREAM_FRAME_PROF=1` + `ACDREAM_FRAME_HISTORY`):** of 708
|
||||
stall frames (>12 ms), 701 allocate 30-77 MB IN THAT SINGLE FRAME (normal
|
||||
frames: ~22 KB, p99 94 KB). The time and the allocation sit on the render
|
||||
path outside the tracked stages. The bursts arrive in ~8-frame clusters
|
||||
during movement — the streaming MESH COMPLETION path: each frame completes
|
||||
up to `MaxCompletionsPerFrame` (quality High = 4) newly streamed meshes on
|
||||
the render thread, and each completion in
|
||||
`ObjectMeshManager.UploadGfxObjMeshData` (~line 2043) runs LINQ chains —
|
||||
`TextureBatches.Values.SelectMany(...).Select(b => b.Indices.ToArray())
|
||||
.ToArray()`, plus the retained pick-support copies
|
||||
`CPUPositions = Vertices.Select(v => v.Position).ToArray()` and
|
||||
`CPUIndices = ...SelectMany(...).SelectMany(...).ToArray()` — megabytes of
|
||||
enumerator/intermediate-List garbage per mesh, tens of MB per frame.
|
||||
Gen0 runs 70-145 collections per 5 s during movement (vs ~1/6 s idle).
|
||||
|
||||
**Fix shape (a bounded slice, not a quickie — this is the production mesh
|
||||
pipeline):**
|
||||
1. De-LINQ the conversion: direct pre-sized loops for the index batches and
|
||||
the CPU pick copies (sizes are known up front from the batch counts).
|
||||
2. Consider byte-budgeted completions (4 huge EnvCell meshes is not the
|
||||
same frame cost as 4 fence posts) and/or moving the CPU-side conversion
|
||||
onto the existing mesh-preparation scheduler thread so the render thread
|
||||
only adopts finished arrays.
|
||||
3. Allocation-gate test in the I1 style: a completion of a representative
|
||||
mesh set must allocate near its retained-copy size, not multiples of it.
|
||||
The pack-ON player-jump phase question remains as the second defect but
|
||||
becomes mostly moot once the stalls themselves shrink.
|
||||
|
||||
**Next probes (in order):**
|
||||
1. `ACDREAM_DUMP_MOTION=1` + a temporary inbound-position log for the
|
||||
LOCAL guid: does ACE send position sets for the local player every
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue