summaryrefslogtreecommitdiff
path: root/docs/维护说明.md
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-22 10:36:39 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-22 10:36:39 +0800
commit164f4749460a304c1aaad4900ef3facc29859eb0 (patch)
tree05794b5f853566d68ebefc822b3dce3b5f780ca3 /docs/维护说明.md
parentb377e750a6a3f35c5d64a29f14ac3fbd87d4a752 (diff)
downloadliving-village-164f4749460a304c1aaad4900ef3facc29859eb0.tar.gz
perf(kernel): P27 第一步 — Rumor 长跑基准与修复前量化
新增 Kernel 层 Rumor 长跑基准(RumorBench.fs + headless --rumor-bench [days npcs chats_per_day]),把「聊天→生成/追溯谣言」路径从 Sim.step 的 NPC 快照分配解耦,隔离测量谣言工作集随世界年龄的分配/耗时;同 Config 的 retained_id_checksum 证明确定性。 复核 M3-1 前提:World.Rumors 已被 M6a(d94ec2d/cc850bf)按 3 天保留窗口收敛, 单日成本平稳(1/5/10 天 ≈18.7/18.1/19.8s、≈19GB/天),超线性项消失。 剩余 Rumor 成本 = 每次聊天的两条 O(N) 扫描 latestRumorFor/rumorIsDuplicate, 且 [<Struct>] NpcId/RumorId 用 = 比较会逐条装箱(Sim.chat 单独测得 N=16000 时 393,736 B/次、随 N 线性)。 修复前基准(30 NPC,--rumor-bench D 30 2000): 3d chat_calls=6000 retained=6000 alloc=930,716,456 ms=1626.7 30d chat_calls=60000 retained=8000 alloc=13,419,045,864 ms=12182.5 60d chat_calls=120000 retained=8000 alloc=27,297,668,608 ms=23769.7 (60d 工作集稳定 8000,不随年龄增长。) docs/维护说明.md 新增 P27 小节记录上述现状与量级。不改任何模拟语义。
Diffstat (limited to 'docs/维护说明.md')
-rw-r--r--docs/维护说明.md25
1 files changed, 25 insertions, 0 deletions
diff --git a/docs/维护说明.md b/docs/维护说明.md
index cc3a698..7be174a 100644
--- a/docs/维护说明.md
+++ b/docs/维护说明.md
@@ -459,6 +459,31 @@ dotnet src/LivingVillage.Headless/bin/Release/net8.0/LivingVillage.Headless.dll
各出一格,相邻民居极近时挑檐可能视觉叠压,可在布点时加 1 格间隔;③ 巡游 40s 档的 `visible>=8`
占比仅 13%(P25 150s 档为 74%),属取证时长差异,非可见性回归。
+## P27:Rumor 长局性能修复(工作集扫描去装箱 + 裁剪判定)
+
+- **现状复核(更正 M3-1 前提)**:M3-1 记录的「`World.Rumors` 不裁剪、逐次聊天全表扫描」已由 M6a
+ (`d94ec2d` 工作集容量上界+按天淘汰、`cc850bf` 窗口化早停扫描)修复:`RumorEvent.DayIndex` 派生字段
+ + `trimRumors` 把工作集按「最新在前 + 3 天保留窗口」收敛。实测单日成本已平稳(本机 `--cost-probe`:
+ 1 天 18.7s/18.9GB、5 天 90.5s/95.7GB、10 天 198.2s/191.9GB,≈19GB/天常数),M3 记录的 20 天
+ ≈45 s/天的超线性项已消失。故 P27 不采用「砍 depth/strength 传播」这类会改变模拟语义的方案。
+- **剩余 Rumor 成本定位**:工作集有界后每次聊天仍有两条 O(N) 扫描 `latestRumorFor` / `rumorIsDuplicate`;
+ 且此前用 `=` 比较 `[<Struct>]` 的 `NpcId`/`RumorId`,会走泛型结构相等,对每一条被扫描到的谣言
+ 装箱(实测 ≈24 B/条、单次聊天随 N 线性增长——`Sim.chat` 单独测得 N=16000 时 393,736 B/次);
+ 这是 Rumor 逐条分配的主因,而非列表 cons 本身。
+- **Kernel 长跑基准**:新增 `src/LivingVillage.Kernel/RumorBench.fs` 与 headless
+ `--rumor-bench [days npcs chats_per_day]`,把「聊天→生成/追溯谣言」路径从 `Sim.step` 的 NPC 快照
+ 分配解耦,按模拟日推进 tick、固定节奏注入聊天,测工作集分配与耗时;同 `Config` 的
+ `retained_id_checksum` 可证明确定性。
+ 修复前(30 NPC,`--rumor-bench D 30 2000`):
+
+ | days | chat_calls | rumors_retained | allocated_bytes | elapsed_ms |
+ |---|---|---|---|---|
+ | 3 | 6000 | 6000 | 930,716,456 | 1626.7 |
+ | 30 | 60000 | 8000 | 13,419,045,864 | 12182.5 |
+ | 60 | 120000 | 8000 | 27,297,668,608 | 23769.7 |
+
+ 60 天工作集稳定在 8000(M6a 的 3 天保留窗口 + 2000/天),不再随年龄增长。
+
## 已验证命令
```bash