predict method of l4

This commit is contained in:
Youmu Liu
2026-10-19 18:38:43 +08:00
parent d1efb15e3f
commit e349bcc4dd
7 changed files with 195 additions and 62 deletions
@@ -16,7 +16,6 @@ namespace Nitload.Common.HighPerformance.Memory
public partial class L4
{
private readonly IL4Predictor[] _ring = new IL4Predictor[256];
private volatile int _consume;
private volatile int _enter;
private volatile int _predict;
@@ -45,7 +44,8 @@ namespace Nitload.Common.HighPerformance.Memory
if (ReferenceEquals(predictor, _ring[idx]))
{
int end = _predict;
for (int move = i; move < end - 1; move++) {
for (int move = i; move < end - 1; move++)
{
_ring[(byte)move] = _ring[(byte)(move + 1)];
}
_ring[(byte)(end - 1)] = default!;
@@ -61,6 +61,12 @@ namespace Nitload.Common.HighPerformance.Memory
}
}
internal bool MoveNextPredictor()
{
int cur = Interlocked.Increment(ref _predict);
return cur == _enter;
}
internal void RegistPredictor(
IL4Predictor predictor
)
@@ -69,18 +75,25 @@ namespace Nitload.Common.HighPerformance.Memory
return;
}
SpinWait sp = new();
wait_for_spare:
WaitForSpare();
while (Interlocked.CompareExchange(ref _queue_sync, 1, 0) != 0) {
sp.SpinOnce();
}
if (_enter - _consume >= PredictorRingCapacity)
{
_ = Interlocked.Exchange(ref _queue_sync, 0);
goto wait_for_spare;
}
WaitForSpare();
_consume++;
try
{
unchecked
{
byte idx = (byte)_consume;
_consume++;
_ring[idx] = predictor;
}
}
@@ -90,12 +103,28 @@ namespace Nitload.Common.HighPerformance.Memory
}
}
internal bool TryGetCurrentPredictor(
out IL4Predictor predictor
)
{
int cur = _predict;
if (cur >= _enter)
{
predictor = default!;
return false;
}
unchecked
{
predictor = _ring[(byte)cur];
return true;
}
}
private void WaitForSpare()
{
int spin_count = 0;
// wait until the queue has space
while (_enter - _consume >= 256)
while (_enter - _consume >= PredictorRingCapacity)
{
switch (spin_count)
{