This commit is contained in:
Youmu Liu
2026-03-26 18:02:13 +08:00
parent d960d02972
commit 06e3aa119b
20 changed files with 198 additions and 169 deletions
+2 -2
View File
@@ -38,7 +38,7 @@ namespace StgSharp
// 仅供 L4 内存安全测试使用。
// ====================================================================
internal sealed unsafe class SequentialPredictor : IPrefetchPredict
internal sealed unsafe class SequentialPredictor : IL4Predict
{
private readonly nuint[] _addresses;
@@ -313,7 +313,7 @@ namespace StgSharp
{
nuint[] result = new nuint[count];
for (int i = 0; i < count; i++) {
result[i] = (nuint)(0x1_0000_0000UL + (ulong)i * 0x1000);
result[i] = (nuint)(0x1_0000_0000UL + (((ulong)i) * 0x1000));
}
return result;
}
+10 -7
View File
@@ -40,7 +40,7 @@ namespace StgSharp
// WriteBack 记录被回写的 origin,供驱逐测试断言。
// ====================================================================
internal sealed unsafe class TrackingPredictor : IPrefetchPredict
internal sealed unsafe class TrackingPredictor : IL4Predict
{
private readonly nuint[] _addresses;
@@ -128,7 +128,10 @@ namespace StgSharp
private static unsafe byte L4ReadFirstByte(
L4.CacheLine line
) => *(byte*)line.Address;
)
{
return *(byte*)line.Address;
}
// ================================================================
// P1-2 AgeAll_SaturatesAt3
@@ -168,7 +171,7 @@ namespace StgSharp
for (int i = 0; i < snap.MaxId; i++) {
L4Assert(
snap.RrpvSnapshot[i] == 0,
$"RrpvSnapshot[{i}] should be 0 right after Map, " + $"got {snap.RrpvSnapshot[i]}");
$"{$"RrpvSnapshot[{i}] should be 0 right after Map, "}{$"got {snap.RrpvSnapshot[i]}"}");
}
}
@@ -191,7 +194,7 @@ namespace StgSharp
if (snap.RrpvSnapshot[i] != 3)
{
L4Assert(false,
$"RrpvSnapshot[{i}] == {snap.RrpvSnapshot[i]}, " + "expected 3 after 4x AgeAll (saturation failure or overflow)");
$"{$"RrpvSnapshot[{i}] == {snap.RrpvSnapshot[i]}, "}expected 3 after 4x AgeAll (saturation failure or overflow)");
allSaturated = false;
}
}
@@ -305,7 +308,7 @@ namespace StgSharp
}
L4Assert(
evictedOrigin != nuint.Zero,
$"WriteBack origin should be a batch1 address, " + $"WriteBackLog=[{string.Join(", ", predictor2.WriteBackLog)}]");
$"{$"WriteBack origin should be a batch1 address, "}{($"WriteBackLog=[{string.Join(", ", predictor2.WriteBackLog)}]")}");
// 断言 c: SwissTable 中已不含该 origin
L4Assert(
@@ -320,11 +323,11 @@ namespace StgSharp
remapped.Dispose();
L4Assert(
refill == 0xCC,
$"Re-mapped evicted line should be re-prefetched with 0xCC, " + $"got 0x{refill:X2} (0xAA = stale data not evicted)");
$"{$"Re-mapped evicted line should be re-prefetched with 0xCC, "}{($"got 0x{refill:X2} (0xAA = stale data not evicted)")}");
if (_l4FailCount == 0) {
Console.WriteLine(
$"PASS (evicted 0x{evictedOrigin:X}, remain={remain}, " + $"WriteBack×{predictor2.WriteBackLog.Count})");
$"{($"PASS (evicted 0x{evictedOrigin:X}, remain={remain}, ")}{$"WriteBack×{predictor2.WriteBackLog.Count})"}");
}
}
catch (Exception ex)
+8 -8
View File
@@ -40,7 +40,7 @@ namespace StgSharp
// 用于 P2-2 验证"预填充后 Map 命中不触发二次 Prefetch"。
// ====================================================================
internal sealed class CountingPredictor : IPrefetchPredict
internal sealed class CountingPredictor : IL4Predict
{
private readonly nuint[] _addresses;
@@ -158,7 +158,7 @@ namespace StgSharp
L4.DebugSnapshot snap = l4.GetDebugSnapshot();
Console.WriteLine();
Console.WriteLine(
$" [diag] after warm-up: MaxId={snap.MaxId}, " + $"AheadCount={snap.AheadCount}, " + $"Predict×{predictAfterWarmup}, " + $"Prefetch×{prefetchAfterWarmup}");
$"{$" [diag] after warm-up: MaxId={snap.MaxId}, "}{$"AheadCount={snap.AheadCount}, "}{$"Predict×{predictAfterWarmup}, "}{$"Prefetch×{prefetchAfterWarmup}"}");
}
// 断言 c(warm-up 后):所有 K 条地址均在缓存中
@@ -195,7 +195,7 @@ namespace StgSharp
{
L4.DebugSnapshot snap = l4.GetDebugSnapshot();
Console.WriteLine(
$" [diag] after {K}x Map: AheadCount={snap.AheadCount}, " + $"Predict×{predictAfterMaps}, " + $"Prefetch×{prefetchAfterMaps}");
$"{$" [diag] after {K}x Map: AheadCount={snap.AheadCount}, "}{$"Predict×{predictAfterMaps}, "}{$"Prefetch×{prefetchAfterMaps}"}");
}
// 断言 b: 已缓存的行不会被重新装填(Prefetch(line) 调用次数不增加)
@@ -204,15 +204,15 @@ namespace StgSharp
// 这是预期行为,不断言 Predict 次数。
L4Assert(
prefetchAfterMaps == prefetchAfterWarmup,
$"Prefetch(line) should not be called again for already-cached addresses, " + $"was {prefetchAfterWarmup} after warm-up, now {prefetchAfterMaps}");
$"{$"Prefetch(line) should not be called again for already-cached addresses, "}{$"was {prefetchAfterWarmup} after warm-up, now {prefetchAfterMaps}"}");
// Predict 增加是正常的,仅打印供参考
Console.WriteLine(
$" [info] Predict called {predictAfterMaps - predictAfterWarmup} " + $"extra time(s) during {K}x Map " + $"(aheadCount stays below threshold=1024 " + $"because K={K} << 1024, re-prediction is expected)");
$"{$" [info] Predict called {predictAfterMaps - predictAfterWarmup} "}{$"extra time(s) during {K}x Map "}{$"(aheadCount stays below threshold=1024 "}{$"because K={K} << 1024, re-prediction is expected)"}");
if (_l4FailCount == 0) {
Console.WriteLine(
$"PASS (K={K}, all hits, no re-prefetch, " + $"Prefetch×{prefetchAfterMaps})");
$"{$"PASS (K={K}, all hits, no re-prefetch, "}{$"Prefetch×{prefetchAfterMaps})"}");
}
}
catch (Exception ex)
@@ -284,7 +284,7 @@ namespace StgSharp
// 此处仅记录行为,不判定 FAIL——但打印出来供后续决策参考。
Console.WriteLine(
evictThrew ?
"PASS (DebugEvict with null Predictor threw NullRef as expected " + "— caller is responsible for null check per trusted-call model)" :
("PASS (DebugEvict with null Predictor threw NullRef as expected " + "— caller is responsible for null check per trusted-call model)") :
"PASS (DebugEvict with null Predictor did not throw)");
// 核心断言:Prefetch() 本身在 null Predictor 时不崩溃
@@ -300,7 +300,7 @@ namespace StgSharp
L4.DebugSnapshot snap = l4b.GetDebugSnapshot();
Console.WriteLine(
$" [info] AheadCount after warm-up = {snap.AheadCount} " + $"(Prefetch triggers when < 1024)");
$"{$" [info] AheadCount after warm-up = {snap.AheadCount} "}{$"(Prefetch triggers when < 1024)"}");
// Prefetch 的 null 检查测试:直接调用 DebugPrefetch(如已暴露)
// 当前 Debug 接口未暴露 DebugPrefetch,改为间接验证: