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.
This commit is contained in:
RoosterDragon
2015-12-12 00:47:58 +00:00
parent 8ec03ab3b7
commit 8d2fc24fbe

View File

@@ -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<T>();
// 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<T>();
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;
}
}