hlsf gong on rewrite again

This commit is contained in:
Youmu Liu
2025-11-27 20:13:09 +08:00
parent 83537c7be7
commit a3570bf20a
7 changed files with 267 additions and 242 deletions
@@ -37,47 +37,13 @@ namespace StgSharp.HighPerformance.Memory
/// <summary>
/// check out if a bucket is within the same higher-level boundary as currentOffset
/// </summary>
/// <param name="currentOffset">
///
/// </param>
/// <param name="target">
///
/// </param>
/// <param name="level">
///
/// </param>
/// <returns>
///
/// </returns>
private bool AssertBackwardBoundary(ulong currentOffset, Entry* target, int level)
private bool AssertBoundary(Entry* previous, Entry* current, int level)
{
level = int.Min(level, MaxLevel);
int nextLevelSize = levelSizeArray[level] * 4;
ulong targetHead = target->Position - (ulong)m_Buffer;
return (currentOffset / (ulong)nextLevelSize) == (targetHead / (ulong)nextLevelSize);
}
/// <summary>
/// check out if a bucket is within the same higher-level boundary as currentOffset
/// </summary>
/// <param name="currentOffset">
///
/// </param>
/// <param name="target">
///
/// </param>
/// <param name="level">
///
/// </param>
/// <returns>
///
/// </returns>
private bool AssertForwardBoundary(ulong currentOffset, Entry* target, int level)
{
level = int.Min(level, MaxLevel);
int nextLevelSize = levelSizeArray[level] * 4;
ulong targetTail = target->Position - (ulong)m_Buffer + target->Size - 1;
return (currentOffset / (ulong)nextLevelSize) == (targetTail / (ulong)nextLevelSize);
ulong prevHead = previous->Position - (ulong)m_Buffer,
currHead = current->Position - (ulong)m_Buffer;
return (currHead / (ulong)nextLevelSize) == (prevHead / (ulong)nextLevelSize);
}
/// <summary>
@@ -108,90 +74,62 @@ namespace StgSharp.HighPerformance.Memory
/// </summary>
private void MergeAndRemoveFromBuckets(Entry* entry)
{
// TODO
/*
* 1.有限回收,最多向上收集2层(算上当前总共3层)
* 2.单层内就可以通过前后链表遍历解决,很容易做到
* 3.由于SLAB分配器内部包含快速复用路径,因而可以考虑直接进行Free掉被合并的Entry。复用成本很低(因为SLAB既没有Version也没有IEnumerable,所以不会有额外的操作计数损耗)
* 4.后续提供HLSF.Collect全量整理API,从头遍历邻接块进行彻底的合并
*/
// TODO 后续提供HLSF.Collect全量整理API,从头遍历邻接块进行彻底的合并
if (entry == null)
{
return;
}
Entry* result = entry;
uint size = entry->Size;
int originLevel = entry->Level;
int segment = DetermineSegmentIndex(size, originLevel);
// RemoveFromBucket(originLevel, segment, (BucketNode*)entry->Position);
do
{
// previous direction merge
Entry* p = entry->PreviousNear;
if (p == null ||
p->State != EntryState.Empty ||
!IsAdjacentTo(result, p) ||
p->Level != entry->Level ||
!AssertBoundary(p, entry, originLevel))
{
break;
}
// Console.WriteLine($"{(ulong)p->Size} merged to {(ulong)entry->Size} previous");
entry->Size += p->Size;
entry->Position = p->Position;
RemoveFromBucket(originLevel, DetermineSegmentIndex(p->Size, originLevel), (BucketNode*)p->Position);
RemoveFromPositionChain(p);
} while (true);
do
{
originLevel = entry->Level;
while (true)
// next direction merge
Entry* n = entry->NextNear;
if (n == null ||
n->State != EntryState.Empty ||
!IsAdjacentTo(result, n) ||
n->Level != entry->Level ||
!AssertBoundary(n, entry, originLevel))
{
// backward merging - simplified to single attempt
Entry* prev = entry->PreviousNear;
// compute offset of current block and base position
ulong currentOffset = entry->Position - (ulong)m_Buffer;
if (prev != null &&
prev != _spareMemory &&
AssertBackwardBoundary(currentOffset, prev, originLevel) &&
IsAdjacentTo(entry, prev) &&
TryRemoveFromBucket(originLevel, DetermineSegmentIndex(prev->Size, originLevel), (BucketNode*)prev->Position))
{
// Merge
entry->Position = prev->Position;
entry->Size += prev->Size;
RemoveFromPositionChain(prev);
}
// Update linked list
/*
Entry* prevPrev = prev->PreviousNear;
if (prevPrev != null) {
prevPrev->NextNear = entry;
}
entry->PreviousNear = prevPrev;
/**/
break;
}
while (true)
{
// forward merging - simplified to single attempt
Entry* next = entry->NextNear;
// Console.WriteLine($"{(ulong)n->Size} merged to {(ulong)entry->Size} next");
entry->Size += n->Size;
RemoveFromBucket(originLevel, DetermineSegmentIndex(n->Size, originLevel), (BucketNode*)n->Position);
RemoveFromPositionChain(n);
} while (true);
originLevel = int.Min(9, originLevel);
entry->Level += entry->Size >= levelSizeArray[originLevel] * 4 ? 1 : 0;
entry->Level &= 15;
ulong currentOffset = entry->Position - (ulong)m_Buffer;
if (next == null ||
next == _spareMemory ||
!AssertForwardBoundary(currentOffset, next, entry->Level) ||
!IsAdjacentTo(entry, next) ||
entry->Level != next->Level ||
!TryRemoveFromBucket(originLevel, DetermineSegmentIndex(next->Size, originLevel), (BucketNode*)next->Position))
{
break;
}
// Update linked list
/*
Entry* nextNext = next->NextNear;
if (nextNext != null) {
nextNext->PreviousNear = entry;
}
entry->NextNear = nextNext;
/**/
// Merge
entry->Size += next->Size;
RemoveFromPositionChain(next);
}
entry->Level = GetLevelFromSize(entry->Size);
} while (originLevel < entry->Level);
BucketNode* bucket = (BucketNode*)entry->Position;
bucket->EntryRef = entry;
}
/// <summary>
@@ -202,9 +140,14 @@ namespace StgSharp.HighPerformance.Memory
Entry* prev = entry->PreviousNear;
Entry* next = entry->NextNear;
if (prev != null) {
if (prev != null)
{
prev->NextNear = entry->NextNear;
} else
{
_positionHead = entry->NextNear;
}
if (next != null) {
next->PreviousNear = entry->PreviousNear;
}
@@ -228,11 +171,23 @@ namespace StgSharp.HighPerformance.Memory
[FieldOffset(8)] internal Entry* NextNear; // Position linked list: next pointer
[FieldOffset(16)] internal Entry* PreviousNear; // Position linked list: previous pointer
[FieldOffset(28)] internal int Level; // Level of the block in the allocator
[FieldOffset(28)] internal int _Level; // Level of the block in the allocator
[FieldOffset(24)] internal uint Size; // Block size information
[FieldOffset(32)] public EntryState State;
[FieldOffset(0)] public nuint Position; // Memory block position
public int Level
{
get => _Level;
set
{
if (value > 15 || value < 0) {
throw new InvalidOperationException();
}
_Level = value;
}
}
}
internal enum EntryState : uint