feat(allocator): add unified Reallocate to all allocators
Introduce a unified Reallocate method to all memory allocator types (Arena, Stack, FreeList, VirtualArena, VirtualStack, DynamicArena) and require it in the IMemoryAllocator interface. This enables efficient resizing of memory blocks, with fast-path optimizations for stack-like allocators. Update AllocationManager and MemoryPool to use the new Reallocate method, simplifying and optimizing memory resizing logic. Add public properties for buffer pointers, sizes, and offsets to allocator structs for easier diagnostics. Set FreeList's default concurrency level to 1 and make its allocation method return null on dispose instead of throwing. Clean up vector types for formatting, fix UnsafeList's RemoveRangeSwapBack logic, and simplify RemoveAtSwapBack. Simplify Program.cs to only run SPMDBenchmark. Add new unit tests for FixedString, UnsafeList, UnsafeHashMap, and UnsafeHashSet. Apply minor test code cleanups for consistency in TestUnsafeQueue. BREAKING CHANGE: IMemoryAllocator now requires a Reallocate method, and allocator APIs have changed accordingly.
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
namespace Misaki.HighPerformance.Test.UnitTest.Collections;
|
||||
|
||||
[TestClass]
|
||||
public class TestFixedString
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestFixedString32()
|
||||
{
|
||||
var fs = new FixedString32("Hello");
|
||||
Assert.AreEqual(5, fs.Length);
|
||||
Assert.AreEqual("Hello", fs.ToString());
|
||||
Assert.AreEqual("Hello", fs.Value);
|
||||
|
||||
fs.Value = "World";
|
||||
Assert.AreEqual(5, fs.Length);
|
||||
Assert.AreEqual("World", fs.Value);
|
||||
|
||||
fs.Value = "";
|
||||
Assert.AreEqual(0, fs.Length);
|
||||
Assert.AreEqual("", fs.Value);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestFixedString32TooLong()
|
||||
{
|
||||
// MAX_LENGTH is 15
|
||||
try
|
||||
{
|
||||
new FixedString32("This string is definitely longer than 15 characters");
|
||||
Assert.Fail("Should have thrown ArgumentException");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Success
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestFixedString64()
|
||||
{
|
||||
var fs = new FixedString64("A bit longer string");
|
||||
Assert.AreEqual("A bit longer string", fs.Value);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestFixedString128()
|
||||
{
|
||||
var fs = new FixedString128("Even longer string for 128 bytes buffer");
|
||||
Assert.AreEqual("Even longer string for 128 bytes buffer", fs.Value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
namespace Misaki.HighPerformance.Test.UnitTest.Collections;
|
||||
|
||||
[TestClass]
|
||||
public class TestUnsafeHashMap
|
||||
{
|
||||
private UnsafeHashMap<int, int> _map;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
_map = new UnsafeHashMap<int, int>(4, Allocator.Persistent);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
if (_map.IsCreated)
|
||||
{
|
||||
_map.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestAddGet()
|
||||
{
|
||||
_map.Add(1, 100);
|
||||
_map.Add(2, 200);
|
||||
Assert.AreEqual(2, _map.Count);
|
||||
Assert.AreEqual(100, _map[1]);
|
||||
Assert.AreEqual(200, _map[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestTryAdd()
|
||||
{
|
||||
Assert.IsTrue(_map.TryAdd(1, 100));
|
||||
Assert.IsFalse(_map.TryAdd(1, 200)); // Duplicate key
|
||||
Assert.AreEqual(100, _map[1]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestRemove()
|
||||
{
|
||||
_map.Add(1, 100);
|
||||
Assert.IsTrue(_map.Remove(1));
|
||||
Assert.IsFalse(_map.ContainsKey(1));
|
||||
Assert.AreEqual(0, _map.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestTryGetValue()
|
||||
{
|
||||
_map.Add(1, 100);
|
||||
Assert.IsTrue(_map.TryGetValue(1, out var value));
|
||||
Assert.AreEqual(100, value);
|
||||
Assert.IsFalse(_map.TryGetValue(2, out _));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestIndexerUpdate()
|
||||
{
|
||||
_map[1] = 100;
|
||||
_map[1] = 200;
|
||||
Assert.AreEqual(200, _map[1]);
|
||||
Assert.AreEqual(1, _map.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestClear()
|
||||
{
|
||||
_map.Add(1, 100);
|
||||
_map.Clear();
|
||||
Assert.AreEqual(0, _map.Count);
|
||||
Assert.IsFalse(_map.ContainsKey(1));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestEnumerator()
|
||||
{
|
||||
_map.Add(1, 10);
|
||||
_map.Add(2, 20);
|
||||
var keySum = 0;
|
||||
var valueSum = 0;
|
||||
foreach (var kvp in _map)
|
||||
{
|
||||
keySum += kvp.Key;
|
||||
valueSum += kvp.Value;
|
||||
}
|
||||
Assert.AreEqual(3, keySum);
|
||||
Assert.AreEqual(30, valueSum);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
namespace Misaki.HighPerformance.Test.UnitTest.Collections;
|
||||
|
||||
[TestClass]
|
||||
public class TestUnsafeHashSet
|
||||
{
|
||||
private UnsafeHashSet<int> _set;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
_set = new UnsafeHashSet<int>(4, Allocator.Persistent);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
if (_set.IsCreated)
|
||||
{
|
||||
_set.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestAddContains()
|
||||
{
|
||||
Assert.IsTrue(_set.Add(1));
|
||||
Assert.IsTrue(_set.Add(2));
|
||||
Assert.IsFalse(_set.Add(1)); // Duplicate
|
||||
Assert.AreEqual(2, _set.Count);
|
||||
Assert.IsTrue(_set.Contains(1));
|
||||
Assert.IsTrue(_set.Contains(2));
|
||||
Assert.IsFalse(_set.Contains(3));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestRemove()
|
||||
{
|
||||
_set.Add(1);
|
||||
_set.Add(2);
|
||||
Assert.IsTrue(_set.Remove(1));
|
||||
Assert.IsFalse(_set.Contains(1));
|
||||
Assert.AreEqual(1, _set.Count);
|
||||
Assert.IsFalse(_set.Remove(3)); // Not present
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestClear()
|
||||
{
|
||||
_set.Add(1);
|
||||
_set.Add(2);
|
||||
_set.Clear();
|
||||
Assert.AreEqual(0, _set.Count);
|
||||
Assert.IsFalse(_set.Contains(1));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestResize()
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
_set.Add(i);
|
||||
}
|
||||
Assert.AreEqual(100, _set.Count);
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
Assert.IsTrue(_set.Contains(i));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestEnumerator()
|
||||
{
|
||||
_set.Add(10);
|
||||
_set.Add(20);
|
||||
var sum = 0;
|
||||
var count = 0;
|
||||
foreach (var item in _set)
|
||||
{
|
||||
sum += item;
|
||||
count++;
|
||||
}
|
||||
Assert.AreEqual(30, sum);
|
||||
Assert.AreEqual(2, count);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
namespace Misaki.HighPerformance.Test.UnitTest.Collections;
|
||||
|
||||
[TestClass]
|
||||
public class TestUnsafeList
|
||||
{
|
||||
private UnsafeList<int> _list;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
_list = new UnsafeList<int>(4, Allocator.Persistent);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
if (_list.IsCreated)
|
||||
{
|
||||
_list.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestAdd()
|
||||
{
|
||||
_list.Add(1);
|
||||
_list.Add(2);
|
||||
_list.Add(3);
|
||||
Assert.AreEqual(3, _list.Count);
|
||||
Assert.AreEqual(1, _list[0]);
|
||||
Assert.AreEqual(2, _list[1]);
|
||||
Assert.AreEqual(3, _list[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestResize()
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
_list.Add(i);
|
||||
}
|
||||
Assert.AreEqual(10, _list.Count);
|
||||
Assert.IsTrue(_list.Capacity >= 10);
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
Assert.AreEqual(i, _list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestRemoveAt()
|
||||
{
|
||||
_list.Add(0);
|
||||
_list.Add(1);
|
||||
_list.Add(2);
|
||||
_list.RemoveAt(1);
|
||||
Assert.AreEqual(2, _list.Count);
|
||||
Assert.AreEqual(0, _list[0]);
|
||||
Assert.AreEqual(2, _list[1]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestRemoveAtSwapBack()
|
||||
{
|
||||
_list.Add(10);
|
||||
_list.Add(11);
|
||||
_list.Add(12);
|
||||
_list.Add(13);
|
||||
|
||||
// Before: [10, 11, 12, 13]
|
||||
_list.RemoveAtSwapBack(1);
|
||||
// After: [10, 13, 12]
|
||||
|
||||
Assert.AreEqual(3, _list.Count, "Count should be 3");
|
||||
Assert.AreEqual(10, _list[0], "Index 0 should be 10");
|
||||
Assert.AreEqual(13, _list[1], "Index 1 should be 13");
|
||||
Assert.AreEqual(12, _list[2], "Index 2 should be 12");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestClear()
|
||||
{
|
||||
_list.Add(1);
|
||||
_list.Add(2);
|
||||
_list.Clear();
|
||||
Assert.AreEqual(0, _list.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestAddRange()
|
||||
{
|
||||
int[] values = { 10, 20, 30 };
|
||||
_list.AddRange(values);
|
||||
Assert.AreEqual(3, _list.Count);
|
||||
Assert.AreEqual(10, _list[0]);
|
||||
Assert.AreEqual(20, _list[1]);
|
||||
Assert.AreEqual(30, _list[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestAsSpan()
|
||||
{
|
||||
_list.Add(1);
|
||||
_list.Add(2);
|
||||
var span = _list.AsSpan();
|
||||
Assert.AreEqual(2, span.Length);
|
||||
Assert.AreEqual(1, span[0]);
|
||||
Assert.AreEqual(2, span[1]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestEnumerator()
|
||||
{
|
||||
_list.Add(1);
|
||||
_list.Add(2);
|
||||
_list.Add(3);
|
||||
var sum = 0;
|
||||
foreach (var item in _list)
|
||||
{
|
||||
sum += item;
|
||||
}
|
||||
Assert.AreEqual(6, sum);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Misaki.HighPerformance.Test.UnitTest.Collections;
|
||||
|
||||
@@ -50,14 +47,14 @@ public class TestUnsafeQueue
|
||||
{
|
||||
Assert.IsFalse(_queue.TryPeek(out _));
|
||||
_queue.Enqueue(5);
|
||||
Assert.IsTrue(_queue.TryPeek(out int value));
|
||||
Assert.IsTrue(_queue.TryPeek(out var value));
|
||||
Assert.AreEqual(5, value);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestResize()
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
_queue.Enqueue(i);
|
||||
}
|
||||
@@ -67,12 +64,12 @@ public class TestUnsafeQueue
|
||||
_queue.Dequeue();
|
||||
_queue.Dequeue();
|
||||
|
||||
for (int i = 10; i < 20; i++)
|
||||
for (var i = 10; i < 20; i++)
|
||||
{
|
||||
_queue.Enqueue(i);
|
||||
}
|
||||
|
||||
for (int i = 2; i < 20; i++)
|
||||
for (var i = 2; i < 20; i++)
|
||||
{
|
||||
Assert.AreEqual(i, _queue.Dequeue());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user