]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Reduce ChunkingSystem allocations (#21795)
authorLeon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Wed, 29 Nov 2023 01:02:24 +0000 (20:02 -0500)
committerGitHub <noreply@github.com>
Wed, 29 Nov 2023 01:02:24 +0000 (12:02 +1100)
Content.Server/Chunking/ChunkingSystem.cs
Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs

index 6f44c43be85a8ecd0dc49bc0148dd474f34b9658..3919361af13da31ffdcdc3ed2b7a1ed4bd99696e 100644 (file)
@@ -38,7 +38,10 @@ public sealed class ChunkingSystem : EntitySystem
         _configurationManager.UnsubValueChanged(CVars.NetMaxUpdateRange, OnPvsRangeChanged);
     }
 
-    private void OnPvsRangeChanged(float value) => _baseViewBounds = Box2.UnitCentered.Scale(value);
+    private void OnPvsRangeChanged(float value)
+    {
+        _baseViewBounds = Box2.UnitCentered.Scale(value);
+    }
 
     public Dictionary<NetEntity, HashSet<Vector2i>> GetChunksForSession(
         ICommonSession session,
@@ -47,70 +50,84 @@ public sealed class ChunkingSystem : EntitySystem
         ObjectPool<Dictionary<NetEntity, HashSet<Vector2i>>> viewerPool,
         float? viewEnlargement = null)
     {
-        var viewers = GetSessionViewers(session);
-        var chunks = GetChunksForViewers(viewers, chunkSize, indexPool, viewerPool, viewEnlargement ?? chunkSize);
-        return chunks;
-    }
-
-    private HashSet<EntityUid> GetSessionViewers(ICommonSession session)
-    {
-        var viewers = new HashSet<EntityUid>();
-        if (session.Status != SessionStatus.InGame || session.AttachedEntity is null)
-            return viewers;
+        var chunks = viewerPool.Get();
+        DebugTools.Assert(chunks.Count == 0);
 
-        viewers.Add(session.AttachedEntity.Value);
+        if (session.Status != SessionStatus.InGame || session.AttachedEntity is not {} player)
+            return chunks;
 
+        var enlargement = viewEnlargement ?? chunkSize;
+        AddViewerChunks(player, chunks, indexPool, chunkSize, enlargement);
         foreach (var uid in session.ViewSubscriptions)
         {
-            viewers.Add(uid);
+            AddViewerChunks(uid, chunks, indexPool, chunkSize, enlargement);
         }
 
-        return viewers;
+        return chunks;
     }
 
-    private Dictionary<NetEntity, HashSet<Vector2i>> GetChunksForViewers(
-        HashSet<EntityUid> viewers,
-        int chunkSize,
+    private void AddViewerChunks(EntityUid viewer,
+        Dictionary<NetEntity, HashSet<Vector2i>> chunks,
         ObjectPool<HashSet<Vector2i>> indexPool,
-        ObjectPool<Dictionary<NetEntity, HashSet<Vector2i>>> viewerPool,
+        int chunkSize,
         float viewEnlargement)
     {
-        var chunks = viewerPool.Get();
-        DebugTools.Assert(chunks.Count == 0);
+        if (!_xformQuery.TryGetComponent(viewer, out var xform))
+            return;
 
-        foreach (var viewerUid in viewers)
+        var pos = _transform.GetWorldPosition(xform);
+        var bounds = _baseViewBounds.Translated(pos).Enlarged(viewEnlargement);
+
+        var state = new QueryState(chunks, indexPool, chunkSize, bounds, _transform, EntityManager);
+        _mapManager.FindGridsIntersecting(xform.MapID, bounds, ref state, AddGridChunks, true);
+    }
+
+    private static bool AddGridChunks(
+        EntityUid uid,
+        MapGridComponent grid,
+        ref QueryState state)
+    {
+        var netGrid = state.EntityManager.GetNetEntity(uid);
+        if (!state.Chunks.TryGetValue(netGrid, out var set))
         {
-            if (!_xformQuery.TryGetComponent(viewerUid, out var xform))
-            {
-                Log.Error($"Player has deleted viewer entities? Viewers: {string.Join(", ", viewers.Select(ToPrettyString))}");
-                continue;
-            }
-
-            var pos = _transform.GetWorldPosition(xform);
-            var bounds = _baseViewBounds.Translated(pos).Enlarged(viewEnlargement);
-            var grids = new List<Entity<MapGridComponent>>();
-            _mapManager.FindGridsIntersecting(xform.MapID, bounds, ref grids, true);
-
-            foreach (var grid in grids)
-            {
-                var netGrid = GetNetEntity(grid);
-
-                if (!chunks.TryGetValue(netGrid, out var set))
-                {
-                    chunks[netGrid] = set = indexPool.Get();
-                    DebugTools.Assert(set.Count == 0);
-                }
-
-                var enumerator = new ChunkIndicesEnumerator(_transform.GetInvWorldMatrix(grid).TransformBox(bounds), chunkSize);
-
-                while (enumerator.MoveNext(out var indices))
-                {
-                    set.Add(indices.Value);
-                }
-            }
+            state.Chunks[netGrid] = set = state.Pool.Get();
+            DebugTools.Assert(set.Count == 0);
         }
 
-        return chunks;
+        var aabb = state.Transform.GetInvWorldMatrix(uid).TransformBox(state.Bounds);
+        var enumerator = new ChunkIndicesEnumerator(aabb, state.ChunkSize);
+        while (enumerator.MoveNext(out var indices))
+        {
+            set.Add(indices.Value);
+        }
+
+        return true;
+    }
+
+    private readonly struct QueryState
+    {
+        public readonly Dictionary<NetEntity, HashSet<Vector2i>> Chunks;
+        public readonly ObjectPool<HashSet<Vector2i>> Pool;
+        public readonly int ChunkSize;
+        public readonly Box2 Bounds;
+        public readonly SharedTransformSystem Transform;
+        public readonly EntityManager EntityManager;
+
+        public QueryState(
+            Dictionary<NetEntity, HashSet<Vector2i>> chunks,
+            ObjectPool<HashSet<Vector2i>> pool,
+            int chunkSize,
+            Box2 bounds,
+            SharedTransformSystem transform,
+            EntityManager entityManager)
+        {
+            Chunks = chunks;
+            Pool = pool;
+            ChunkSize = chunkSize;
+            Bounds = bounds;
+            Transform = transform;
+            EntityManager = entityManager;
+        }
     }
 }
 
