Centralize memory ops via MemoryUtility, add VM support

Refactor all memory allocation/deallocation to use MemoryUtility, replacing direct calls with unified methods. Introduce cross-platform virtual memory management (Mmap, Munmap, Decommit, Recommit). Switch to NativeMemory for standard allocations. Enhance FreeList with global free buckets and thread safety. Standardize alignment/size calculations. Remove global usings for memory utils. Bump version to 1.6.24. Includes minor cleanups and improved docs.
This commit is contained in:
2026-05-07 21:34:25 +09:00
parent f8b11182a9
commit d2c165bbe5
21 changed files with 382 additions and 111 deletions

View File

@@ -132,8 +132,8 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
_capacity = CalcCapacityCeilPow2(capacity);
_bucketCapacity = _capacity * 2;
var alignOfKey = (int)AlignOf<TKey>();
var alignOfInt = (int)AlignOf<int>();
var alignOfKey = (int)MemoryUtility.AlignOf<TKey>();
var alignOfInt = (int)MemoryUtility.AlignOf<int>();
var maxDataAlign = Math.Max(Math.Max(alignOfTValue, alignOfKey), alignOfInt);
_alignment = maxDataAlign;
@@ -276,7 +276,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
for (var idx = oldBuckets[i]; idx != -1; idx = oldNext[idx])
{
var newIdx = Add(oldKeys[idx]);
MemCpy(_buffer + _sizeOfTValue * newIdx, oldBuffer + _sizeOfTValue * idx, (nuint)_sizeOfTValue);
MemoryUtility.MemCpy(_buffer + _sizeOfTValue * newIdx, oldBuffer + _sizeOfTValue * idx, (nuint)_sizeOfTValue);
}
}
@@ -684,8 +684,8 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
{
ThrowIfNotCreated();
MemSet(_buckets, 0xff, (nuint)_bucketCapacity * sizeof(int));
MemSet(_next, 0xff, (nuint)_capacity * sizeof(int));
MemoryUtility.MemSet(_buckets, 0xff, (nuint)_bucketCapacity * sizeof(int));
MemoryUtility.MemSet(_next, 0xff, (nuint)_capacity * sizeof(int));
_count = 0;
_firstFreeIndex = -1;

View File

@@ -136,7 +136,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
{
ArgumentOutOfRangeException.ThrowIfNegative(count);
_buffer = (T*)handle.Alloc((nuint)(count * sizeof(T)), AlignOf<T>(), allocationOption);
_buffer = (T*)handle.Alloc((nuint)(count * sizeof(T)), MemoryUtility.AlignOf<T>(), allocationOption);
#if MHP_ENABLE_SAFETY_CHECKS
_memoryHandle = MemoryHandle.Create(_buffer, (nuint)(count * sizeof(T)));
#endif
@@ -221,11 +221,11 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
return;
}
var elemSize = SizeOf<T>();
_buffer = (T*)_allocationHandle.Realloc(_buffer, (nuint)Count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option);
var elemSize = sizeof(T);
_buffer = (T*)_allocationHandle.Realloc(_buffer, (nuint)(_count * elemSize), (nuint)(newSize * elemSize), MemoryUtility.AlignOf<T>(), option);
_count = newSize;
#if MHP_ENABLE_SAFETY_CHECKS
_memoryHandle.Update(_buffer, (nuint)newSize * elemSize);
_memoryHandle.Update(_buffer, (nuint)(newSize * elemSize));
#endif
}
@@ -234,7 +234,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
public readonly void Clear()
{
ThrowIfNotCreated();
MemClear(_buffer, (nuint)(Count * sizeof(T)));
MemoryUtility.MemClear(_buffer, (nuint)_count * MemoryUtility.SizeOf<T>());
}
/// <inheritdoc/>
@@ -292,7 +292,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
var size = Math.Min(destination.Length, Count);
fixed (T* pDest = destination)
{
MemCpy(pDest, _buffer, (uint)(size * sizeof(T)));
MemoryUtility.MemCpy(pDest, _buffer, (nuint)(size * sizeof(T)));
}
}
@@ -313,7 +313,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
fixed (T* pDest = destination)
{
MemCpy(pDest + destinationIndex, _buffer + sourceIndex, (nuint)(length * sizeof(T)));
MemoryUtility.MemCpy(pDest + destinationIndex, _buffer + sourceIndex, (nuint)(length * sizeof(T)));
}
}
@@ -330,7 +330,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
fixed (T* pSrc = source)
{
MemCpy(_buffer, pSrc, (nuint)(source.Length * sizeof(T)));
MemoryUtility.MemCpy(_buffer, pSrc, (nuint)(source.Length * sizeof(T)));
}
}
@@ -356,7 +356,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
fixed (T* pSrc = source)
{
MemCpy(_buffer + destinationIndex, pSrc + sourceIndex, (nuint)(length * sizeof(T)));
MemoryUtility.MemCpy(_buffer + destinationIndex, pSrc + sourceIndex, (nuint)(length * sizeof(T)));
}
}

