perf(pipeline): MP-Alloc Task 4 - reuse per-frame animatedIds + drawableCells sets
Completes the safe-batch (implementer finished this but died before committing; coordinator independently verified bit-identity + safety post-interruption). Two per-frame HashSet<uint> allocations replaced by reused cleared-in-place fields: - GameWindow._animatedIdsScratch: WalkEntitiesInto treats null and empty identically (line 682 `is null || Count == 0`), so an always-non-null empty set == the old null-when-empty local. Verified. - RetailPViewRenderer._drawableCellsScratch: flows into RetailPViewFrameResult.DrawableCells (live ref) but every consumer reads it same-frame; sigDrawableCells is a per-frame OnRender local that EmitRenderSignatureIfChanged only FORMATS to a string (no reference retention, no _lastSig set field). Built frame N -> read frame N -> cleared frame N+1. No cross-frame corruption. Build green, full suite 4116 passed / 4 skipped. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
76b8b4e9fc
commit
91afea24b4
2 changed files with 26 additions and 8 deletions
|
|
@ -252,6 +252,13 @@ public sealed class GameWindow : IDisposable
|
|||
/// </summary>
|
||||
private readonly Dictionary<uint, AnimatedEntity> _animatedEntities = new();
|
||||
|
||||
// MP-Alloc (2026-07-05): reusable per-frame snapshot of _animatedEntities.Keys.
|
||||
// WbDrawDispatcher.WalkEntitiesInto treats null and an empty set identically
|
||||
// (`animatedEntityIds is null || animatedEntityIds.Count == 0`), so this can
|
||||
// always be a live (possibly empty) HashSet instead of `new`ing one every
|
||||
// frame or passing null.
|
||||
private readonly HashSet<uint> _animatedIdsScratch = new();
|
||||
|
||||
/// <summary>
|
||||
/// Tier 1 cache (#53): per-entity classification results for static
|
||||
/// entities (those NOT in <see cref="_animatedEntities"/>). Conceptually
|
||||
|
|
@ -9104,13 +9111,15 @@ public sealed class GameWindow : IDisposable
|
|||
var envCellViewProj = camera.View * camera.Projection;
|
||||
_envCellFrustum?.Update(envCellViewProj);
|
||||
|
||||
HashSet<uint>? animatedIds = null;
|
||||
if (_animatedEntities.Count > 0)
|
||||
{
|
||||
animatedIds = new HashSet<uint>(_animatedEntities.Count);
|
||||
foreach (var k in _animatedEntities.Keys)
|
||||
animatedIds.Add(k);
|
||||
}
|
||||
// MP-Alloc: reuse _animatedIdsScratch instead of `new`ing a
|
||||
// HashSet<uint> every frame. Downstream consumers (WbDrawDispatcher.
|
||||
// WalkEntitiesInto) treat null and an empty set identically, so an
|
||||
// always-non-null (possibly empty) set is behaviorally the same as
|
||||
// the old null-when-nothing-animated local.
|
||||
_animatedIdsScratch.Clear();
|
||||
foreach (var k in _animatedEntities.Keys)
|
||||
_animatedIdsScratch.Add(k);
|
||||
HashSet<uint>? animatedIds = _animatedIdsScratch;
|
||||
|
||||
// Phase G.1: sky renderer — draws the far-plane-infinity
|
||||
// celestial meshes FIRST so the rest of the scene z-tests
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue