From 8d2fc24fbeed2bf2078e99ab9dce2e008013c887 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sat, 12 Dec 2015 00:47:58 +0000 Subject: [PATCH] Speed up SpatiallyPartitioned.InBox for searches in a single partition bin. If a search in a spatial partition is taking place entirely within a single bin, the cost of tracking possible duplicate items with a set can be avoided for a small speedup. --- OpenRA.Game/Primitives/SpatiallyPartitioned.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/OpenRA.Game/Primitives/SpatiallyPartitioned.cs b/OpenRA.Game/Primitives/SpatiallyPartitioned.cs index 728c711ec4..6bc9833300 100644 --- a/OpenRA.Game/Primitives/SpatiallyPartitioned.cs +++ b/OpenRA.Game/Primitives/SpatiallyPartitioned.cs @@ -86,7 +86,11 @@ namespace OpenRA.Primitives var top = (box.Top / binSize).Clamp(0, rows - 1); var bottom = (box.Bottom / binSize).Clamp(0, rows - 1); - var items = new HashSet(); + // We want to return any items intersecting the box. + // If the box covers multiple bins, we must handle items that are contained in multiple bins and avoid + // returning them more than once. We shall use a set to track these. + // PERF: If we are only looking inside one bin, we can avoid the cost of performing this tracking. + var items = top == bottom && left == right ? null : new HashSet(); for (var row = top; row <= bottom; row++) for (var col = left; col <= right; col++) { @@ -96,10 +100,12 @@ namespace OpenRA.Primitives var item = kvp.Key; var bounds = kvp.Value; - // Return items that intersect the box. We also want to avoid returning the same item many times. - // If the item is contained wholly within this bin, we're good as we know it won't show up in any others. - // Otherwise it may appear in another bin. We use a set of seen items to avoid yielding it again. - if (bounds.IntersectsWith(box) && (binBounds.Contains(bounds) || items.Add(item))) + // If the item is in the bin, we must check it intersects the box before returning it. + // We shall track it in the set of items seen so far to avoid returning it again if it appears + // in another bin. + // PERF: If the item is wholly contained within the bin, we can avoid the cost of tracking it. + if (bounds.IntersectsWith(box) && + (items == null || binBounds.Contains(bounds) || items.Add(item))) yield return item; } }