View File

@@ -84,7 +84,7 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
public UnsafeHashMap(int capacity, AllocationHandle handle, AllocationOption allocationOption = AllocationOption.None)
{
_helper = new HashMapHelper<TKey>(capacity, sizeof(TValue), (int)AlignOf<TValue>(), HashMapHelper<TKey>.MINIMAL_CAPACITY, handle, allocationOption);
_helper = new HashMapHelper<TKey>(capacity, sizeof(TValue), (int)MemoryUtility.AlignOf<TValue>(), HashMapHelper<TKey>.MINIMAL_CAPACITY, handle, allocationOption);
}
[Obsolete("Use AllocationHandle instead.")]

View File

@@ -145,7 +145,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
fixed (T* pCollection = collection)
{
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(listData->_array.GetUnsafePtr(), index), pCollection, (uint)(count * sizeof(T)));
MemoryUtility.MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(listData->_array.GetUnsafePtr(), index), pCollection, (uint)(count * sizeof(T)));
}
}
}
@@ -342,7 +342,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
fixed (T* ptr = values)
{
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(values.Length * sizeof(T)));
MemoryUtility.MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(values.Length * sizeof(T)));
}
_count += values.Length;
@@ -361,7 +361,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
Resize(Capacity + count);
}
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T)));
MemoryUtility.MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T)));
_count += count;
}
@@ -375,7 +375,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
fixed (T* pCollection = collection)
{
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), pCollection, (uint)(collection.Length * sizeof(T)));
MemoryUtility.MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), pCollection, (uint)(collection.Length * sizeof(T)));
}
_count += collection.Length;
@@ -390,7 +390,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
{
CheckNoResizeCapacity(count);
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T)));
MemoryUtility.MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T)));
_count += count;
}
@@ -409,7 +409,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
}
var copyFrom = Math.Min(start + length, _count);
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), start),
MemoryUtility.MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), start),
UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), copyFrom),
(uint)((_count - copyFrom) * sizeof(T))
);
@@ -444,7 +444,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
if (numToCopy > 0)
{
MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), start),
MemoryUtility.MemCpy(UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), start),
UnsafeUtility.ReadArrayElementUnsafe<T>(_array.GetUnsafePtr(), copyFrom),
(uint)((_count - copyFrom) * sizeof(T)));
}
@@ -519,7 +519,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
var size = Math.Min(destination.Length, Count);
fixed (T* pDest = destination)
{
MemCpy(pDest, _array.GetUnsafePtr(), (uint)(size * sizeof(T)));
MemoryUtility.MemCpy(pDest, _array.GetUnsafePtr(), (uint)(size * sizeof(T)));
}
}
@@ -540,7 +540,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
fixed (T* pDest = destination)
{
MemCpy(pDest + destinationIndex, (byte*)_array.GetUnsafePtr() + sourceIndex * sizeof(T), (nuint)(length * sizeof(T)));
MemoryUtility.MemCpy(pDest + destinationIndex, (byte*)_array.GetUnsafePtr() + sourceIndex * sizeof(T), (nuint)(length * sizeof(T)));
}
}
@@ -557,7 +557,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
fixed (T* pSrc = source)
{
MemCpy(_array.GetUnsafePtr(), pSrc, (nuint)(source.Length * sizeof(T)));
MemoryUtility.MemCpy(_array.GetUnsafePtr(), pSrc, (nuint)(source.Length * sizeof(T)));
}
}
@@ -583,7 +583,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
fixed (T* pSrc = source)
{
MemCpy((byte*)_array.GetUnsafePtr() + destinationIndex * sizeof(T), pSrc + sourceIndex, (nuint)(length * sizeof(T)));
MemoryUtility.MemCpy((byte*)_array.GetUnsafePtr() + destinationIndex * sizeof(T), pSrc + sourceIndex, (nuint)(length * sizeof(T)));
}
}

View File

