summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-22 10:48:11 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-22 10:48:11 +0800
commit593b3a69294f2c93df1e14d4be7d2f4cd9f9ac14 (patch)
tree42a6fd1a396016287fb4365be375d533c6271e05
parenta0597455629618a282b582d13c23bfeab786e7d2 (diff)
downloadliving-village-593b3a69294f2c93df1e14d4be7d2f4cd9f9ac14.tar.gz
docs: P27 小节补全修复后指标与等价性/门槛
补 P27 修复策略(扫描去装箱 + 裁剪判定 O(1))、修复前后基准对照 (60 天 alloc -64%、ms -28%)、retained_id_checksum 前后一致、 5 天双跑 WorldSave 逐字节相同、digest/PASS 与 Kernel 92/Desktop 143 门槛; 并记录全模拟 --cost-probe 基本持平的原因(逐 tick NPC 快照分配主导, 谣言子系统占比小,留给后续单)。已验证命令补 --rumor-bench。
-rw-r--r--docs/维护说明.md30
1 files changed, 30 insertions, 0 deletions
diff --git a/docs/维护说明.md b/docs/维护说明.md
index 7be174a..dbbf2ac 100644
--- a/docs/维护说明.md
+++ b/docs/维护说明.md
@@ -483,6 +483,32 @@ dotnet src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll
| 60 | 120000 | 8000 | 27,297,668,608 | 23769.7 |
60 天工作集稳定在 8000(M6a 的 3 天保留窗口 + 2000/天),不再随年龄增长。
+- **修复策略(两条,均不改保留集合与查询结果)**:
+ 1. **扫描去装箱**:`latestRumorFor` / `rumorIsDuplicate` 原来用 `=` 比较 `[<Struct>]` 的
+ `NpcId`/`RumorId`(含 `RumorId option`),走泛型结构相等、逐条装箱。改为先解构底层
+ `int`/`int64` 再比较(`Parent` 用 `int64 option` 比较);语义完全等价,扫描不再逐条分配。
+ 2. **裁剪判定 O(1)**:`World` 新增派生镜像 `RumorCount`/`RumorOldestDay`(不参与存档,读档由
+ `Sim.rumorWorkingSetStats` 从列表重建)。`appendRumor` 用「`count+1 > capacity` 或
+ `min(oldest, day) < cutoff`」O(1) 判定;旧 `consRumor` 每次追加都 `rumorsNeedTrim` 全表扫一遍。
+ 判定条件与 `rumorsNeedTrim` 逐字等价,仅真需裁剪时才走 `trimRumors`,保留集合逐条相同。
+- **修复后基准(同机、同 `--rumor-bench D 30 2000`)**:
+
+ | days | 修复前 alloc / ms | 修复后 alloc / ms | alloc 降幅 |
+ |---|---|---|---|
+ | 3 | 930,716,456 / 1626.7 | 482,716,192 / 1511.3 | −48% |
+ | 30 | 13,419,045,864 / 12182.5 | 4,884,067,640 / 8879.6 | −64% |
+ | 60 | 27,297,668,608 / 23769.7 | 9,774,660,360 / 17078.2 | −64% |
+
+ 60 天分配 −64%、耗时 −28%;`retained_id_checksum=927964000`(3/30/60 天分别为
+ 17997000 / 447996000 / 927964000)与修复前逐位一致,证明保留集合未变。
+- **等价性与门槛**:5 天 2000 聊天/天连跑两遍 `WorldSave.save` 逐字节相同;
+ `RumorCount`/`RumorOldestDay` 与对列表重算一致(count=8000、oldest_day=1)。
+ `final_digest=953775FAEB2FDDE97289491AA260BD8D390C571E48A7A13AD2CB6FB7124F7F6C`
+ 三次一致、`performance_determinism=PASS`;Kernel 92 / Desktop 143 全绿。
+- **全模拟口径(`--cost-probe`)**:1 天 18.7s/18.8GB、5 天 90.4s/94.6GB,与修复前基本持平——
+ 全模拟分配由逐 tick 的 `Npc[30]` 快照(`Sim.step` 的 `Array.copy`,≈120 B/NPC/tick)主导,
+ 谣言子系统占比很小;P27 的收益集中在 Rumor 工作集路径,符合「隔离测量」的基准口径。
+ 逐 tick NPC 快照分配属另一个课题(会触及不可变快照不变量),留给后续单。
## 已验证命令
@@ -502,6 +528,10 @@ LV_BATCH_WORKERS=4 dotnet src/LivingVillage.Headless/bin/Release/net8.0/LivingVi
# 长局成本阶梯(只读,真实测量)
dotnet src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll --cost-probe 1,5,10
+# P27 Rumor 长跑基准(隔离谣言子系统;默认 30 NPC×60 天×2000 聊天/天)
+dotnet src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll --rumor-bench
+dotnet src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll --rumor-bench 3 30 2000
+
# 素材再生成(确定性,输出 byte-identical)
python3 scripts/make-jiangnan-art.py && python3 scripts/make-cc0-art.py