L4 is now on new algo, using new eviction arrays, using union of hlsf and cache line head.
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System.ComponentModel;
|
||||
using System.Numerics;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
@@ -55,7 +56,6 @@ namespace StgSharp.HighPerformance.Memory
|
||||
return;
|
||||
}
|
||||
int missIndex = 0;
|
||||
AgeAll();
|
||||
for (int i = 0; i < actualCount; i++)
|
||||
{
|
||||
ref CacheLineDescription handle = ref span[i];
|
||||
@@ -82,26 +82,40 @@ namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
head = (CacheLineHead*)handle;
|
||||
index = head->Id;
|
||||
(*_eviction)[index] = 0; // reset eviction counter
|
||||
(*_predictCount)[index] = 0; // reset eviction counter
|
||||
|
||||
#region update predictor belonging
|
||||
|
||||
int predictId = head->Predictor;
|
||||
IL4Predict belong = predictorSpan[predictId];
|
||||
|
||||
// TODO 由于L4的缓存行改为“可变长度”缓存行,需要调整缓存行复用策略
|
||||
// This branch performs resident-line adoption rather than a simple policy
|
||||
// equality check. Returning true means the current predictor can keep using
|
||||
// the existing cache bytes without a write-back plus re-prefetch cycle.
|
||||
if (!ReferenceEquals(predict, belong))
|
||||
{
|
||||
throw new L4PredictConflictException(head->Origin, head->Profile, predictId);
|
||||
} else
|
||||
{
|
||||
// Compatibility failed, so the old owner must first flush its view of
|
||||
// the line before the new predictor rematerializes the cache bytes.
|
||||
|
||||
_ = Interlocked.Increment(ref head->RemainingPredictionCount);
|
||||
if ((*_predictCount)[index] > short.MaxValue / 2)
|
||||
{
|
||||
/*
|
||||
* EXPERIMENTAL / INTENTIONALLY UNSAFE:
|
||||
* This code performs a 32-bit atomic operation starting from a short reference.
|
||||
*
|
||||
* It is only valid in this specific storage layout because:
|
||||
* - the runtime is little-endian;
|
||||
* - arithmetic here does not cause harmful cross-16-bit carry/borrow;
|
||||
* - the backing storage remains valid and accessible beyond the logical short-array boundary;
|
||||
* - touching the adjacent 16 bits is acceptable for this allocation layout;
|
||||
* - misaligned int access is acceptable on the target platform.
|
||||
*
|
||||
* This is safe only with the current L4 allocation/layout guarantees.
|
||||
*/
|
||||
short predictCount = Volatile.Read(ref (*_predictCount)[index]);
|
||||
short mapCount = Volatile.Read(ref (*_mapCount)[index]);
|
||||
int decrement = (short.Min(predictCount, mapCount) + 1) / 2;
|
||||
_ = Interlocked.Add(ref Unsafe.As<short, int>(ref (*_predictCount)[index]), -decrement);
|
||||
_ = Interlocked.Add(ref Unsafe.As<short, int>(ref (*_mapCount)[index]), -decrement);
|
||||
}
|
||||
(*_predictCount)[index]++;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -122,8 +136,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
}
|
||||
head = &_head[index];
|
||||
head->_id = index;
|
||||
head = _head + index;
|
||||
head->Id = index;
|
||||
head->Origin = address;
|
||||
head->Profile = pHandle.MapPolicy;
|
||||
head->RefCount = 0;
|
||||
|
||||
Reference in New Issue
Block a user