-
Notifications
You must be signed in to change notification settings - Fork 382
performance: reduce LINQ allocations in UpdateInstanceControllers #2811
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,28 +5,44 @@ | |
| using Microsoft.Extensions.Logging; | ||
|
|
||
| namespace Intersect.Server.Core.MapInstancing; | ||
|
|
||
| public static class InstanceProcessor | ||
| { | ||
| private static Dictionary<Guid, InstanceController> InstanceControllers = new(); | ||
| private static readonly Dictionary<Guid, InstanceController> InstanceControllers = new(); | ||
|
|
||
| public static Guid[] CurrentControllers => InstanceControllers.Keys.ToArray(); | ||
| private static readonly HashSet<Guid> 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<Guid> 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<Guid>? toRemove = null; | ||
| foreach (var id in InstanceControllers.Keys) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not race condition safe? |
||
| { | ||
| if (id == default) | ||
| { | ||
| continue; // never clean overworld | ||
| } | ||
|
|
||
| if (!ActiveIdScratch.Contains(id)) | ||
| { | ||
| (toRemove ??= new List<Guid>()).Add(id); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer |
||
| } | ||
| } | ||
|
|
||
| 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}"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't remember anymore what the correct code is but |
||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -48,14 +64,21 @@ public static void UpdateInstanceControllers(MapInstance[] activeMaps) | |
| return; | ||
| } | ||
|
|
||
| // Cleanup inactive instances | ||
| CleanupOrphanedControllers(activeMaps.Select(map => map.MapInstanceId)); | ||
| CleanupOrphanedControllers(activeMaps); | ||
|
|
||
| Dictionary<Guid, MapInstance[]> mapsAndInstances = activeMaps | ||
| .GroupBy(m => m.MapInstanceId) | ||
| .ToDictionary(m => m.Key, m => m.ToArray()); | ||
| // Manual grouping + ToDictionary allocations | ||
| var mapsAndInstances = new Dictionary<Guid, List<MapInstance>>(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer |
||
| 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<MapInstance>(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer |
||
| } | ||
|
|
||
| list.Add(map); | ||
| } | ||
|
|
||
| // For each instance... | ||
| foreach (var (instanceId, mapsInInstance) in mapsAndInstances) | ||
| { | ||
| // Fetch our instance controller... | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
Clear()would most likely end up destroying the backing buffer, I'm not sure there's a point in a static variable for this.