Skip to content

Commit 01c3829

Browse files
committed
Add high-performance unmanaged HashMap and tests
Introduced a high-performance, unmanaged `HashMap<TKey, TValue>` optimized for .NET 8.0 or greater. The implementation includes SIMD-based probing, alignment-aware memory management, and dynamic resizing for efficient operations. Added a `Tag` system to manage hash table slot states and utility methods for probing and hashing. Added `AlignmentHelper` for aligning values up or down to the nearest multiple of a given alignment. Included a comprehensive test suite (`HashMapTests.cs`) to verify the correctness of the `HashMap` implementation, covering operations like adding, retrieving, resizing, and removing elements.
1 parent fb75b2a commit 01c3829

File tree

3 files changed

+491
-0
lines changed

3 files changed

+491
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
namespace Hexa.NET.Utilities.Tests
2+
{
3+
[TestFixture]
4+
public unsafe class HashMapTests
5+
{
6+
[Test]
7+
public void AddAndContainsWorks()
8+
{
9+
HashMap<int, int> map = new();
10+
map.EnsureCapacity(8);
11+
map.Add(1, 100);
12+
map.Add(2, 200);
13+
Assert.That(map.Contains(1), Is.True);
14+
Assert.That(map.Contains(2), Is.True);
15+
Assert.That(map.Contains(3), Is.False);
16+
map.Release();
17+
}
18+
19+
[Test]
20+
public void TryGetValueReturnsCorrectValue()
21+
{
22+
HashMap<int, int> map = new();
23+
map.EnsureCapacity(8);
24+
map.Add(42, 420);
25+
map.Add(7, 70);
26+
Assert.That(map.TryGetValue(42, out var v1), Is.True);
27+
Assert.That(v1, Is.EqualTo(420));
28+
Assert.That(map.TryGetValue(7, out var v2), Is.True);
29+
Assert.That(v2, Is.EqualTo(70));
30+
Assert.That(map.TryGetValue(99, out var v3), Is.False);
31+
map.Release();
32+
}
33+
34+
[Test]
35+
public void AddDuplicateKeyThrows()
36+
{
37+
HashMap<int, int> map = new();
38+
map.EnsureCapacity(8);
39+
map.Add(5, 50);
40+
Assert.That(() => map.Add(5, 55), Throws.TypeOf<ArgumentException>());
41+
map.Release();
42+
}
43+
44+
[Test]
45+
public void ResizeWorksCorrectly()
46+
{
47+
HashMap<int, int> map = new();
48+
map.EnsureCapacity(2);
49+
for (int i = 0; i < 100; i++)
50+
{
51+
map.Add(i, i * 10);
52+
}
53+
for (int i = 0; i < 100; i++)
54+
{
55+
Assert.Multiple(() =>
56+
{
57+
Assert.That(map.Contains(i), Is.True);
58+
Assert.That(map.TryGetValue(i, out var v), Is.True);
59+
Assert.That(v, Is.EqualTo(i * 10));
60+
});
61+
}
62+
map.Release();
63+
}
64+
65+
[Test]
66+
public void RemoveWorksCorrectly()
67+
{
68+
HashMap<int, int> map = new();
69+
map.EnsureCapacity(8);
70+
map.Add(1, 100);
71+
map.Add(2, 200);
72+
Assert.That(map.Contains(1), Is.True);
73+
Assert.That(map.Contains(2), Is.True);
74+
Assert.That(map.Remove(1), Is.True);
75+
Assert.That(map.Contains(1), Is.False);
76+
Assert.That(map.Remove(1), Is.False);
77+
Assert.That(map.Contains(2), Is.True);
78+
Assert.That(map.Remove(2), Is.True);
79+
Assert.That(map.Contains(2), Is.False);
80+
map.Release();
81+
}
82+
}
83+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
namespace Hexa.NET.Utilities
2+
{
3+
public static class AlignmentHelper
4+
{
5+
public static ulong AlignUp(ulong size, ulong alignment)
6+
{
7+
return size + alignment - 1 & ~(alignment - 1);
8+
}
9+
10+
public static uint AlignUp(uint size, uint alignment)
11+
{
12+
return size + alignment - 1 & ~(alignment - 1);
13+
}
14+
15+
public static long AlignUp(long size, long alignment)
16+
{
17+
return size + alignment - 1 & ~(alignment - 1);
18+
}
19+
20+
public static int AlignUp(int size, int alignment)
21+
{
22+
return size + alignment - 1 & ~(alignment - 1);
23+
}
24+
25+
public static ulong AlignDown(ulong size, ulong alignment)
26+
{
27+
return size & ~(alignment - 1);
28+
}
29+
30+
public static long AlignDown(long size, long alignment)
31+
{
32+
return size & ~(alignment - 1);
33+
}
34+
35+
public static int AlignDown(int size, int alignment)
36+
{
37+
return size & ~(alignment - 1);
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)