fix sever L4 errors

This commit is contained in:
Nitload
2026-03-17 00:31:52 +08:00
parent f8a879c4da
commit 98d711a3ca
4 changed files with 104 additions and 53 deletions
@@ -2,8 +2,8 @@
// -----------------------------------------------------------------------
// file="L4.Prefetch"
// Project: StgSharp
// AuthorGroup: Nitload
// Copyright (c) Nitload. All rights reserved.
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -25,18 +25,27 @@
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
using System.ComponentModel;
namespace StgSharp.HighPerformance.Memory
{
public unsafe partial class L4
{
public const int MaxActivateCacheLineCount = 1024;
private partial void Prefetch()
{
if (PrefetchPredict is null) {
return;
}
if (_activeCount > MaxActivateCacheLineCount) {
throw new OverflowException("Too many activated cache line in external reference.");
}
Span<CacheLinePrediction> span = new(_prediction, PredictionCount);
int actualCount = PrefetchPredict.Predict(span);
if (!(PrefetchPredict.Predict(span, out int actualCount) && actualCount > 0)) {
return;
}
int missIndex = 0;
AgeAll();
for (int i = 0; i < actualCount; i++)
@@ -61,21 +70,31 @@ namespace StgSharp.HighPerformance.Memory
continue;
}
// TODO 未经初始化的_idMux可能会导致TryGetEmptyLine失败,导致无法预取,最好添加末尾指针计数
if (!TryGetEmptyLine(out int index))
int retryCount = 0, index, remain = missIndex - i;
const int maxRetry = 1024;
while (!TryGetEmptyLine(out index))
{
throw new OverflowException("L4 has no empty cache line.");
missIndex = Evict(missIndex);
retryCount++;
if (retryCount > maxRetry) {
throw new OverflowException($"Failed to evict cache line after {maxRetry} retries.");
}
}
CacheLineHead* head = &_head[index];
head->_id = index;
head->_origin = address;
head->_profile = handle.MapPolicy;
head->_refCount = 0;
head->_address = (nuint)(&_data[index]);
// pre fetch them here
_ = PrefetchPredict.Prefetch(head->_origin, head->_profile, head->_address);
PrefetchPredict.Prefetch(head->_origin, head->_profile, new Span<byte>((byte*)head->_address, Unsafe.SizeOf<CacheLineData>()));
_ = _map.TryAddOrSet(address, (nuint)head, out _);
}
_ = Interlocked.Add(ref _aheadCount, actualCount);
}
private partial bool TestHit(
nuint origin
)
private partial bool TestHit(nuint origin)
{
if (_map.TryGet(origin, out nuint handle))
{