hlsf error is solving
This commit is contained in:
@@ -77,21 +77,14 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
throw new OverflowException("Out of memory: insufficient block size returned from spare memory.");
|
throw new OverflowException("Out of memory: insufficient block size returned from spare memory.");
|
||||||
}
|
}
|
||||||
long remainder = handle->Size - requestedOffset;
|
long remainder = handle->Size - requestedOffset;
|
||||||
if (remainder > 0)
|
SetEntryLevel(handle, handle->Position, (uint)requestedOffset);
|
||||||
{
|
|
||||||
Entry* extra = (Entry*)_entries.Allocate();
|
|
||||||
extra->Position = handle->Position + (nuint)requestedOffset;
|
|
||||||
extra->Size = (uint)remainder;
|
|
||||||
extra->State = EntryState.Empty;
|
|
||||||
extra->NextNear = handle->NextNear;
|
|
||||||
extra->PreviousNear = handle;
|
|
||||||
extra->NextNear->PreviousNear = extra;
|
|
||||||
extra->PreviousNear->NextNear = extra;
|
|
||||||
SliceMemory(extra);
|
|
||||||
}
|
|
||||||
handle->State = EntryState.Alloc;
|
handle->State = EntryState.Alloc;
|
||||||
handle->Size = requestedOffset;
|
if (remainder > 0) {
|
||||||
handle->Level = level;
|
SliceMemory(handle->NextNear, remainder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (handle->PreviousNear == null || handle->NextNear == null) {
|
||||||
|
throw new HLSFPositionChainBreakException();
|
||||||
}
|
}
|
||||||
return new hlsfHandle(handle, size);
|
return new hlsfHandle(handle, size);
|
||||||
}
|
}
|
||||||
@@ -103,14 +96,15 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
/// <param name="e">
|
/// <param name="e">
|
||||||
///
|
///
|
||||||
/// </param>
|
/// </param>
|
||||||
private void SliceMemory(Entry* e)
|
/// <param name="sizeToSlice">
|
||||||
|
///
|
||||||
|
/// </param>
|
||||||
|
private void SliceMemory(Entry* e, long sizeToSlice)
|
||||||
{
|
{
|
||||||
Entry* cur = e->PreviousNear;
|
Entry* next = e;
|
||||||
Entry* next = e->NextNear;
|
long remain = sizeToSlice; // remained size to slice
|
||||||
long remain = e->Size;
|
long offset = (long)e->Position - sizeToSlice - (long)m_Buffer; // offset of buffer to slice
|
||||||
long offset = (long)e->Position - (long)m_Buffer;
|
long end = (long)e->Position - (long)m_Buffer; // end offset of buffer to slice
|
||||||
long end = offset + remain;
|
|
||||||
_entries.Free((nuint)e);
|
|
||||||
|
|
||||||
int i = (BitOperations.TrailingZeroCount(remain) - 6) / 2;
|
int i = (BitOperations.TrailingZeroCount(remain) - 6) / 2;
|
||||||
i = int.Min(10, i);
|
i = int.Min(10, i);
|
||||||
@@ -125,21 +119,15 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
int newSize = count * size;
|
int newSize = count * size;
|
||||||
|
|
||||||
Entry* newEntry = (Entry*)_entries.Allocate();
|
Entry* newEntry = (Entry*)_entries.Allocate();
|
||||||
newEntry->PreviousNear = cur;
|
InsertEntryBefore(newEntry, next);
|
||||||
newEntry->NextNear = next;
|
SetEntryLevel(newEntry, (nuint)offset + (nuint)m_Buffer, newSize);
|
||||||
cur->NextNear = newEntry;
|
|
||||||
next->PreviousNear = newEntry;
|
|
||||||
newEntry->Position = (nuint)offset + (nuint)m_Buffer;
|
|
||||||
newEntry->State = EntryState.Empty;
|
newEntry->State = EntryState.Empty;
|
||||||
newEntry->Size = (uint)newSize;
|
|
||||||
newEntry->Level = i;
|
|
||||||
|
|
||||||
BucketNode* b = (BucketNode*)newEntry->Position;
|
BucketNode* b = (BucketNode*)newEntry->Position;
|
||||||
b->EntryRef = newEntry;
|
b->EntryRef = newEntry;
|
||||||
PushLevel(i, count - 1, b);
|
PushBucketToLevel(i, count - 1, b);
|
||||||
offset += newSize;
|
offset += newSize;
|
||||||
remain -= (long)newSize;
|
remain -= newSize;
|
||||||
cur = newEntry;
|
|
||||||
}
|
}
|
||||||
if (remain <= 0) {
|
if (remain <= 0) {
|
||||||
return;
|
return;
|
||||||
@@ -157,19 +145,13 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
int newSize = count * upper;
|
int newSize = count * upper;
|
||||||
|
|
||||||
Entry* newEntry = (Entry*)_entries.Allocate();
|
Entry* newEntry = (Entry*)_entries.Allocate();
|
||||||
newEntry->PreviousNear = cur;
|
InsertEntryBefore(newEntry, next);
|
||||||
newEntry->NextNear = next;
|
SetEntryLevel(newEntry, (nuint)offset + (nuint)m_Buffer, newSize);
|
||||||
cur->NextNear = newEntry;
|
|
||||||
next->PreviousNear = newEntry;
|
|
||||||
newEntry->Position = (nuint)offset + (nuint)m_Buffer;
|
|
||||||
newEntry->State = EntryState.Empty;
|
newEntry->State = EntryState.Empty;
|
||||||
newEntry->Size = (uint)newSize;
|
|
||||||
newEntry->Level = i;
|
|
||||||
|
|
||||||
BucketNode* b = (BucketNode*)newEntry->Position;
|
BucketNode* b = (BucketNode*)newEntry->Position;
|
||||||
b->EntryRef = newEntry;
|
b->EntryRef = newEntry;
|
||||||
PushLevel(i, count - 1, b);
|
PushBucketToLevel(i, count - 1, b);
|
||||||
cur = newEntry;
|
|
||||||
offset += newSize;
|
offset += newSize;
|
||||||
remain -= (long)newSize;
|
remain -= (long)newSize;
|
||||||
if (remain <= 0) {
|
if (remain <= 0) {
|
||||||
@@ -188,22 +170,15 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
int newSize = count * size;
|
int newSize = count * size;
|
||||||
|
|
||||||
Entry* newEntry = (Entry*)_entries.Allocate();
|
Entry* newEntry = (Entry*)_entries.Allocate();
|
||||||
newEntry->PreviousNear = cur;
|
InsertEntryBefore(newEntry, next);
|
||||||
newEntry->NextNear = next;
|
SetEntryLevel(newEntry, (nuint)offset + (nuint)m_Buffer, newSize);
|
||||||
cur->NextNear = newEntry;
|
|
||||||
next->PreviousNear = newEntry;
|
|
||||||
newEntry->Position = (nuint)offset + (nuint)m_Buffer;
|
|
||||||
newEntry->State = EntryState.Empty;
|
newEntry->State = EntryState.Empty;
|
||||||
newEntry->Size = (uint)newSize;
|
|
||||||
newEntry->Level = i;
|
|
||||||
|
|
||||||
BucketNode* b = (BucketNode*)newEntry->Position;
|
BucketNode* b = (BucketNode*)newEntry->Position;
|
||||||
b->EntryRef = newEntry;
|
b->EntryRef = newEntry;
|
||||||
b->NextLevel = null;
|
b->NextLevel = null;
|
||||||
b->PreviousLevel = null;
|
b->PreviousLevel = null;
|
||||||
PushLevel(i, count - 1, b);
|
PushBucketToLevel(i, count - 1, b);
|
||||||
|
|
||||||
cur = newEntry;
|
|
||||||
offset += newSize;
|
offset += newSize;
|
||||||
remain -= (long)newSize;
|
remain -= (long)newSize;
|
||||||
}
|
}
|
||||||
@@ -236,20 +211,15 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
|
|
||||||
// build new entry
|
// build new entry
|
||||||
Entry* e = (Entry*)_entries.Allocate();
|
Entry* e = (Entry*)_entries.Allocate();
|
||||||
e->Position = pos;
|
SetEntryLevel(e, pos, size);
|
||||||
e->Size = size;
|
InsertEntryBefore(e, _spareMemory);
|
||||||
Entry* prev = _spareMemory->PreviousNear;
|
|
||||||
e->NextNear = _spareMemory;
|
|
||||||
e->PreviousNear = prev;
|
|
||||||
prev->NextNear = e;
|
|
||||||
_spareMemory->PreviousNear = e;
|
|
||||||
e->State = EntryState.Empty;
|
e->State = EntryState.Empty;
|
||||||
e->Level = GetLevelFromSize(size);
|
|
||||||
|
|
||||||
// set fields of spare memory
|
// set fields of spare memory
|
||||||
_spareMemory->Size -= size;
|
_spareMemory->Size -= size;
|
||||||
_spareMemory->Position += (nuint)size;
|
_spareMemory->Position += (nuint)size;
|
||||||
|
|
||||||
|
|
||||||
handle = e;
|
handle = e;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
public unsafe partial class HybridLayerSegregatedFitAllocator
|
public unsafe partial class HybridLayerSegregatedFitAllocator
|
||||||
{
|
{
|
||||||
|
|
||||||
private void PushLevel(int levelIndex, int sizeIndex, BucketNode* node)
|
private void PushBucketToLevel(int levelIndex, int sizeIndex, BucketNode* node)
|
||||||
{
|
{
|
||||||
if (node == null || node->EntryRef == null) {
|
if (node == null || node->EntryRef == null) {
|
||||||
return;
|
return;
|
||||||
@@ -68,25 +68,6 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private void RemoveFromBucket(BucketNode* node)
|
|
||||||
{
|
|
||||||
BucketNode* previous = node->PreviousLevel;
|
|
||||||
BucketNode* next = node->NextLevel;
|
|
||||||
|
|
||||||
if (previous != null) {
|
|
||||||
previous->NextLevel = next;
|
|
||||||
}
|
|
||||||
if (next != null) {
|
|
||||||
next->PreviousLevel = previous;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->NextLevel = (BucketNode*)null;
|
|
||||||
node->PreviousLevel = (BucketNode*)null;
|
|
||||||
node->IsInBucket = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void RemoveFromBucket(int levelIndex, int sizeIndex, BucketNode* node)
|
private void RemoveFromBucket(int levelIndex, int sizeIndex, BucketNode* node)
|
||||||
{
|
{
|
||||||
@@ -97,7 +78,6 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BucketNode* previous = node->PreviousLevel;
|
BucketNode* previous = node->PreviousLevel;
|
||||||
BucketNode* next = node->NextLevel;
|
BucketNode* next = node->NextLevel;
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,42 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DumpPositionChain(bool singleStep = false, int maxCount = 4096)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Entry* cur = _spareMemory;
|
||||||
|
int cnt = 0;
|
||||||
|
if (cur != null) {
|
||||||
|
cur = cur->NextNear;
|
||||||
|
}
|
||||||
|
Console.WriteLine(EntryToString(_spareMemory));
|
||||||
|
while (cur != null && cur != _spareMemory && cnt < maxCount)
|
||||||
|
{
|
||||||
|
Console.WriteLine(EntryToString(cur));
|
||||||
|
cnt++;
|
||||||
|
if (singleStep) {
|
||||||
|
Console.ReadKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = cur->NextNear;
|
||||||
|
}
|
||||||
|
if (cur == _spareMemory)
|
||||||
|
{
|
||||||
|
Console.WriteLine("(reached sentinel)");
|
||||||
|
} else if (cnt >= maxCount) {
|
||||||
|
Console.WriteLine("(stopped at maxCount)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[DumpPositionChain-forward] Exception: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<string> ShowEntryLayout()
|
public IEnumerable<string> ShowEntryLayout()
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
@@ -80,7 +116,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
private static string EntryToString(Entry* e)
|
private static string EntryToString(Entry* e)
|
||||||
{
|
{
|
||||||
BucketNode* b = (BucketNode*)e->Position;
|
BucketNode* b = (BucketNode*)e->Position;
|
||||||
return $"{(ulong)e->PreviousNear}<-- Position{(ulong)e} Bucket:{{{(ulong)e->Position},{e->Level},{e->Size}}} -->{(ulong)e->NextNear}";
|
return $"{(ulong)e->PreviousNear}<-prev- Position:{(ulong)e} Bucket:{{{(ulong)e->Position},{e->Level},{e->Size}}} -next->{(ulong)e->NextNear}";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,27 +49,28 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
public void Collect()
|
public void Collect()
|
||||||
{
|
{
|
||||||
Entry* cur = _spareMemory->NextNear;
|
Entry* cur = _spareMemory->NextNear;
|
||||||
|
long size = 0;
|
||||||
while (cur != null && cur != _spareMemory)
|
while (cur != null && cur != _spareMemory)
|
||||||
{
|
{
|
||||||
|
// cur is not empty, skip
|
||||||
if (cur->State != EntryState.Empty)
|
if (cur->State != EntryState.Empty)
|
||||||
{
|
{
|
||||||
cur = cur->NextNear;
|
cur = cur->NextNear;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RemoveFromBucket(cur->Level, DetermineSegmentIndex(cur->Size, cur->Level), (BucketNode*)cur->Position);
|
|
||||||
Entry* next = cur->NextNear;
|
|
||||||
|
|
||||||
while (next is not null &&
|
// remove cur from bucket
|
||||||
next->State == EntryState.Empty &&
|
do
|
||||||
AssertAdjacentTo(cur, next))
|
|
||||||
{
|
{
|
||||||
RemoveFromBucket(next->Level, DetermineSegmentIndex(next->Size, next->Level), (BucketNode*)next->Position);
|
size += cur->Size;
|
||||||
cur->Size += next->Size;
|
Entry* next = cur->NextNear;
|
||||||
RemoveFromPositionChain(next);
|
RemoveFromBucket(cur->Level, DetermineSegmentIndex(cur->Size, cur->Level), (BucketNode*)cur->Position);
|
||||||
next = cur->NextNear;
|
RemoveFromPositionChain(cur);
|
||||||
}
|
|
||||||
SliceMemory(cur);
|
|
||||||
cur = next;
|
cur = next;
|
||||||
|
} while (cur != null && cur != _spareMemory && cur->State == EntryState.Empty);
|
||||||
|
if (size > 0) {
|
||||||
|
SliceMemory(cur, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +109,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
int finalSegment = DetermineSegmentIndex(finalSize, finalLevel);
|
int finalSegment = DetermineSegmentIndex(finalSize, finalLevel);
|
||||||
|
|
||||||
// Push the merged entry back to appropriate bucket
|
// Push the merged entry back to appropriate bucket
|
||||||
PushLevel(finalLevel, finalSegment, (BucketNode*)e->Position);
|
PushBucketToLevel(finalLevel, finalSegment, (BucketNode*)e->Position);
|
||||||
|
|
||||||
// Console.WriteLine("one block freed");
|
// Console.WriteLine("one block freed");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,13 +60,13 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private int GetLevelFromSize(long size)
|
private static int GetLevelFromSize(long size)
|
||||||
{
|
{
|
||||||
return GetLevelFromSize((uint)size);
|
return GetLevelFromSize((uint)size);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private int GetLevelFromSize(uint size)
|
private static int GetLevelFromSize(uint size)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Level sizes: [64, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216]
|
* Level sizes: [64, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216]
|
||||||
|
|||||||
@@ -61,12 +61,32 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
/// Determine segment index based on size and originLevel
|
/// Determine segment index based on size and originLevel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private int DetermineSegmentIndex(long size, int level)
|
private static int DetermineSegmentIndex(long size, int level)
|
||||||
{
|
{
|
||||||
level = int.Min(level, MaxLevel);
|
level = int.Min(level, MaxLevel);
|
||||||
return (int)((size - 1) / levelSizeArray[level]);
|
return (int)((size - 1) / levelSizeArray[level]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void InsertEntryAfter(Entry* entry, Entry* position)
|
||||||
|
{
|
||||||
|
Entry* next = position->NextNear;
|
||||||
|
entry->NextNear = next;
|
||||||
|
entry->PreviousNear = position;
|
||||||
|
next->PreviousNear = entry;
|
||||||
|
position->NextNear = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void InsertEntryBefore(Entry* entry, Entry* position)
|
||||||
|
{
|
||||||
|
Entry* prev = position->PreviousNear;
|
||||||
|
entry->NextNear = position;
|
||||||
|
entry->PreviousNear = prev;
|
||||||
|
prev->NextNear = entry;
|
||||||
|
position->PreviousNear = entry;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used in Free operations, efficiently remove from buckets and merge adjacent blocks.
|
/// Used in Free operations, efficiently remove from buckets and merge adjacent blocks.
|
||||||
/// Current Entry will serve as the final merged block. The Merge will be in lazy
|
/// Current Entry will serve as the final merged block. The Merge will be in lazy
|
||||||
@@ -74,12 +94,52 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void MergeAndRemoveFromBuckets(Entry* entry)
|
private void MergeAndRemoveFromBuckets(Entry* entry)
|
||||||
{
|
{
|
||||||
// TODO 后续提供HLSF.Collect全量整理API,从头遍历邻接块进行彻底的合并
|
if (entry == null) {
|
||||||
if (entry == null)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Console.WriteLine("============ Merge start =======================");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("forward from entry");
|
||||||
|
Entry* __cur = entry;
|
||||||
|
int __cnt = 0;
|
||||||
|
while (__cur != null && __cur != _spareMemory && __cnt < 512)
|
||||||
|
{
|
||||||
|
Console.WriteLine(EntryToString(__cur));
|
||||||
|
__cur = __cur->NextNear;
|
||||||
|
__cnt++;
|
||||||
|
if (__cur == entry)
|
||||||
|
{
|
||||||
|
Console.WriteLine("(looped back to start)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.WriteLine(EntryToString(__cur));
|
||||||
|
Console.WriteLine("MergeAndRemoveFromBuckets: backward from entry");
|
||||||
|
__cur = entry;
|
||||||
|
__cnt = 0;
|
||||||
|
while (__cur != null && __cur != _spareMemory && __cnt < 512)
|
||||||
|
{
|
||||||
|
Console.WriteLine(EntryToString(__cur));
|
||||||
|
__cur = __cur->PreviousNear;
|
||||||
|
__cnt++;
|
||||||
|
if (__cur == entry)
|
||||||
|
{
|
||||||
|
Console.WriteLine("(looped back to start)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.WriteLine(EntryToString(__cur));
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Console.WriteLine("==========================================");
|
||||||
|
}
|
||||||
|
/**/
|
||||||
|
|
||||||
long size = entry->Size;
|
long size = entry->Size;
|
||||||
int originLevel = entry->Level;
|
int originLevel = entry->Level;
|
||||||
int segment = DetermineSegmentIndex(size, originLevel);
|
int segment = DetermineSegmentIndex(size, originLevel);
|
||||||
@@ -88,8 +148,8 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
// previous direction merge
|
// previous direction merge
|
||||||
Entry* p = entry->PreviousNear;
|
Entry* p = entry->PreviousNear;
|
||||||
if (p == null ||
|
if (p == null ||
|
||||||
|
p == _spareMemory ||
|
||||||
p->State != EntryState.Empty ||
|
p->State != EntryState.Empty ||
|
||||||
!AssertAdjacentTo(entry, p) ||
|
|
||||||
p->Level != entry->Level ||
|
p->Level != entry->Level ||
|
||||||
!AssertBoundary(p, entry, originLevel))
|
!AssertBoundary(p, entry, originLevel))
|
||||||
{
|
{
|
||||||
@@ -108,8 +168,8 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
// next direction merge
|
// next direction merge
|
||||||
Entry* n = entry->NextNear;
|
Entry* n = entry->NextNear;
|
||||||
if (n == null ||
|
if (n == null ||
|
||||||
|
n == _spareMemory ||
|
||||||
n->State != EntryState.Empty ||
|
n->State != EntryState.Empty ||
|
||||||
!AssertAdjacentTo(entry, n) ||
|
|
||||||
n->Level != entry->Level ||
|
n->Level != entry->Level ||
|
||||||
!AssertBoundary(n, entry, originLevel))
|
!AssertBoundary(n, entry, originLevel))
|
||||||
{
|
{
|
||||||
@@ -149,6 +209,14 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
_entries.Free((nuint)entry);
|
_entries.Free((nuint)entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void SetEntryLevel(Entry* entry, nuint position, long size)
|
||||||
|
{
|
||||||
|
entry ->Position = position;
|
||||||
|
entry->Size = size;
|
||||||
|
entry->Level = GetLevelFromSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Entry structure - streamlined version (only position and state information) Stored in
|
/// Entry structure - streamlined version (only position and state information) Stored in
|
||||||
/// external SLAB
|
/// external SLAB
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Bucket system field - directly in main allocator class
|
// Bucket system field - directly in main allocator class
|
||||||
private BucketNode*[] _bucketHeads;
|
private readonly BucketNode*[] _bucketHeads;
|
||||||
|
|
||||||
// _spareMemory is also the beginning position of allocator
|
// _spareMemory is also the beginning position of allocator
|
||||||
private Entry* _spareMemory;
|
private Entry* _spareMemory;
|
||||||
@@ -64,7 +64,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
_spareMemory->PreviousNear = _spareMemory;
|
_spareMemory->PreviousNear = _spareMemory;
|
||||||
_spareMemory->NextNear = _spareMemory;
|
_spareMemory->NextNear = _spareMemory;
|
||||||
_spareMemory->Position = (nuint)m_Buffer;
|
_spareMemory->Position = (nuint)m_Buffer;
|
||||||
_spareMemory->Size = (uint)byteSize;
|
_spareMemory->Size = (long)byteSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HybridLayerSegregatedFitAllocator(nuint byteSize, int align)
|
public HybridLayerSegregatedFitAllocator(nuint byteSize, int align)
|
||||||
@@ -85,7 +85,7 @@ namespace StgSharp.HighPerformance.Memory
|
|||||||
_spareMemory->PreviousNear = _spareMemory;
|
_spareMemory->PreviousNear = _spareMemory;
|
||||||
_spareMemory->NextNear = _spareMemory;
|
_spareMemory->NextNear = _spareMemory;
|
||||||
_spareMemory->Position = (nuint)m_Buffer;
|
_spareMemory->Position = (nuint)m_Buffer;
|
||||||
_spareMemory->Size = (uint)byteSize;
|
_spareMemory->Size = (long)byteSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ namespace StgSharp
|
|||||||
uint size = sz > MaxAllocSize ? MaxAllocSize : sz;
|
uint size = sz > MaxAllocSize ? MaxAllocSize : sz;
|
||||||
BenchAllocThroughput(allocator, size, touch:false);
|
BenchAllocThroughput(allocator, size, touch:false);
|
||||||
allocator.Collect();
|
allocator.Collect();
|
||||||
|
allocator.DumpPositionChain();
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
GC.WaitForPendingFinalizers();
|
GC.WaitForPendingFinalizers();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user