optimize away a dictionary lookup in SpatialHash

generics
Evan Hemsley 2019-12-31 16:13:11 -08:00
parent d9bc05ee32
commit 50e4b86029
3 changed files with 33 additions and 29 deletions

View File

@ -12,7 +12,7 @@ namespace MoonTools.Core.Bonk
{ {
private readonly int cellSize; private readonly int cellSize;
private readonly Dictionary<int, Dictionary<int, HashSet<T>>> hashDictionary = new Dictionary<int, Dictionary<int, HashSet<T>>>(); private readonly Dictionary<long, HashSet<T>> hashDictionary = new Dictionary<long, HashSet<T>>();
private readonly Dictionary<T, (IShape2D, Transform2D)> IDLookup = new Dictionary<T, (IShape2D, Transform2D)>(); private readonly Dictionary<T, (IShape2D, Transform2D)> IDLookup = new Dictionary<T, (IShape2D, Transform2D)>();
public SpatialHash(int cellSize) public SpatialHash(int cellSize)
@ -41,17 +41,13 @@ namespace MoonTools.Core.Bonk
{ {
for (int j = minHash.Item2; j <= maxHash.Item2; j++) for (int j = minHash.Item2; j <= maxHash.Item2; j++)
{ {
if (!hashDictionary.ContainsKey(i)) var key = LongHelper.MakeLong(i, j);
if (!hashDictionary.ContainsKey(key))
{ {
hashDictionary.Add(i, new Dictionary<int, HashSet<T>>()); hashDictionary.Add(key, new HashSet<T>());
} }
if (!hashDictionary[i].ContainsKey(j)) hashDictionary[key].Add(id);
{
hashDictionary[i].Add(j, new HashSet<T>());
}
hashDictionary[i][j].Add(id);
IDLookup[id] = (shape, transform2D); IDLookup[id] = (shape, transform2D);
} }
} }
@ -70,9 +66,10 @@ namespace MoonTools.Core.Bonk
{ {
for (int j = minHash.Item2; j <= maxHash.Item2; j++) for (int j = minHash.Item2; j <= maxHash.Item2; j++)
{ {
if (hashDictionary.ContainsKey(i) && hashDictionary[i].ContainsKey(j)) var key = LongHelper.MakeLong(i, j);
if (hashDictionary.ContainsKey(key))
{ {
foreach (var t in hashDictionary[i][j]) foreach (var t in hashDictionary[key])
{ {
var (otherShape, otherTransform) = IDLookup[t]; var (otherShape, otherTransform) = IDLookup[t];
if (!id.Equals(t)) { yield return (t, otherShape, otherTransform); } if (!id.Equals(t)) { yield return (t, otherShape, otherTransform); }
@ -87,12 +84,9 @@ namespace MoonTools.Core.Bonk
/// </summary> /// </summary>
public void Clear() public void Clear()
{ {
foreach (var innerDict in hashDictionary.Values) foreach (var hash in hashDictionary.Values)
{ {
foreach (var set in innerDict.Values) hash.Clear();
{
set.Clear();
}
} }
IDLookup.Clear(); IDLookup.Clear();

10
Bonk/LongHelper.cs Normal file
View File

@ -0,0 +1,10 @@
namespace MoonTools.Core.Bonk
{
public static class LongHelper
{
public static long MakeLong(int left, int right)
{
return ((long)left << 32) | ((uint)right);
}
}
}

View File

@ -13,28 +13,28 @@ namespace Tests
{ {
var spatialHash = new SpatialHash<int>(16); var spatialHash = new SpatialHash<int>(16);
var rectA = new MoonTools.Core.Bonk.Rectangle(-2, -2, 2, 2); var rectA = new Rectangle(-2, -2, 2, 2);
var rectATransform = new Transform2D(new Vector2(-8, -8)); var rectATransform = new Transform2D(new Vector2(-8, -8));
var rectB = new MoonTools.Core.Bonk.Rectangle(-2, -2, 2, 2); var rectB = new Rectangle(-2, -2, 2, 2);
var rectBTransform = new Transform2D(new Vector2(8, 8)); var rectBTransform = new Transform2D(new Vector2(8, 8));
var rectC = new MoonTools.Core.Bonk.Rectangle(-2, -2, 2, 2); var rectC = new Rectangle(-2, -2, 2, 2);
var rectCTransform = new Transform2D(new Vector2(24, -4)); var rectCTransform = new Transform2D(new Vector2(24, -4));
var rectD = new MoonTools.Core.Bonk.Rectangle(-2, -2, 2, 2); var rectD = new Rectangle(-2, -2, 2, 2);
var rectDTransform = new Transform2D(new Vector2(24, 24)); var rectDTransform = new Transform2D(new Vector2(24, 24));
var circleA = new MoonTools.Core.Bonk.Circle(2); var circleA = new Circle(2);
var circleATransform = new Transform2D(new Vector2(24, -8)); var circleATransform = new Transform2D(new Vector2(24, -8));
var circleB = new MoonTools.Core.Bonk.Circle(8); var circleB = new Circle(8);
var circleBTransform = new Transform2D(new Vector2(16, 16)); var circleBTransform = new Transform2D(new Vector2(16, 16));
var line = new MoonTools.Core.Bonk.Line(new Position2D(20, -4), new Position2D(22, -12)); var line = new Line(new Position2D(20, -4), new Position2D(22, -12));
var lineTransform = new Transform2D(new Vector2(0, 0)); var lineTransform = new Transform2D(new Vector2(0, 0));
var point = new MoonTools.Core.Bonk.Point(8, 8); var point = new Point(8, 8);
var pointTransform = Transform2D.DefaultTransform; var pointTransform = Transform2D.DefaultTransform;
spatialHash.Insert(0, rectA, rectATransform); spatialHash.Insert(0, rectA, rectATransform);
@ -63,13 +63,13 @@ namespace Tests
{ {
var spatialHash = new SpatialHash<int>(16); var spatialHash = new SpatialHash<int>(16);
var rectA = new MoonTools.Core.Bonk.Rectangle(-2, -2, 2, 2); var rectA = new Rectangle(-2, -2, 2, 2);
var rectATransform = new Transform2D(new Vector2(-8, -8)); var rectATransform = new Transform2D(new Vector2(-8, -8));
var rectB = new MoonTools.Core.Bonk.Rectangle(-2, -2, 2, 2); var rectB = new Rectangle(-2, -2, 2, 2);
var rectBTransform = new Transform2D(new Vector2(-8, -8)); var rectBTransform = new Transform2D(new Vector2(-8, -8));
var rectC = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); var rectC = new Rectangle(-1, -1, 1, 1);
var rectCTransform = new Transform2D(new Vector2(-8, -8)); var rectCTransform = new Transform2D(new Vector2(-8, -8));
spatialHash.Insert(0, rectA, rectATransform); spatialHash.Insert(0, rectA, rectATransform);
@ -84,10 +84,10 @@ namespace Tests
{ {
var spatialHash = new SpatialHash<int>(16); var spatialHash = new SpatialHash<int>(16);
var rectA = new MoonTools.Core.Bonk.Rectangle(-2, -2, 2, 2); var rectA = new Rectangle(-2, -2, 2, 2);
var rectATransform = new Transform2D(new Vector2(-8, -8)); var rectATransform = new Transform2D(new Vector2(-8, -8));
var rectB = new MoonTools.Core.Bonk.Rectangle(-2, -2, 2, 2); var rectB = new Rectangle(-2, -2, 2, 2);
var rectBTransform = new Transform2D(new Vector2(8, 8)); var rectBTransform = new Transform2D(new Vector2(8, 8));
spatialHash.Insert(0, rectA, rectATransform); spatialHash.Insert(0, rectA, rectATransform);