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:
@@ -1,6 +1,6 @@
|
|||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
using Misaki.HighPerformance.Unsafe.Collections;
|
using Misaki.HighPerformance.Unsafe.Collections;
|
||||||
using Misaki.HighPerformance.Unsafe.Collections.Services;
|
using Misaki.HighPerformance.Unsafe.Services;
|
||||||
|
|
||||||
namespace Misaki.HighPerformance.Test;
|
namespace Misaki.HighPerformance.Test;
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class ParallelNoiseBenchmark
|
|||||||
[Benchmark]
|
[Benchmark]
|
||||||
public static void JobSystem()
|
public static void JobSystem()
|
||||||
{
|
{
|
||||||
using var buffers = new UnsafeArray<float>(_LENGTH, Allocator.Persistent, AllocationType.UnInitialized);
|
using var buffers = new UnsafeArray<float>(_LENGTH, Allocator.Persistent, AllocationOption.UnInitialized);
|
||||||
var job = new NoiseJob()
|
var job = new NoiseJob()
|
||||||
{
|
{
|
||||||
buffers = buffers,
|
buffers = buffers,
|
||||||
@@ -76,7 +76,7 @@ public class ParallelNoiseBenchmark
|
|||||||
[Benchmark]
|
[Benchmark]
|
||||||
public static void ParallelFor()
|
public static void ParallelFor()
|
||||||
{
|
{
|
||||||
using var buffers = new UnsafeArray<float>(_LENGTH, Allocator.Persistent, AllocationType.UnInitialized);
|
using var buffers = new UnsafeArray<float>(_LENGTH, Allocator.Persistent, AllocationOption.UnInitialized);
|
||||||
|
|
||||||
Parallel.For(0, _LENGTH, i =>
|
Parallel.For(0, _LENGTH, i =>
|
||||||
{
|
{
|
||||||
@@ -90,7 +90,7 @@ public class ParallelNoiseBenchmark
|
|||||||
[Benchmark]
|
[Benchmark]
|
||||||
public static void For()
|
public static void For()
|
||||||
{
|
{
|
||||||
using var buffers = new UnsafeArray<float>(_LENGTH, Allocator.Persistent, AllocationType.UnInitialized);
|
using var buffers = new UnsafeArray<float>(_LENGTH, Allocator.Persistent, AllocationOption.UnInitialized);
|
||||||
for (var i = 0; i < _LENGTH; i++)
|
for (var i = 0; i < _LENGTH; i++)
|
||||||
{
|
{
|
||||||
var x = i % _WIDTH;
|
var x = i % _WIDTH;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Misaki.HighPerformance.Test;
|
using Misaki.HighPerformance.Test;
|
||||||
using Misaki.HighPerformance.Unsafe.Collections.Services;
|
using Misaki.HighPerformance.Unsafe.Services;
|
||||||
|
|
||||||
AllocationManager.Initialize(512_000);
|
AllocationManager.Initialize(512_000);
|
||||||
var test = new CollectionBenchmark();
|
var test = new CollectionBenchmark();
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public unsafe struct Arena : IDisposable
|
|||||||
/// <param name="alignSize">Defines the alignment requirement for the allocated memory.</param>
|
/// <param name="alignSize">Defines the alignment requirement for the allocated memory.</param>
|
||||||
/// <returns>A pointer to the allocated memory block or null if the allocation cannot be fulfilled.</returns>
|
/// <returns>A pointer to the allocated memory block or null if the allocation cannot be fulfilled.</returns>
|
||||||
/// <exception cref="ObjectDisposedException">Thrown if the arena has been disposed.</exception>
|
/// <exception cref="ObjectDisposedException">Thrown if the arena has been disposed.</exception>
|
||||||
public void* Allocate(uint size, uint alignSize, AllocationType allocationType)
|
public void* Allocate(uint size, uint alignSize, AllocationOption allocationType)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -41,9 +41,9 @@ public unsafe struct Arena : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_offset = offset + size;
|
_offset = offset + size;
|
||||||
var ptr = (byte*)_buffer + offset;
|
var ptr = _buffer + offset;
|
||||||
|
|
||||||
if (allocationType == AllocationType.Clear)
|
if (allocationType == AllocationOption.Clear)
|
||||||
{
|
{
|
||||||
MemClear(ptr, size);
|
MemClear(ptr, size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public unsafe struct DynamicArena : IDisposable
|
|||||||
/// <param name="alignSize">Alignment requirement for the memory block.</param>
|
/// <param name="alignSize">Alignment requirement for the memory block.</param>
|
||||||
/// <returns>Pointer to the allocated memory block.</returns>
|
/// <returns>Pointer to the allocated memory block.</returns>
|
||||||
/// <exception cref="ObjectDisposedException">Thrown if the arena has been disposed.</exception>
|
/// <exception cref="ObjectDisposedException">Thrown if the arena has been disposed.</exception>
|
||||||
public void* Allocate(uint size, uint alignSize, AllocationType allocationType)
|
public void* Allocate(uint size, uint alignSize, AllocationOption allocationType)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
namespace Misaki.HighPerformance.Unsafe.Collections;
|
|
||||||
|
|
||||||
public enum AllocationType
|
|
||||||
{
|
|
||||||
UnInitialized,
|
|
||||||
Clear
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Allocator
|
|
||||||
{
|
|
||||||
Temp,
|
|
||||||
Persistent
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using Misaki.HighPerformance.Unsafe.Collections.Contracts;
|
using Misaki.HighPerformance.Unsafe.Collections.Contracts;
|
||||||
using Misaki.HighPerformance.Unsafe.Collections.Services;
|
|
||||||
using Misaki.HighPerformance.Unsafe.Helpers;
|
using Misaki.HighPerformance.Unsafe.Helpers;
|
||||||
|
using Misaki.HighPerformance.Unsafe.Services;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@@ -66,6 +66,8 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
|||||||
private T* _buffer;
|
private T* _buffer;
|
||||||
private int _count;
|
private int _count;
|
||||||
|
|
||||||
|
private readonly Allocator _allocator;
|
||||||
|
|
||||||
public readonly int Count => _count;
|
public readonly int Count => _count;
|
||||||
|
|
||||||
public readonly ref T this[int index]
|
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="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>
|
/// <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>
|
/// <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)
|
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);
|
_buffer = AllocationManager.Allocate<T>((uint)count, (uint)AlignOf<T>(), allocator, allocationType);
|
||||||
_count = count;
|
_count = count;
|
||||||
|
|
||||||
if (allocationType == AllocationType.Clear)
|
if (allocationType == AllocationOption.Clear)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
@@ -132,7 +134,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly void Clear()
|
public readonly void Clear()
|
||||||
{
|
{
|
||||||
MemClear(_buffer, (uint)(_count * sizeof(T)));
|
MemClear(_buffer, (nuint)(_count * sizeof(T)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -143,7 +145,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
AlignedFree(_buffer);
|
AllocationManager.Free(_buffer, _allocator);
|
||||||
|
|
||||||
_buffer = null;
|
_buffer = null;
|
||||||
_count = 0;
|
_count = 0;
|
||||||
|
|||||||
@@ -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));
|
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => new Enumerator((HashMapHelper<TKey>*)UnsafeUtilities.AddressOf(ref _hashMap));
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
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>
|
/// <summary>
|
||||||
|
|||||||
@@ -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));
|
public IEnumerator<T> GetEnumerator() => new Enumerator((HashMapHelper<T>*)UnsafeUtilities.AddressOf(ref _hashMap));
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
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>
|
/// <summary>
|
||||||
|
|||||||
@@ -129,12 +129,12 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
|
|||||||
|
|
||||||
public ParallelWriter AsParallelWriter() => new((UnsafeList<T>*)UnsafeUtilities.AddressOf(ref this));
|
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);
|
_array = new UnsafeArray<T>(capacity, allocator, allocationType);
|
||||||
_count = 0;
|
_count = 0;
|
||||||
|
|
||||||
if (allocationType == AllocationType.Clear)
|
if (allocationType == AllocationOption.Clear)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,13 +80,13 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
|
|||||||
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeQueue<T>*)UnsafeUtilities.AddressOf(ref this));
|
public IEnumerator<T> GetEnumerator() => new Enumerator((UnsafeQueue<T>*)UnsafeUtilities.AddressOf(ref this));
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
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);
|
_array = new UnsafeArray<T>(capacity, allocator, allocationType);
|
||||||
_count = 0;
|
_count = 0;
|
||||||
_offset = 0;
|
_offset = 0;
|
||||||
|
|
||||||
if (allocationType == AllocationType.Clear)
|
if (allocationType == AllocationOption.Clear)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Misaki.HighPerformance.Mathematics;
|
|
||||||
using Misaki.HighPerformance.Unsafe.Collections;
|
using Misaki.HighPerformance.Unsafe.Collections;
|
||||||
|
using Misaki.HighPerformance.Unsafe.Services;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@@ -74,6 +74,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
|
|
||||||
private readonly int _sizeOfTValue;
|
private readonly int _sizeOfTValue;
|
||||||
private readonly int _log2MinGrowth;
|
private readonly int _log2MinGrowth;
|
||||||
|
private readonly Allocator _allocator;
|
||||||
|
|
||||||
public const int MINIMAL_CAPACITY = 64;
|
public const int MINIMAL_CAPACITY = 64;
|
||||||
|
|
||||||
@@ -107,16 +108,6 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
get => !IsCreated || _count == 0;
|
get => !IsCreated || _count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private readonly int CalcCapacityCeilPow2(int capacity)
|
|
||||||
{
|
|
||||||
capacity = Math.Max(Math.Max(1, _count), capacity);
|
|
||||||
var newCapacity = Math.Max(capacity, 1 << _log2MinGrowth);
|
|
||||||
var result = MathUtilities.CeilPow2(newCapacity);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int CalculateDataSize(int capacity, int bucketCapacity, int sizeOfTValue, out int outKeyOffset, out int outNextOffset, out int outBucketOffset)
|
private static int CalculateDataSize(int capacity, int bucketCapacity, int sizeOfTValue, out int outKeyOffset, out int outNextOffset, out int outBucketOffset)
|
||||||
{
|
{
|
||||||
var sizeOfTKey = sizeof(TKey);
|
var sizeOfTKey = sizeof(TKey);
|
||||||
@@ -135,7 +126,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
return totalSize;
|
return totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMapHelper(int capacity, int sizeOfTValue, uint minGrowth)
|
public HashMapHelper(int capacity, int sizeOfTValue, uint minGrowth, Allocator allocator)
|
||||||
{
|
{
|
||||||
if (capacity <= 0)
|
if (capacity <= 0)
|
||||||
{
|
{
|
||||||
@@ -150,18 +141,25 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
_capacity = CalcCapacityCeilPow2(capacity);
|
_capacity = CalcCapacityCeilPow2(capacity);
|
||||||
_bucketCapacity = _capacity * 2;
|
_bucketCapacity = _capacity * 2;
|
||||||
|
|
||||||
|
_sizeOfTValue = sizeOfTValue;
|
||||||
|
_log2MinGrowth = BitOperations.Log2(minGrowth);
|
||||||
|
_allocator = allocator;
|
||||||
|
|
||||||
var totalSize = CalculateDataSize(_capacity, _bucketCapacity, sizeOfTValue,
|
var totalSize = CalculateDataSize(_capacity, _bucketCapacity, sizeOfTValue,
|
||||||
out var keyOffset, out var nextOffset, out var bucketOffset);
|
out var keyOffset, out var nextOffset, out var bucketOffset);
|
||||||
|
|
||||||
_buffer = (byte*)Malloc((nuint)totalSize);
|
AllocateBuffer(totalSize, keyOffset, nextOffset, bucketOffset);
|
||||||
_keys = (TKey*)(_buffer + keyOffset);
|
|
||||||
_next = (int*)(_buffer + nextOffset);
|
|
||||||
_buckets = (int*)(_buffer + bucketOffset);
|
|
||||||
|
|
||||||
Clear();
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
_sizeOfTValue = sizeOfTValue;
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
_log2MinGrowth = BitOperations.Log2(minGrowth);
|
private readonly int CalcCapacityCeilPow2(int capacity)
|
||||||
|
{
|
||||||
|
capacity = Math.Max(Math.Max(1, _count), capacity);
|
||||||
|
var newCapacity = Math.Max(capacity, 1 << _log2MinGrowth);
|
||||||
|
var result = MathUtilities.CeilPow2(newCapacity);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -179,6 +177,17 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void AllocateBuffer(int totalSize, int keyOffset, int nextOffset, int bucketOffset)
|
||||||
|
{
|
||||||
|
var alignSize = sizeof(TKey) > sizeof(int) ? AlignOf<TKey>() : AlignOf<int>();
|
||||||
|
|
||||||
|
_buffer = AllocationManager.Allocate<byte>((uint)totalSize, (uint)alignSize, _allocator, AllocationOption.UnInitialized);
|
||||||
|
_keys = (TKey*)(_buffer + keyOffset);
|
||||||
|
_next = (int*)(_buffer + nextOffset);
|
||||||
|
_buckets = (int*)(_buffer + bucketOffset);
|
||||||
|
}
|
||||||
|
|
||||||
internal void ResizeExact(int newCapacity, int newBucketCapacity)
|
internal void ResizeExact(int newCapacity, int newBucketCapacity)
|
||||||
{
|
{
|
||||||
var totalSize = CalculateDataSize(newCapacity, newBucketCapacity, _sizeOfTValue,
|
var totalSize = CalculateDataSize(newCapacity, newBucketCapacity, _sizeOfTValue,
|
||||||
@@ -190,10 +199,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
var oldBuckets = _buckets;
|
var oldBuckets = _buckets;
|
||||||
var oldBucketCapacity = _bucketCapacity;
|
var oldBucketCapacity = _bucketCapacity;
|
||||||
|
|
||||||
_buffer = (byte*)Malloc((nuint)totalSize);
|
AllocateBuffer(totalSize, keyOffset, nextOffset, bucketOffset);
|
||||||
_keys = (TKey*)(_buffer + keyOffset);
|
|
||||||
_next = (int*)(_buffer + nextOffset);
|
|
||||||
_buckets = (int*)(_buffer + bucketOffset);
|
|
||||||
_capacity = newCapacity;
|
_capacity = newCapacity;
|
||||||
_bucketCapacity = newBucketCapacity;
|
_bucketCapacity = newBucketCapacity;
|
||||||
|
|
||||||
@@ -405,7 +411,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
|
|
||||||
internal UnsafeArray<TKey> GetKeyArray(Allocator allocator)
|
internal UnsafeArray<TKey> GetKeyArray(Allocator allocator)
|
||||||
{
|
{
|
||||||
var result = new UnsafeArray<TKey>(_count, allocator, AllocationType.UnInitialized);
|
var result = new UnsafeArray<TKey>(_count, allocator, AllocationOption.UnInitialized);
|
||||||
|
|
||||||
for (int i = 0, count = 0, max = result.Count, capacity = _bucketCapacity; i < capacity && count < max; i++)
|
for (int i = 0, count = 0, max = result.Count, capacity = _bucketCapacity; i < capacity && count < max; i++)
|
||||||
{
|
{
|
||||||
@@ -424,7 +430,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
internal UnsafeArray<TValue> GetValueArray<TValue>(Allocator allocator)
|
internal UnsafeArray<TValue> GetValueArray<TValue>(Allocator allocator)
|
||||||
where TValue : unmanaged
|
where TValue : unmanaged
|
||||||
{
|
{
|
||||||
var result = new UnsafeArray<TValue>(_count, allocator, AllocationType.UnInitialized);
|
var result = new UnsafeArray<TValue>(_count, allocator, AllocationOption.UnInitialized);
|
||||||
|
|
||||||
for (int i = 0, count = 0, max = result.Count, capacity = _bucketCapacity; i < capacity && count < max; ++i)
|
for (int i = 0, count = 0, max = result.Count, capacity = _bucketCapacity; i < capacity && count < max; ++i)
|
||||||
{
|
{
|
||||||
@@ -443,7 +449,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
public UnsafeArray<KeyValuePair<TKey, TValue>> GetKeyValueArrays<TValue>(Allocator allocator)
|
public UnsafeArray<KeyValuePair<TKey, TValue>> GetKeyValueArrays<TValue>(Allocator allocator)
|
||||||
where TValue : unmanaged
|
where TValue : unmanaged
|
||||||
{
|
{
|
||||||
var result = new UnsafeArray<KeyValuePair<TKey, TValue>>(_count, allocator, AllocationType.UnInitialized);
|
var result = new UnsafeArray<KeyValuePair<TKey, TValue>>(_count, allocator, AllocationOption.UnInitialized);
|
||||||
|
|
||||||
for (int i = 0, count = 0, max = result.Count, capacity = _bucketCapacity; i < capacity && count < max; i++)
|
for (int i = 0, count = 0, max = result.Count, capacity = _bucketCapacity; i < capacity && count < max; i++)
|
||||||
{
|
{
|
||||||
@@ -476,7 +482,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
|||||||
{
|
{
|
||||||
if (IsCreated)
|
if (IsCreated)
|
||||||
{
|
{
|
||||||
Free(_buffer);
|
AllocationManager.Free(_buffer, _allocator);
|
||||||
|
|
||||||
_buffer = null;
|
_buffer = null;
|
||||||
_keys = null;
|
_keys = null;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Misaki.HighPerformance.Math\Misaki.HighPerformance.Mathematics.csproj" />
|
<ProjectReference Include="..\Misaki.HighPerformance\Misaki.HighPerformance.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Misaki.HighPerformance.Unsafe.Buffer;
|
using Misaki.HighPerformance.Unsafe.Buffer;
|
||||||
|
using Misaki.HighPerformance.Unsafe.Collections;
|
||||||
|
|
||||||
namespace Misaki.HighPerformance.Unsafe.Collections.Services;
|
namespace Misaki.HighPerformance.Unsafe.Services;
|
||||||
|
|
||||||
public static unsafe class AllocationManager
|
public static unsafe class AllocationManager
|
||||||
{
|
{
|
||||||
@@ -15,7 +16,7 @@ public static unsafe class AllocationManager
|
|||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T* Allocate<T>(uint size, uint alignSize, Allocator allocator, AllocationType allocationType)
|
internal static T* Allocate<T>(uint size, uint alignSize, Allocator allocator, AllocationOption allocationType)
|
||||||
where T : unmanaged
|
where T : unmanaged
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
@@ -34,6 +35,22 @@ public static unsafe class AllocationManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void Free(void* ptr, Allocator allocator)
|
||||||
|
{
|
||||||
|
if (!_initialized)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The AllocationManager has not been initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (allocator == Allocator.Persistent)
|
||||||
|
{
|
||||||
|
AlignedFree(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void Reset(bool clear = false)
|
public static void Reset(bool clear = false)
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
@@ -9,8 +9,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Misaki.HighPerformance.Unsa
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Misaki.HighPerformance.Test", "Misaki.HighPerformance.Test\Misaki.HighPerformance.Test.csproj", "{90EFF5B8-22CD-4B6A-83AB-48E0E97610EA}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Misaki.HighPerformance.Test", "Misaki.HighPerformance.Test\Misaki.HighPerformance.Test.csproj", "{90EFF5B8-22CD-4B6A-83AB-48E0E97610EA}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Misaki.HighPerformance.Mathematics", "Misaki.HighPerformance.Math\Misaki.HighPerformance.Mathematics.csproj", "{861F9574-2063-4B54-8D6A-AA32B26B6583}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -29,10 +27,6 @@ Global
|
|||||||
{90EFF5B8-22CD-4B6A-83AB-48E0E97610EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{90EFF5B8-22CD-4B6A-83AB-48E0E97610EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{90EFF5B8-22CD-4B6A-83AB-48E0E97610EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{90EFF5B8-22CD-4B6A-83AB-48E0E97610EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{90EFF5B8-22CD-4B6A-83AB-48E0E97610EA}.Release|Any CPU.Build.0 = Release|Any CPU
|
{90EFF5B8-22CD-4B6A-83AB-48E0E97610EA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{861F9574-2063-4B54-8D6A-AA32B26B6583}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{861F9574-2063-4B54-8D6A-AA32B26B6583}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{861F9574-2063-4B54-8D6A-AA32B26B6583}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{861F9574-2063-4B54-8D6A-AA32B26B6583}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
19
Misaki.HighPerformance/MathUtilities.cs
Normal file
19
Misaki.HighPerformance/MathUtilities.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Misaki.HighPerformance;
|
||||||
|
|
||||||
|
public static class MathUtilities
|
||||||
|
{
|
||||||
|
/// <summary>Returns the smallest power of two that is greater than or equal to the specified number.</summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int CeilPow2(int x)
|
||||||
|
{
|
||||||
|
x -= 1;
|
||||||
|
x |= x >> 1;
|
||||||
|
x |= x >> 2;
|
||||||
|
x |= x >> 4;
|
||||||
|
x |= x >> 8;
|
||||||
|
x |= x >> 16;
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user