From 83adef923d70d726cb0b96a8326c4829db967149 Mon Sep 17 00:00:00 2001 From: biwa <6475593+biwa@users.noreply.github.com> Date: Sat, 17 Apr 2021 20:06:58 +0200 Subject: [PATCH] Increased performance on multi-core CPUs when selecting sectors in Sectors Mode when Synchronize Thing Editing is enabled --- .../BuilderModes/ClassicModes/SectorsMode.cs | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs index ae42fd44d..2a38520b5 100755 --- a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs @@ -19,7 +19,10 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Diagnostics; +using System.Threading.Tasks; using System.Windows.Forms; +using System.Collections.Concurrent; using CodeImp.DoomBuilder.Actions; using CodeImp.DoomBuilder.BuilderModes.Interface; using CodeImp.DoomBuilder.Config; @@ -79,6 +82,8 @@ namespace CodeImp.DoomBuilder.BuilderModes // Stores sizes of the text for text labels so that they only have to be computed once private Dictionary<string, float> textlabelsizecache; + private HashSet<Thing> determinedsectorthings; + #endregion #region ================== Properties @@ -585,20 +590,36 @@ namespace CodeImp.DoomBuilder.BuilderModes if(General.Interface.AltState ^ BuilderPlug.Me.SyncronizeThingEdit) { List<BlockEntry> belist = blockmap.GetSquareRange(s.BBox); + HashSet<Thing> detthings = new HashSet<Thing>(); // Things that still need their sector to be determined + ConcurrentBag<Thing> selthings = new ConcurrentBag<Thing>(); // Things that have to have their selection status changed - foreach(BlockEntry be in belist) + foreach (BlockEntry be in belist) { foreach(Thing t in be.Things) { - // Always determine the thing's current sector because it might have change since the last determination - t.DetermineSector(blockmap); - - if (t.Sector == s && t.Selected != s.Selected) t.Selected = s.Selected; + // If the thing isn't cached we need to add it to the list of things that need their sector to be determined, + // otherwise (if they are cached) add them to the list of things that have to have their selection status changed + if (!determinedsectorthings.Contains(t)) + detthings.Add(t); + else if (t.Sector == s && t.Selected != s.Selected) + selthings.Add(t); } } + + // Determine sectors of things in parallel. If there's a match add the thing to the list of things that have to have their selection status changed + Parallel.ForEach(detthings, t => { + t.DetermineSector(blockmap); + determinedsectorthings.Add(t); // Add to cache + if (t.Sector == s && t.Selected != s.Selected) selthings.Add(t); + }); + + // Finally change the selection status. This has be done here (and not in parallel), since changing the Selected property + // runs some methods that are not threadsafe + foreach (Thing t in selthings) + t.Selected = s.Selected; } - if(update) + if (update) { UpdateOverlay(); renderer.Present(); @@ -843,6 +864,8 @@ namespace CodeImp.DoomBuilder.BuilderModes } } + determinedsectorthings = new HashSet<Thing>(); + // Make text labels for sectors SetupLabels(); @@ -851,7 +874,7 @@ namespace CodeImp.DoomBuilder.BuilderModes UpdateOverlaySurfaces();//mxd UpdateSelectionInfo(); //mxd } - + // Mode disengages public override void OnDisengage() { @@ -904,7 +927,7 @@ namespace CodeImp.DoomBuilder.BuilderModes General.Interface.HideInfo(); General.Interface.Display.HideToolTip(); //mxd } - + // This redraws the display public override void OnRedrawDisplay() { @@ -1499,6 +1522,9 @@ namespace CodeImp.DoomBuilder.BuilderModes // Recreate the blockmap to not include the potentially un-done sectors and things anymore CreateBlockmap(); + // Clear the cache of things that already got their sector determined + determinedsectorthings = new HashSet<Thing>(); + // If something is highlighted make sure to update the association so that it contains valid data if (highlighted != null && !highlighted.IsDisposed) highlightasso.Set(highlighted); @@ -1525,6 +1551,9 @@ namespace CodeImp.DoomBuilder.BuilderModes // Recreate the blockmap to include the potentially re-done sectors and things again CreateBlockmap(); + // Clear the cache of things that already got their sector determined + determinedsectorthings = new HashSet<Thing>(); + // If something is highlighted make sure to update the association so that it contains valid data if (highlighted != null && !highlighted.IsDisposed) highlightasso.Set(highlighted); -- GitLab