going on reconstruct of HLSF
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Reflection.Metadata;
|
||||
using hlsfHandle = StgSharp.HighPerformance.Memory.HlsfHandle;
|
||||
@@ -42,46 +43,37 @@ namespace StgSharp.HighPerformance.Memory
|
||||
if (size > _maxAllocSize) {
|
||||
throw new InvalidOperationException("Requested size exceeds maximum allocatable size.");
|
||||
}
|
||||
|
||||
/*
|
||||
int level = GetLevelFromSize(size);
|
||||
int segmentIndex = DetermineSegmentIndex(_levelSizeArray, size, level);
|
||||
int segmentIndex = GetSegmentFromLevel(size, level);
|
||||
|
||||
int i = level, s = segmentIndex;
|
||||
Entry* handle;
|
||||
while (!TryPopLevelForAllocation(i, s, out handle))
|
||||
{
|
||||
if (++s >= 3)
|
||||
{
|
||||
s = 0;
|
||||
i++;
|
||||
}
|
||||
if (i > MaxLevel)
|
||||
{
|
||||
if (TryPopLevelForAllocation(10, 1, out handle))
|
||||
{
|
||||
break;
|
||||
} else if (TryAllocateNew32MBBlock(out handle))
|
||||
{
|
||||
break;
|
||||
}
|
||||
throw new OverflowException("Out of memory: Unable to allocate new 16MB block or find suitable bucket for allocation.");
|
||||
}
|
||||
}
|
||||
/**/
|
||||
|
||||
if (handle != null)
|
||||
Entry* entry = null;
|
||||
nuint requestedOffset = GetAllocSize(size);
|
||||
(int level, int segment) = GetIndexPairOnce(size);
|
||||
int index = (3 * level) + segment;
|
||||
int i = index;
|
||||
while ((i < _bucketHeads.Length) && !TryPopLevelForAllocation(index, out entry)) {
|
||||
i++;
|
||||
}
|
||||
if ((i > _maxLevel) && !TryAllocateNewBlock(requestedOffset, out entry)) {
|
||||
throw new OverflowException("Out of memory: Unable to allocate new 16MB block or find suitable bucket for allocation.");
|
||||
}
|
||||
if (entry != null)
|
||||
{
|
||||
int requestedOffset = (segmentIndex + 1) * ((int)_levelSizeArray[level]);
|
||||
if (requestedOffset > (int)handle->Size) {
|
||||
if (requestedOffset > entry->Size) {
|
||||
throw new OverflowException("Out of memory: insufficient block size returned from spare memory.");
|
||||
}
|
||||
nuint remainder = handle->Size - ((nuint)requestedOffset);
|
||||
SetEntryLevel(handle, handle->Position, (uint)requestedOffset);
|
||||
handle->State = EntryState.Alloc;
|
||||
nuint remainder = entry->Size - requestedOffset;
|
||||
SetEntryLevel(entry, entry->Position, (uint)requestedOffset);
|
||||
entry->State = EntryState.Alloc;
|
||||
if (remainder > 0) {
|
||||
SliceMemory(handle->NextNear, remainder);
|
||||
OrganizeMemory(entry->NextNear, remainder);
|
||||
}
|
||||
}
|
||||
return new(handle, size);
|
||||
return new(entry, size);
|
||||
}
|
||||
|
||||
public bool TryAlloc(
|
||||
@@ -94,44 +86,35 @@ namespace StgSharp.HighPerformance.Memory
|
||||
handle = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
int level = GetLevelFromSize(size);
|
||||
int segmentIndex = DetermineSegmentIndex(_levelSizeArray, size, level);
|
||||
int segmentIndex = GetSegmentFromLevel(size, level);
|
||||
|
||||
int i = level, s = segmentIndex;
|
||||
Entry* entry;
|
||||
while (!TryPopLevelForAllocation(i, s, out entry))
|
||||
{
|
||||
if (++s >= 3)
|
||||
{
|
||||
s = 0;
|
||||
i++;
|
||||
}
|
||||
if (i > MaxLevel)
|
||||
{
|
||||
if (TryPopLevelForAllocation(10, 1, out entry))
|
||||
{
|
||||
break;
|
||||
} else if (TryAllocateNew32MBBlock(out entry))
|
||||
{
|
||||
break;
|
||||
}
|
||||
handle = default;
|
||||
return false;
|
||||
}
|
||||
/**/
|
||||
|
||||
Entry* entry = null;
|
||||
nuint requestedOffset = GetAllocSize(size);
|
||||
(int level, int segment) = GetIndexPairOnce(size);
|
||||
int index = (3 * level) + segment;
|
||||
int i = index;
|
||||
while ((i < _bucketHeads.Length) && !TryPopLevelForAllocation(index, out entry)) {
|
||||
i++;
|
||||
}
|
||||
if ((i > _maxLevel) && !TryAllocateNewBlock(requestedOffset, out entry)) {
|
||||
throw new OverflowException("Out of memory: Unable to allocate new 16MB block or find suitable bucket for allocation.");
|
||||
}
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
int requestedOffset = (segmentIndex + 1) * ((int)_levelSizeArray[level]);
|
||||
if (requestedOffset > (int)entry->Size) {
|
||||
if (requestedOffset > entry->Size) {
|
||||
throw new OverflowException("Out of memory: insufficient block size returned from spare memory.");
|
||||
}
|
||||
nuint remainder = entry->Size - ((nuint)requestedOffset);
|
||||
nuint remainder = entry->Size - requestedOffset;
|
||||
SetEntryLevel(entry, entry->Position, (uint)requestedOffset);
|
||||
entry->State = EntryState.Alloc;
|
||||
if (remainder > 0) {
|
||||
SliceMemory(entry->NextNear, remainder);
|
||||
OrganizeMemory(entry->NextNear, remainder);
|
||||
}
|
||||
}
|
||||
handle = new(entry, size);
|
||||
@@ -139,16 +122,16 @@ namespace StgSharp.HighPerformance.Memory
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Slice the memory block into smaller blocks and add them to the appropriate buckets
|
||||
/// Slice the memory block into smaller blocks and add them to the appropriate buckets.
|
||||
/// Notice: this method is not responsible for freeing the original BucketNode
|
||||
/// </summary>
|
||||
/// <param name="e">
|
||||
///
|
||||
/// The next entry nearby the part to slice
|
||||
/// </param>
|
||||
/// <param name="sizeToSlice">
|
||||
///
|
||||
/// </param>
|
||||
private void SliceMemory(
|
||||
private void OrganizeMemory(
|
||||
Entry* e,
|
||||
nuint sizeToSlice
|
||||
)
|
||||
@@ -159,97 +142,22 @@ namespace StgSharp.HighPerformance.Memory
|
||||
nuint end = e->Position - ((nuint)m_Buffer); // end offset of buffer to slice
|
||||
|
||||
int i = (BitOperations.TrailingZeroCount(offset) - 6) / 2;
|
||||
i = int.Min(10, i);
|
||||
for (; i < _levelSizeArray.Length; i++)
|
||||
{
|
||||
uint size = _levelSizeArray[i];
|
||||
nuint upper = size * 4;
|
||||
nuint edge = (((offset + upper) - 1U) / upper) * upper;
|
||||
int count = (int)((nuint.Min(edge, end) - offset) / size);
|
||||
if (count > 0)
|
||||
{
|
||||
nuint newSize = ((nuint)count) * size;
|
||||
|
||||
Entry* newEntry = (Entry*)_entries.Allocate();
|
||||
InsertEntryBefore(newEntry, next);
|
||||
SetEntryLevel(newEntry, offset + ((nuint)m_Buffer), newSize);
|
||||
newEntry->State = EntryState.Empty;
|
||||
|
||||
BucketNode* b = (BucketNode*)newEntry->Position;
|
||||
b->EntryRef = newEntry;
|
||||
PushBucketToLevel(i, count - 1, b);
|
||||
offset += newSize;
|
||||
remain -= newSize;
|
||||
}
|
||||
if (remain <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > MaxLevel)
|
||||
{
|
||||
uint size = _levelSizeArray[^1];
|
||||
nuint upper = size * 4;
|
||||
nuint edge = (end / upper) * upper;
|
||||
int count = (int)((nuint.Min(edge, end) - offset) / upper);
|
||||
if (count > 0)
|
||||
{
|
||||
nuint newSize = ((nuint)count) * upper;
|
||||
|
||||
Entry* newEntry = (Entry*)_entries.Allocate();
|
||||
InsertEntryBefore(newEntry, next);
|
||||
SetEntryLevel(newEntry, offset + ((nuint)m_Buffer), newSize);
|
||||
newEntry->State = EntryState.Empty;
|
||||
|
||||
BucketNode* b = (BucketNode*)newEntry->Position;
|
||||
b->EntryRef = newEntry;
|
||||
PushBucketToLevel(i, count - 1, b);
|
||||
offset += newSize;
|
||||
remain -= newSize;
|
||||
if (remain <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i--; i >= 0; i--)
|
||||
{
|
||||
uint size = _levelSizeArray[i];
|
||||
nuint edge = (end / size) * size;
|
||||
int count = (int)((nuint.Min(edge, end) - offset) / size);
|
||||
if (count > 0)
|
||||
{
|
||||
nuint newSize = ((nuint)count) * size;
|
||||
|
||||
Entry* newEntry = (Entry*)_entries.Allocate();
|
||||
InsertEntryBefore(newEntry, next);
|
||||
SetEntryLevel(newEntry, offset + ((nuint)m_Buffer), newSize);
|
||||
newEntry->State = EntryState.Empty;
|
||||
|
||||
BucketNode* b = (BucketNode*)newEntry->Position;
|
||||
b->EntryRef = newEntry;
|
||||
b->NextLevel = null;
|
||||
b->PreviousLevel = null;
|
||||
PushBucketToLevel(i, count - 1, b);
|
||||
offset += newSize;
|
||||
remain -= newSize;
|
||||
}
|
||||
if (remain <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to allocate a new 16MB block when all buckets are empty
|
||||
/// </summary>
|
||||
/// <param name="size">
|
||||
/// Size of memory block to be allocated. Notice: Size is assumed as times of 64.
|
||||
/// </param>
|
||||
/// <param name="handle">
|
||||
/// Output handle to the allocated Entry
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// True if allocation succeeded
|
||||
/// </returns>
|
||||
private bool TryAllocateNew32MBBlock(
|
||||
private bool TryAllocateNewBlock(
|
||||
nuint size,
|
||||
out Entry* handle
|
||||
)
|
||||
{
|
||||
@@ -260,7 +168,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
handle = null;
|
||||
return false;
|
||||
}
|
||||
nuint size = (remain > 32 * 1024 * 1024L) ? (32 * 1024 * 1024U) : remain;
|
||||
size = nuint.Min(size, remain);
|
||||
|
||||
|
||||
// build new entry
|
||||
@@ -278,6 +186,23 @@ namespace StgSharp.HighPerformance.Memory
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for allocation - converts BucketNode to Entry
|
||||
/// </summary>
|
||||
private bool TryPopLevelForAllocation(
|
||||
int bucketIndex,
|
||||
out Entry* entry
|
||||
)
|
||||
{
|
||||
if (TryPopBucket(bucketIndex, out BucketNode* bucketNode))
|
||||
{
|
||||
entry = bucketNode->EntryRef;
|
||||
return entry != null;
|
||||
}
|
||||
entry = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for allocation - converts BucketNode to Entry
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user