index 617bc5527628ea375cdc54562f0c97d7382c090b..1941ff9d163fb671dc585d17c2245fccf086798a 100644 (file)
@@ -273,7 +273,7 @@ public sealed partial class ExplosionSystem
         return !tileBlocked;
     }
 
-    private bool GridQueryCallback(
+    private static bool GridQueryCallback(
         ref (List<(EntityUid, TransformComponent)> List, HashSet<EntityUid> Processed, EntityQuery<TransformComponent> XformQuery) state,
         in EntityUid uid)
     {
@@ -283,7 +283,7 @@ public sealed partial class ExplosionSystem
         return true;
     }
 
-    private bool GridQueryCallback(
+    private static bool GridQueryCallback(
         ref (List<(EntityUid, TransformComponent)> List, HashSet<EntityUid> Processed, EntityQuery<TransformComponent> XformQuery) state,
         in FixtureProxy proxy)
     {
@@ -307,7 +307,7 @@ public sealed partial class ExplosionSystem
         var gridBox = Box2.FromDimensions(tile * DefaultTileSize, new Vector2(DefaultTileSize, DefaultTileSize));
         var worldBox = spaceMatrix.TransformBox(gridBox);
         var list = new List<(EntityUid, TransformComponent)>();
-        var state = (list, processed, invSpaceMatrix, lookup.Owner, _transformQuery, gridBox);
+        var state = (list, processed, invSpaceMatrix, lookup.Owner, _transformQuery, gridBox, _transformSystem);
 
         // get entities:
         lookup.DynamicTree.QueryAabb(ref state, SpaceQueryCallback, worldBox, true);
@@ -336,8 +336,8 @@ public sealed partial class ExplosionSystem
         }
     }
 
-    private bool SpaceQueryCallback(
-        ref (List<(EntityUid, TransformComponent)> List, HashSet<EntityUid> Processed, Matrix3 InvSpaceMatrix, EntityUid LookupOwner, EntityQuery<TransformComponent> XformQuery, Box2 GridBox) state,
+    private static bool SpaceQueryCallback(
+        ref (List<(EntityUid, TransformComponent)> List, HashSet<EntityUid> Processed, Matrix3 InvSpaceMatrix, EntityUid LookupOwner, EntityQuery<TransformComponent> XformQuery, Box2 GridBox, SharedTransformSystem System) state,
         in EntityUid uid)
     {
         if (state.Processed.Contains(uid))
@@ -355,14 +355,15 @@ public sealed partial class ExplosionSystem
         }
 
         // finally check if it intersects our tile
-        if (state.GridBox.Contains(state.InvSpaceMatrix.Transform(_transformSystem.GetWorldPosition(xform, state.XformQuery))))
+        var wpos = state.System.GetWorldPosition(xform);
+        if (state.GridBox.Contains(state.InvSpaceMatrix.Transform(wpos)))
             state.List.Add((uid, xform));
 
         return true;
     }
 
-    private bool SpaceQueryCallback(
-        ref (List<(EntityUid, TransformComponent)> List, HashSet<EntityUid> Processed, Matrix3 InvSpaceMatrix, EntityUid LookupOwner, EntityQuery<TransformComponent> XformQuery, Box2 GridBox) state,
+    private static bool SpaceQueryCallback(
+        ref (List<(EntityUid, TransformComponent)> List, HashSet<EntityUid> Processed, Matrix3 InvSpaceMatrix, EntityUid LookupOwner, EntityQuery<TransformComponent> XformQuery, Box2 GridBox, SharedTransformSystem System) state,
         in FixtureProxy proxy)
     {
         var uid = proxy.Entity;