This commit is contained in:
Nitload
2025-08-25 09:50:30 +08:00
parent bd0e31e922
commit 1359ff4ecc
1630 changed files with 738486 additions and 2399 deletions
@@ -57,10 +57,13 @@ namespace StgSharp.HighPerformance.Memory
int segmentIndex = DetermineSegmentIndex(size, level);
int i = level, s = segmentIndex;
if (TryPopLevelForAllocation(i, s, out Entry* handle)) {
if (TryPopLevelForAllocation(i, s, out Entry* handle))
{
SetEntryState(handle, EntryState.Allocated);
return new hlsfHandle(handle, size);
}
fallback:
i = level;
s = segmentIndex;
while (!TryPopLevelForAllocation(i, s, out handle))
@@ -76,115 +79,146 @@ namespace StgSharp.HighPerformance.Memory
throw new OverflowException("Out of memory: Unable to allocate new 16MB block or find suitable bucket for allocation.");
}
break;
Thread.Sleep(0);
goto fallback;
}
}
if (handle != null) {
SliceMemory(handle, (segmentIndex + 1) * levelSizeArray[level]);
}
try
{
if (handle != null)
{
AcquireEntryNextLock(handle);
SliceMemory(handle, (segmentIndex + 1) * levelSizeArray[level]);
SetEntryState(handle, EntryState.Allocated);
}
return new hlsfHandle(handle, size);
return new hlsfHandle(handle, size);
}
finally
{
ReleaseEntryNextLock(handle);
}
}
private void SliceMemory(Entry* e, int offset)
{
Entry* current = e;
ulong n = e->NextNear;
Entry* next = (Entry*)n;
Entry* next = e;
ulong originOffset = e->Position - (ulong)m_Buffer;
ulong finalOffset = originOffset + (ulong)offset;
ulong end = e->Position + e->Size - (ulong)m_Buffer;
int remainSize = (int)(e->Size - offset);
if ((originOffset & 63) != 0) {
throw new InvalidOperationException("Entry position offset is not aligned to 64 bytes.");
}
AcquireEntryNextLock(e);
AcquireEntryPrevLock(next);
int minLevel = Math.Max((BitOperations.TrailingZeroCount(finalOffset) - 6) / 2, 0);
int i = minLevel >= levelSizeArray.Length ? levelSizeArray.Length - 1 : minLevel;
for (; i < levelSizeArray.Length; i++)
try
{
int levelSize = levelSizeArray[i];
ulong board = (finalOffset + (ulong)levelSize - 1) & ~((ulong)levelSize - 1);
int blockCount = (int)((ulong.Min(board, end) - board) / (ulong)levelSize);
if (blockCount == 0)
if ((originOffset & 63) != 0) {
throw new InvalidOperationException("Entry position offset is not aligned to 64 bytes.");
}
int minLevel = Math.Max((BitOperations.TrailingZeroCount(originOffset) - 6) / 2, 0);
int i = minLevel >= levelSizeArray.Length ? levelSizeArray.Length - 1 : minLevel;
for (; i < levelSizeArray.Length; i++)
{
break;
}
int s = blockCount * levelSize;
int levelSize = levelSizeArray[i];
int blockCount = remainSize / levelSize % 4;
if (blockCount == 0)
{
break;
}
int s = blockCount * levelSize;
// create and init new entry
Entry* newEntry = (Entry*)_entries.Allocate();
newEntry->Position = (nuint)((ulong)m_Buffer + finalOffset);
newEntry->Size = (uint)s;
BucketNode* bucket = (BucketNode*)newEntry->Position;
bucket->EntryRef = newEntry;
// create and init new entry
Entry* newEntry = (Entry*)_entries.Allocate();
newEntry->Position = (nuint)((ulong)m_Buffer + finalOffset);
newEntry->Size = (uint)s;
newEntry->LockBuffer = 0;
BucketNode* bucket = (BucketNode*)newEntry->Position;
bucket->EntryRef = newEntry;
bucket->LockBuffer = 0;
newEntry->State = EntryState.ThreadOccupied;
// link new entry
newEntry->PreviousNear = (ulong)current;
newEntry->NextNear = n;
current->NextNear = (ulong)newEntry;
if (next != null) {
// link new entry
newEntry->PreviousNear = (ulong)current;
newEntry->NextNear = n;
current->NextNear = (ulong)newEntry;
next->PreviousNear = (ulong)newEntry;
newEntry->Level = i;
PushLevel(i, blockCount - 1, bucket);
// set new entry
Entry* old = current;
current = newEntry;
// update lock and data
finalOffset += (ulong)s;
remainSize -= s;
ReleaseEntryNextLock(old);
AcquireEntryNextLock(current);
}
newEntry->Level = i;
PushLevel(i, blockCount - 1, bucket);
// set new entry
current = newEntry;
// update data
finalOffset += (ulong)s;
remainSize -= s;
}
if (remainSize <= 0) {
return;
}
for (i -= 1; i >= 0; i--)
{
int levelSize = levelSizeArray[i];
ulong board = (finalOffset + (ulong)levelSize - 1) & ~((ulong)levelSize - 1);
int blockCount = (int)((ulong.Min(board, end) - finalOffset) / (ulong)levelSize);
if (blockCount == 0)
{
continue;
}
int s = blockCount * levelSize;
// create and init new entry
Entry* newEntry = (Entry*)_entries.Allocate();
newEntry->Position = (nuint)((ulong)m_Buffer + finalOffset);
newEntry->Size = (uint)s;
BucketNode* bucket = (BucketNode*)newEntry->Position;
bucket->EntryRef = newEntry;
// link new entry
newEntry->PreviousNear = (ulong)current;
newEntry->NextNear = n;
current->NextNear = (ulong)newEntry;
if (next != null) {
next->PreviousNear = (ulong)newEntry;
}
newEntry->Level = i;
PushLevel(i, blockCount - 1, bucket);
// set new entry
current = newEntry;
// update data
finalOffset += (ulong)s;
remainSize -= s;
if (remainSize <= 0)
{
break;
ReleaseEntryNextLock(current);
ReleaseEntryPrevLock(next);
return;
}
for (; i >= 0; i--)
{
int levelSize = levelSizeArray[i];
int blockCount = remainSize / levelSize % 4;
if (blockCount == 0)
{
continue;
}
int s = blockCount * levelSize;
// create and init new entry
Entry* newEntry = (Entry*)_entries.Allocate();
newEntry->LockBuffer = 0;
newEntry->Position = (nuint)((ulong)m_Buffer + finalOffset);
newEntry->Size = (uint)s;
BucketNode* bucket = (BucketNode*)newEntry->Position;
bucket->EntryRef = newEntry;
bucket->LockBuffer = 0;
newEntry->State = EntryState.ThreadOccupied;
// link new entry
newEntry->PreviousNear = (ulong)current;
current->NextNear = (ulong)newEntry;
newEntry->NextNear = n;
next->PreviousNear = (ulong)newEntry;
newEntry->Level = i;
PushLevel(i, blockCount - 1, bucket);
// set new entry
Entry* old = current;
current = newEntry;
// update lock and data
finalOffset += (ulong)s;
remainSize -= s;
ReleaseEntryNextLock(old);
AcquireEntryNextLock(current);
if (remainSize <= 0)
{
break;
}
}
}
catch (Exception)
{
throw;
}
finally
{
// Release locks in reverse order
ReleaseEntryNextLock(current);
ReleaseEntryPrevLock(next);
}
}
@@ -199,13 +233,22 @@ namespace StgSharp.HighPerformance.Memory
/// </returns>
private bool TryAllocateNew16MBBlock(out Entry* handle)
{
nuint pos = _spareMemory->Position;
nuint pos = Volatile.Read(ref _spareMemory->Position);
nuint blockSize = (nuint)levelSizeArray[^1] * 2; // Use last level size (16MB)
nuint newPos = pos + blockSize;
ulong p = _spareMemory->PreviousNear;
Entry* previous = (Entry*)p;
ulong p;
Entry* previous;
do
{
p = Volatile.Read(ref _spareMemory->PreviousNear);
previous = (Entry*)p;
if (previous != null) {
AcquireEntryNextLock(previous);
}
AcquireEntryPrevLock(_spareMemory);
break;
} while (true);
if (_spareMemory->Size <= 0)
{
handle = null;
@@ -220,25 +263,42 @@ namespace StgSharp.HighPerformance.Memory
}
// Try to allocate new Entry from slab allocator
handle = (Entry*)_entries.Allocate();
handle->Position = pos;
handle->Size = (uint)blockSize;
handle->Level = GetLevelFromSize((uint)blockSize);
try
{
handle = (Entry*)_entries.Allocate();
handle->Position = pos;
handle->Size = (uint)blockSize;
SetEntryState(handle, EntryState.ThreadOccupied);
handle->Level = GetLevelFromSize((uint)blockSize);
// Update spare memory position
_spareMemory->Position = newPos;
BucketNode* b = (BucketNode*)handle->Position;
b->EntryRef = handle;
PushLevel(handle->Level, DetermineSegmentIndex((uint)blockSize, handle->Level), b);
handle->PrevLock = 0;
handle->NextLock = 0;
// update position linked list
handle->NextNear = (ulong)_spareMemory;
handle->PreviousNear = p;
_spareMemory->PreviousNear = (ulong)handle;
if (previous != null) {
previous->NextNear = (ulong)handle;
// Update spare memory position
_spareMemory->Position = newPos;
BucketNode* b = (BucketNode*)handle->Position;
b->EntryRef = handle;
PushLevel(handle->Level, DetermineSegmentIndex((uint)blockSize, handle->Level), b);
// update position linked list
handle->NextNear = (ulong)_spareMemory;
handle->PreviousNear = p;
_spareMemory->PreviousNear = (ulong)handle;
if (previous != null) {
previous->NextNear = (ulong)handle;
}
return true;
}
catch
{
handle = null;
return false;
}
finally
{
ReleaseEntryNextLock(previous);
ReleaseEntryPrevLock(_spareMemory);
}
return true;
}
/// <summary>