diff --git a/Intersect.Server.Core/Core/MapInstancing/InstanceProcessor.cs b/Intersect.Server.Core/Core/MapInstancing/InstanceProcessor.cs index d1f9060e34..1d2c48bfdb 100644 --- a/Intersect.Server.Core/Core/MapInstancing/InstanceProcessor.cs +++ b/Intersect.Server.Core/Core/MapInstancing/InstanceProcessor.cs @@ -5,28 +5,44 @@ using Microsoft.Extensions.Logging; namespace Intersect.Server.Core.MapInstancing; + public static class InstanceProcessor { - private static Dictionary InstanceControllers = new(); + private static readonly Dictionary InstanceControllers = new(); - public static Guid[] CurrentControllers => InstanceControllers.Keys.ToArray(); + private static readonly HashSet ActiveIdScratch = []; - public static bool TryGetInstanceController(Guid instanceId, out InstanceController controller) - { - return InstanceControllers.TryGetValue(instanceId, out controller); - } + public static bool TryGetInstanceController(Guid instanceId, out InstanceController controller) => InstanceControllers.TryGetValue(instanceId, out controller); - private static void CleanupOrphanedControllers(IEnumerable activeInstanceIds) + private static void CleanupOrphanedControllers(MapInstance[] activeMaps) { - var processingInstances = InstanceControllers.Keys - .Except(activeInstanceIds) - .Except(new Guid[1] { default }) // Never cleanup the overworld instance - .ToArray(); + ActiveIdScratch.Clear(); + for (var i = 0; i < activeMaps.Length; i++) + { + ActiveIdScratch.Add(activeMaps[i].MapInstanceId); + } + + List? toRemove = null; + foreach (var id in InstanceControllers.Keys) + { + if (id == default) + { + continue; // never clean overworld + } + + if (!ActiveIdScratch.Contains(id)) + { + (toRemove ??= new List()).Add(id); + } + } - foreach (var id in processingInstances) + if (toRemove != null) { - InstanceControllers.Remove(id); - ApplicationContext.Context.Value?.Logger.LogDebug($"Removing instance controller {id}"); + foreach (var id in toRemove) + { + InstanceControllers.Remove(id); + ApplicationContext.Context.Value?.Logger.LogDebug($"Removing instance controller {id}"); + } } } @@ -48,14 +64,21 @@ public static void UpdateInstanceControllers(MapInstance[] activeMaps) return; } - // Cleanup inactive instances - CleanupOrphanedControllers(activeMaps.Select(map => map.MapInstanceId)); + CleanupOrphanedControllers(activeMaps); - Dictionary mapsAndInstances = activeMaps - .GroupBy(m => m.MapInstanceId) - .ToDictionary(m => m.Key, m => m.ToArray()); + // Manual grouping + ToDictionary allocations + var mapsAndInstances = new Dictionary>(); + for (var i = 0; i < activeMaps.Length; i++) + { + var map = activeMaps[i]; + if (!mapsAndInstances.TryGetValue(map.MapInstanceId, out var list)) + { + mapsAndInstances[map.MapInstanceId] = list = new List(); + } + + list.Add(map); + } - // For each instance... foreach (var (instanceId, mapsInInstance) in mapsAndInstances) { // Fetch our instance controller...