// ----------------------------------------------------------------------------- // file="L4.Predict" // Project: StgSharp // Copyright (c) Nitload. // SPDX-License-Identifier: MIT // ----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Nitload.Common.HighPerformance.Memory { public unsafe partial class L4 { internal partial int Predict() { if (!TryGetCurrentPredictor(out IL4Predictor? p)) { return 0; } int total_count = 0, count; Span as_sp = stackalloc L4.AddressSource[4]; Predict: while ((count = p.PredictMission(in as_sp)) > 0) { for (int i = 0; i < count; i++) { if (_addressMap.TryGet(as_sp[i], out ulong map_handle_adr)) { L4.CacheLineMetadata* map_handle = (L4.CacheLineMetadata*)map_handle_adr; map_handle->IncreasePredictCount(); map_handle->CheckCount(); } else { uint size = as_sp[i].Size; int handle_idx = _bufferAllocator.Alloc(size); L4.CacheLineMetadata* handle = _bufferAllocator.MetadataAt(handle_idx); if (!_addressMap.TryAddOrSet(as_sp[i], (ulong)handle)) { throw new InvalidOperationException(); } } } total_count += count; if (total_count >= 2048) { return total_count; } } if (MoveNextPredictor()) { _ = TryGetCurrentPredictor(out p); goto Predict; } return total_count; } } } /* goto 本身没问题,但当前控制流有几个需要先确认的点: 高:换 predictor 的分支看起来反了。 MoveNextPredictor() 在 _predict 到达 _enter 时返回 true。因此 L4.Predict.cs:51 现在会在队列耗尽时再次取 predictor;TryGetCurrentPredictor 失败后仍 goto Predict,接着会用空的 p 调 PredictMission。反过来,有下一个 predictor 时它会提前返回,不再处理后续 predictor。 高:新分配的 metadata 没有增加预测计数。 现有映射分支会调用 IncreasePredictCount(),但新分配分支只分配并写入 Swiss。若该计数表示未消费预测数,新条目也需要相同的计数处理;还要确认 TLSF 重用 metadata 时会重置旧计数。 高:同一轮内重复的 AddressSource 可能重复分配。 SwissTable.TryGet 只查 published buffer,而新条目先写入 inactive buffer。后续再次预测相同 key 时会查不到,重新分配 metadata,再由 TryAddOrSet 覆盖先前 value,旧分配就失去映射。 中:需要校验 PredictMission 的返回值范围。 Span 容量是 4;count > 4 会让 as_sp[i] 越界,负值则被当作本轮结束。建议契约明确要求 0..4,并在 L4 边界验证。 本轮未改代码。L4.Predict.cs 的文件诊断通过,但尚未运行完整构建或运行时测试。 */