Refactor memory management with MemoryHandle
Replaced `SafeHandle` with a new `MemoryHandle` system for improved memory tracking, safety, and leak detection. Updated allocators (`ArenaAllocator`, `HeapAllocator`, `StackAllocator`) and collections (`UnTypedArray`, `UnsafeArray<T>`, `UnsafeBitSet`) to use `MemoryHandle`. Refactored `AllocationManager` to use `ConcurrentSlotMap` for live allocation tracking and added methods for managing `MemoryHandle` instances. Simplified alignment and padding logic across allocators and collections. Enhanced performance with optimized memory operations (`MemClear`, `MemSet`, `MemCpy`) and vectorized operations in `MemoryUtility` and `UnsafeBitSet`. Fixed alignment issues in vectorized memory operations. Updated tests to reflect the new memory management system and added new tests for `UnsafeBitSet` bitwise operations. Enabled `ENABLE_COLLECTION_CHECKS` for debug builds and improved error messages and documentation. Removed unused `SafeHandle` code and adjusted project configuration to include necessary references.
This commit is contained in:
@@ -18,9 +18,9 @@
|
||||
|
||||
//Console.WriteLine($"Count should be {threadCount * 990}, actual: {map.Count}");
|
||||
|
||||
using Misaki.HighPerformance.LowLevel;
|
||||
//using Misaki.HighPerformance.LowLevel;
|
||||
|
||||
BenchmarkDotNet.Running.BenchmarkRunner.Run<Misaki.HighPerformance.Test.Benchmark.CollectionBenchmark>();
|
||||
//BenchmarkDotNet.Running.BenchmarkRunner.Run<Misaki.HighPerformance.Test.Benchmark.CollectionBenchmark>();
|
||||
|
||||
//using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
//using Misaki.HighPerformance.LowLevel.Collections;
|
||||
@@ -40,28 +40,16 @@ BenchmarkDotNet.Running.BenchmarkRunner.Run<Misaki.HighPerformance.Test.Benchmar
|
||||
// }
|
||||
//}
|
||||
|
||||
//var arr1 = new Misaki.HighPerformance.LowLevel.Collections.UnsafeArray<int>(10, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||
//var arr2 = arr1;
|
||||
var arr1 = new Misaki.HighPerformance.LowLevel.Collections.UnsafeArray<int>(10, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||
var arr2 = arr1;
|
||||
|
||||
//arr1.Dispose();
|
||||
//try
|
||||
//{
|
||||
// arr2[0] = 42; // This should throw an exception because arr1 has been disposed.
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// Console.WriteLine($"Caught expected exception: {ex.Message}");
|
||||
//}
|
||||
//arr2.Dispose(); // This should not cause a double free error because of safe handle.
|
||||
|
||||
var a = new UniquePtr<MyStruct>();
|
||||
unsafe
|
||||
arr1.Dispose();
|
||||
try
|
||||
{
|
||||
var b = a.Share();
|
||||
b.Get()->Value = 42;
|
||||
arr2[0] = 42; // This should throw an exception because arr1 has been disposed.
|
||||
arr2.Dispose();
|
||||
}
|
||||
|
||||
internal struct MyStruct
|
||||
catch (Exception ex)
|
||||
{
|
||||
public int Value;
|
||||
}
|
||||
Console.WriteLine($"Caught expected exception: {ex.Message}");
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class TestAllocationManager
|
||||
}
|
||||
finally
|
||||
{
|
||||
var leaks = AllocationManager.LiveHeapAllocationCount;
|
||||
var leaks = AllocationManager.LiveAllocationCount;
|
||||
Assert.AreEqual(0, leaks);
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public class TestAllocationManager
|
||||
}
|
||||
catch (MemoryLeakException)
|
||||
{
|
||||
var leaks = AllocationManager.LiveHeapAllocationCount;
|
||||
var leaks = AllocationManager.LiveAllocationCount;
|
||||
Assert.AreEqual(2, leaks);
|
||||
|
||||
return;
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Misaki.HighPerformance.Test.UnitTest.Collections;
|
||||
|
||||
@@ -32,7 +26,7 @@ public class TestUnsafeBitSet
|
||||
[TestMethod]
|
||||
public void TestBitCount()
|
||||
{
|
||||
Assert.AreEqual(256, _set1.BitCount);
|
||||
Assert.AreEqual(256, _set1.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -48,20 +42,20 @@ public class TestUnsafeBitSet
|
||||
[TestMethod]
|
||||
public void TestClearAll()
|
||||
{
|
||||
for (int i = 0; i < _set1.BitCount; i++)
|
||||
for (var i = 0; i < _set1.Count; i++)
|
||||
{
|
||||
_set1.SetBit(i);
|
||||
}
|
||||
|
||||
_set1.ClearAll();
|
||||
for (int i = 0; i < _set1.BitCount; i++)
|
||||
for (var i = 0; i < _set1.Count; i++)
|
||||
{
|
||||
Assert.IsFalse(_set1.IsSet(i));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestAndOperation()
|
||||
public void TestAnd()
|
||||
{
|
||||
_set1.SetBit(0);
|
||||
_set1.SetBit(1);
|
||||
@@ -75,4 +69,41 @@ public class TestUnsafeBitSet
|
||||
Assert.IsTrue(_set1.IsSet(1));
|
||||
Assert.IsFalse(_set1.IsSet(2));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestNot()
|
||||
{
|
||||
_set1.SetBit(0);
|
||||
_set1.SetBit(1);
|
||||
|
||||
_set2.SetBit(1);
|
||||
_set2.SetBit(2);
|
||||
|
||||
_set1.Not();
|
||||
_set2.Not();
|
||||
|
||||
Assert.IsFalse(_set1.IsSet(0));
|
||||
Assert.IsFalse(_set1.IsSet(1));
|
||||
Assert.IsTrue(_set1.IsSet(2));
|
||||
Assert.IsTrue(_set1.IsSet(3));
|
||||
Assert.IsTrue(_set2.IsSet(0));
|
||||
Assert.IsFalse(_set2.IsSet(1));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestANDC()
|
||||
{
|
||||
_set1.SetBit(0);
|
||||
_set1.SetBit(1);
|
||||
|
||||
_set2.SetBit(1);
|
||||
_set2.SetBit(2);
|
||||
|
||||
_set1.ANDC(_set2);
|
||||
|
||||
Assert.IsTrue(_set1.IsSet(0));
|
||||
Assert.IsFalse(_set1.IsSet(1));
|
||||
Assert.IsFalse(_set1.IsSet(2));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user