diff --git a/StgSharp.Common/HighPerformance/Memory/TwoLayerSegregatedFitAllocator.cs b/StgSharp.Common/HighPerformance/Memory/TwoLayerSegregatedFitAllocator.cs index 59a83c74..d1cc2ddf 100644 --- a/StgSharp.Common/HighPerformance/Memory/TwoLayerSegregatedFitAllocator.cs +++ b/StgSharp.Common/HighPerformance/Memory/TwoLayerSegregatedFitAllocator.cs @@ -2,8 +2,8 @@ // ----------------------------------------------------------------------- // file="TwoLayerSegregatedFitAllocator" // Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Reflection.Metadata; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -43,12 +44,13 @@ namespace StgSharp.HighPerformance.Memory private const ulong Mask48Bits = 0x0000FFFFFFFFFFFF; - private Metadata* _allocEnd; private readonly Metadata*[] _bucket; private readonly Metadata* _spareMemory; private readonly Action _freeHandle; private bool disposedValue; private readonly int _align; + + private int _allocEnd; private readonly Ptr64 _basePtr; private readonly ulong _maxAllocSize; private readonly ulong _totalSize; @@ -58,8 +60,7 @@ namespace StgSharp.HighPerformance.Memory int align, ulong maxBlockSize, Func allocator, - Action freeHandle - ) + Action freeHandle) : this(byteSize, align, maxBlockSize, (void*)allocator(byteSize, align), freeHandle) { } internal TwoLayerSegregatedFitAllocator( @@ -67,8 +68,7 @@ namespace StgSharp.HighPerformance.Memory int align, ulong maxBlockSize, void* externalPointer, - Action freeHandle - ) + Action freeHandle) { _totalSize = byteSize; _basePtr = (Ptr64)(ulong)externalPointer; @@ -77,7 +77,7 @@ namespace StgSharp.HighPerformance.Memory _bucket = new Metadata*[58 - BitOperations.LeadingZeroCount(_maxAllocSize)]; _spareMemory = &((Metadata*)(ulong)(_basePtr + _totalSize))[-1]; _freeHandle = freeHandle ?? (static_ => { }); - _allocEnd = _spareMemory; + _allocEnd = 0; // init spare memory node @@ -89,37 +89,23 @@ namespace StgSharp.HighPerformance.Memory _spareMemory->PreviousNear = 0; } - public TwoLayerSegregatedFitAllocator( - nuint byteSize - ) + public TwoLayerSegregatedFitAllocator(nuint byteSize) : this(byteSize, 16, 32U * 1024U * 1024U, NativeMemory.AlignedAlloc(byteSize, 16), ptr => NativeMemory.AlignedFree((void*)ptr)) { } - public TwoLayerSegregatedFitAllocator( - nuint byteSize, - uint maxBlockSize - ) + public TwoLayerSegregatedFitAllocator(nuint byteSize, uint maxBlockSize) : this(byteSize, 16, maxBlockSize, NativeMemory.AlignedAlloc(byteSize, 16), ptr => NativeMemory.AlignedFree((void*)ptr)) { } - public TwoLayerSegregatedFitAllocator( - nuint byteSize, - int align - ) + public TwoLayerSegregatedFitAllocator(nuint byteSize, int align) : this(byteSize, align, 32U * 1024U * 1024U, NativeMemory.AlignedAlloc(byteSize, 16), ptr => NativeMemory.AlignedFree((void*)ptr)) { } - public TwoLayerSegregatedFitAllocator( - nuint byteSize, - int align, - nuint maxBlockSize - ) + public TwoLayerSegregatedFitAllocator(nuint byteSize, int align, nuint maxBlockSize) : this(byteSize, align, maxBlockSize, NativeMemory.AlignedAlloc(byteSize, 16), ptr => NativeMemory.AlignedFree((void*)ptr)) { } - public Handle Alloc( - nuint size - ) + public Handle Alloc(nuint size) { ulong allocSize = nuint.Max(64, (~64U) & (size + 63)); if (allocSize > _maxAllocSize) { @@ -136,11 +122,11 @@ namespace StgSharp.HighPerformance.Memory break; } } - if (entry is null) - { - // alloc new from spare + if (entry is null && !TryGetNewMetadata(allocSize, out entry)) { + throw new OverflowException("No available "); } ulong remain = entry->Size - allocSize; + throw new NotImplementedException(); } @@ -150,16 +136,12 @@ namespace StgSharp.HighPerformance.Memory GC.SuppressFinalize(this); } - public void Free( - Handle handle - ) + public void Free(Handle handle) { throw new NotImplementedException(); } - protected virtual void Dispose( - bool disposing - ) + protected virtual void Dispose(bool disposing) { if (!disposedValue) { @@ -171,12 +153,49 @@ namespace StgSharp.HighPerformance.Memory } } + private bool TryGetNewMetadata(ulong size, out Metadata* meta) + { + int idx = _spareMemory->NextLevel; + if (idx != 0) + { + meta = &_spareMemory[-idx]; + _spareMemory->NextLevel = meta->NextLevel; + return true; + } + ulong spareSize = _spareMemory->Size; + if (spareSize < 32UL + size) + { + meta = null; + return false; + } + _allocEnd++; + meta = &_spareMemory[-_allocEnd]; + spareSize -= 32UL - size; + _spareMemory->Size = spareSize; + _spareMemory->Position += size; + meta->Size = size; + return true; + } + [StructLayout(LayoutKind.Sequential)] - public struct Handle + public readonly struct Handle { - internal readonly Metadata* Meta; + internal readonly Metadata* _meta; public readonly void* Pointer; + public readonly Ptr64 Size; + + internal Handle(Metadata* meta, Ptr64 baseAddress) + { + _meta = meta; + Pointer = (void*)(ulong)(meta->Position + baseAddress); + Size = meta->Size; + } + + [Obsolete("You should not create instance from default. Alloc from allocator please")] + public Handle() { } + + public ref byte this[int offset] => ref ((byte*)Pointer)[offset]; } @@ -207,6 +226,12 @@ namespace StgSharp.HighPerformance.Memory set => SizeMask = (SizeMask & ~Mask48Bits) | ((ulong)value & Mask48Bits); } + public Ptr64 SizeForSpare + { + get => SizeMask; + set => SizeMask = value; + } + public static uint SizeOf { get; } = (uint)Unsafe.SizeOf(); }