Refactor allocation types and improve memory management

This commit renames `AllocationType` to `AllocationOption` across multiple files, enhancing clarity in memory allocation practices. Key updates include:
- Modifications to the `UnsafeArray`, `ParallelNoiseBenchmark`, `Arena`, and `DynamicArena` classes to utilize the new `AllocationOption`.
- Refactoring of the `AllocationManager` and `HashMapHelper` classes to support the new allocation strategy.
- Removal of the `Misaki.HighPerformance.Mathematics` project reference, indicating a restructuring of dependencies.
- Introduction of a new `MathUtilities` class for calculating the smallest power of two, aiding memory allocation strategies.

These changes collectively improve code maintainability and clarity in memory management.
This commit is contained in:
Misaki
2025-04-03 12:06:25 +09:00
parent 48f2dce778
commit da64e07c6f
17 changed files with 111 additions and 71 deletions

View File

@@ -0,0 +1,15 @@
namespace Misaki.HighPerformance.Unsafe.Collections;
public enum AllocationOption : byte
{
UnInitialized,
Clear
}
public enum Allocator: byte
{
// Make the first allocator as invalid because we don't want to user create a defualt collection without passing any parameters
Invalid = 0,
Temp = 1,
Persistent = 2,
}

View File

@@ -1,13 +0,0 @@
namespace Misaki.HighPerformance.Unsafe.Collections;
public enum AllocationType
{
UnInitialized,
Clear
}
public enum Allocator
{
Temp,
Persistent
}

View File

@@ -1,51 +0,0 @@
using Misaki.HighPerformance.Unsafe.Buffer;
namespace Misaki.HighPerformance.Unsafe.Collections.Services;
public static unsafe class AllocationManager
{
private static DynamicArena _arena;
private static bool _initialized;
private static readonly Lock _lock = new();
public static void Initialize(uint initialSize)
{
_arena = new DynamicArena(initialSize);
_initialized = true;
}
public static T* Allocate<T>(uint size, uint alignSize, Allocator allocator, AllocationType allocationType)
where T : unmanaged
{
if (!_initialized)
{
throw new InvalidOperationException("The AllocationManager has not been initialized.");
}
lock (_lock)
{
return allocator switch
{
Allocator.Temp => (T*)_arena.Allocate(size * (uint)sizeof(T), alignSize, allocationType),
Allocator.Persistent => (T*)AlignedAlloc((nuint)(size * sizeof(T)), alignSize),
_ => throw new ArgumentOutOfRangeException(nameof(allocator), "Invalid allocator type."),
};
}
}
public static void Reset(bool clear = false)
{
if (!_initialized)
{
throw new InvalidOperationException("The AllocationManager has not been initialized.");
}
_arena.Reset(clear);
}
public static void Dispose()
{
_arena.Dispose();
}
}

View File

@@ -1,6 +1,6 @@
using Misaki.HighPerformance.Unsafe.Collections.Contracts;
using Misaki.HighPerformance.Unsafe.Collections.Services;
using Misaki.HighPerformance.Unsafe.Helpers;
using Misaki.HighPerformance.Unsafe.Services;
using System.Collections;
using System.Runtime.CompilerServices;
@@ -66,6 +66,8 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
private T* _buffer;
private int _count;
private readonly Allocator _allocator;
public readonly int Count => _count;
public readonly ref T this[int index]
@@ -90,7 +92,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
/// <param name="count">Specifies the number of elements to allocate in the array, which must be greater than zero.</param>
/// <param name="allocationType">Determines how the allocated memory should be initialized, either uninitialized or cleared.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the specified number of elements is less than or equal to zero.</exception>
public UnsafeArray(int count, Allocator allocator, AllocationType allocationType = AllocationType.UnInitialized)
public UnsafeArray(int count, Allocator allocator, AllocationOption allocationType = AllocationOption.UnInitialized)
{
if (count <= 0)
{
@@ -100,7 +102,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
_buffer = AllocationManager.Allocate<T>((uint)count, (uint)AlignOf<T>(), allocator, allocationType);
_count = count;
if (allocationType == AllocationType.Clear)
if (allocationType == AllocationOption.Clear)
{
Clear();
}
@@ -132,7 +134,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void Clear()
{
MemClear(_buffer, (uint)(_count * sizeof(T)));
MemClear(_buffer, (nuint)(_count * sizeof(T)));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -143,7 +145,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
public void Dispose()
{
AlignedFree(_buffer);
AllocationManager.Free(_buffer, _allocator);
_buffer = null;
_count = 0;

View File

@@ -92,9 +92,9 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeCollection<KeyValuePai
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => new Enumerator((HashMapHelper<TKey>*)UnsafeUtilities.AddressOf(ref _hashMap));
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public UnsafeHashMap(int capacity)
public UnsafeHashMap(int capacity, Allocator allocator)
{
_hashMap = new HashMapHelper<TKey>(capacity, sizeof(TValue), HashMapHelper<TKey>.MINIMAL_CAPACITY);
_hashMap = new HashMapHelper<TKey>(capacity, sizeof(TValue), HashMapHelper<TKey>.MINIMAL_CAPACITY, allocator);
}
/// <summary>

View File

@@ -49,9 +49,9 @@ public unsafe struct UnsafeHashSet<T> : IUnsafeCollection<T>, IEnumerable<T>
public IEnumerator<T> GetEnumerator() => new Enumerator((HashMapHelper<T>*)UnsafeUtilities.AddressOf(ref _hashMap));
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public UnsafeHashSet(int capacity)
public UnsafeHashSet(int capacity, Allocator allocator)
{
_hashMap = new HashMapHelper<T>(capacity, 0, HashMapHelper<T>.MINIMAL_CAPACITY);
_hashMap = new HashMapHelper<T>(capacity, 0, HashMapHelper<T>.MINIMAL_CAPACITY, allocator);
}
/// <summary>

View File

@@ -129,12 +129,12 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
public ParallelWriter AsParallelWriter() => new((UnsafeList<T>*)UnsafeUtilities.AddressOf(ref this));
public UnsafeList(int capacity, Allocator allocator, AllocationType allocationType = AllocationType.UnInitialized)
public UnsafeList(int capacity, Allocator allocator, AllocationOption allocationType = AllocationOption.UnInitialized)
{
_array = new UnsafeArray<T>(capacity, allocator, allocationType);
_count = 0;
if (allocationType == AllocationType.Clear)
if (allocationType == AllocationOption.Clear)
{
Clear();
}

View File

@@ -80,13 +80,13 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeQueue<T>*)UnsafeUtilities.AddressOf(ref this));
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public UnsafeQueue(int capacity, Allocator allocator, AllocationType allocationType = AllocationType.UnInitialized)
public UnsafeQueue(int capacity, Allocator allocator, AllocationOption allocationType = AllocationOption.UnInitialized)
{
_array = new UnsafeArray<T>(capacity, allocator, allocationType);
_count = 0;
_offset = 0;
if (allocationType == AllocationType.Clear)
if (allocationType == AllocationOption.Clear)
{
Clear();
}