@@ -121,7 +121,7 @@ public unsafe struct UnsafeMultiHashMap<TKey, TValue> : IUnsafeHashCollection<Ke
public UnsafeMultiHashMap(int capacity, AllocationHandle handle, AllocationOption allocationOption = AllocationOption.None)
{
_helper = new HashMapHelper<TKey>(capacity, sizeof(TValue), (int)AlignOf<TValue>(), HashMapHelper<TKey>.MINIMAL_CAPACITY, handle, allocationOption);
_helper = new HashMapHelper<TKey>(capacity, sizeof(TValue), (int)MemoryUtility.AlignOf<TValue>(), HashMapHelper<TKey>.MINIMAL_CAPACITY, handle, allocationOption);
}
[Obsolete("Use AllocationHandle instead.")]

View File

@@ -1,4 +1,5 @@
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -88,7 +89,7 @@ public unsafe struct UnsafeParallelQueue<T> : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static DisposablePtr<UnsafeParallelQueue<T>> Allocate(int capacityPerChunk, AllocationHandle handle, AllocationOption allocationOption = AllocationOption.None)
{
var pQueue = (UnsafeParallelQueue<T>*)handle.Alloc(SizeOf<DisposablePtr<UnsafeParallelQueue<T>>>(), AlignOf<DisposablePtr<UnsafeParallelQueue<T>>>(), AllocationOption.None);
var pQueue = (UnsafeParallelQueue<T>*)handle.Alloc(MemoryUtility.SizeOf<DisposablePtr<UnsafeParallelQueue<T>>>(), MemoryUtility.AlignOf<DisposablePtr<UnsafeParallelQueue<T>>>(), AllocationOption.None);
*pQueue = new UnsafeParallelQueue<T>(capacityPerChunk, handle, allocationOption);
return new DisposablePtr<UnsafeParallelQueue<T>>(pQueue);
}
@@ -278,7 +279,7 @@ public unsafe struct UnsafeParallelQueue<T> : IDisposable
free->consumedSlots = 0;
var slots = (ChunkSlot*)(free + 1);
MemClear(slots, (uint)(_chunkCapacity * sizeof(ChunkSlot)));
MemoryUtility.MemClear(slots, (uint)(_chunkCapacity * sizeof(ChunkSlot)));
return free;
}
}
@@ -289,7 +290,7 @@ public unsafe struct UnsafeParallelQueue<T> : IDisposable
private readonly ChunkHeader* AllocateNewChunk()
{
nuint byteSize = (nuint)sizeof(ChunkHeader) + (nuint)(_chunkCapacity * sizeof(ChunkSlot));
ChunkHeader* block = (ChunkHeader*)_allocHandle.Alloc(byteSize, AlignOf<int>(), _allocOption);
ChunkHeader* block = (ChunkHeader*)_allocHandle.Alloc(byteSize, MemoryUtility.AlignOf<int>(), _allocOption);
block->next = null;
block->nextFree = null;
@@ -299,7 +300,7 @@ public unsafe struct UnsafeParallelQueue<T> : IDisposable
block->consumedSlots = 0;
var slots = (ChunkSlot*)(block + 1);
MemClear(slots, (uint)(_chunkCapacity * sizeof(ChunkSlot)));
MemoryUtility.MemClear(slots, (uint)(_chunkCapacity * sizeof(ChunkSlot)));
return block;
}

View File

@@ -184,7 +184,7 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
{
// No wrap-around, single copy
var sizeToCopy = (uint)(_count * sizeof(T));
MemCpy(newArray.GetUnsafePtr(), (byte*)_array.GetUnsafePtr() + _offset * sizeof(T), sizeToCopy);
MemoryUtility.MemCpy(newArray.GetUnsafePtr(), (byte*)_array.GetUnsafePtr() + _offset * sizeof(T), sizeToCopy);
}
else
{
@@ -193,10 +193,10 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
var secondPartElements = _count - firstPartElements;
// Copy from _offset to the end of the old array
MemCpy(newArray.GetUnsafePtr(), (byte*)_array.GetUnsafePtr() + _offset * sizeof(T), (uint)(firstPartElements * sizeof(T)));
MemoryUtility.MemCpy(newArray.GetUnsafePtr(), (byte*)_array.GetUnsafePtr() + _offset * sizeof(T), (uint)(firstPartElements * sizeof(T)));
// Copy from the start of the old array to the remaining count
MemCpy((byte*)newArray.GetUnsafePtr() + firstPartElements * sizeof(T), _array.GetUnsafePtr(), (uint)(secondPartElements * sizeof(T)));
MemoryUtility.MemCpy((byte*)newArray.GetUnsafePtr() + firstPartElements * sizeof(T), _array.GetUnsafePtr(), (uint)(secondPartElements * sizeof(T)));
}
}