Files
RobustToolbox/Robust.Server/GameStates/PvsSystem.Dirty.cs
Leon Friedrich 64b5d6e323 Pvs cleanup & expose methods for benchmarking (#4779)
* Pvs cleanup & expose methods for benchmarking

* Fix tests

* Minimalist PvsData
2023-12-30 13:23:29 +11:00

90 lines
3.1 KiB
C#

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Prometheus;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Robust.Server.GameStates
{
/// <summary>
/// Caching for dirty bodies
/// </summary>
internal sealed partial class PvsSystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
/// <summary>
/// if it's a new entity we need to GetEntityState from tick 0.
/// </summary>
private HashSet<EntityUid>[] _addEntities = new HashSet<EntityUid>[DirtyBufferSize];
private HashSet<EntityUid>[] _dirtyEntities = new HashSet<EntityUid>[DirtyBufferSize];
private int _currentIndex = 1;
private void InitializeDirty()
{
for (var i = 0; i < DirtyBufferSize; i++)
{
_addEntities[i] = new HashSet<EntityUid>(32);
_dirtyEntities[i] = new HashSet<EntityUid>(32);
}
EntityManager.EntityAdded += OnEntityAdd;
EntityManager.EntityDirtied += OnEntityDirty;
}
private void ShutdownDirty()
{
EntityManager.EntityAdded -= OnEntityAdd;
EntityManager.EntityDirtied -= OnEntityDirty;
}
private void OnEntityAdd(EntityUid e)
{
DebugTools.Assert(_currentIndex == _gameTiming.CurTick.Value % DirtyBufferSize ||
_gameTiming.GetType().Name == "IGameTimingProxy");// Look I have NFI how best to excuse this assert if the game timing isn't real (a Mock<IGameTiming>).
_addEntities[_currentIndex].Add(e);
}
private void OnEntityDirty(EntityUid uid)
{
if (!_addEntities[_currentIndex].Contains(uid))
_dirtyEntities[_currentIndex].Add(uid);
}
private bool TryGetDirtyEntities(GameTick tick, [NotNullWhen(true)] out HashSet<EntityUid>? addEntities, [NotNullWhen(true)] out HashSet<EntityUid>? dirtyEntities)
{
var currentTick = _gameTiming.CurTick;
if (currentTick.Value - tick.Value >= DirtyBufferSize)
{
addEntities = null;
dirtyEntities = null;
return false;
}
var index = tick.Value % DirtyBufferSize;
addEntities = _addEntities[index];
dirtyEntities = _dirtyEntities[index];
return true;
}
private void CleanupDirty(ICommonSession[] sessions)
{
using var _ = Histogram.WithLabels("Clean Dirty").NewTimer();
if (!CullingEnabled)
{
_seenAllEnts.Clear();
foreach (var player in sessions)
{
_seenAllEnts.Add(player);
}
}
_currentIndex = ((int)_gameTiming.CurTick.Value + 1) % DirtyBufferSize;
_addEntities[_currentIndex].Clear();
_dirtyEntities[_currentIndex].Clear();
}
}
}