记忆 GC 保留评分(RetentionScore)
wesgine 的记忆 GC 使用 retentionScore 加权评分来决定淘汰优先级,而非简单的 LRU。
评分公式
retentionScore = timeDecay × W_time
+ recallWeight × W_recall
+ trustWeight × W_trust
+ kindWeight × W_kind
各因子范围 [0, 1],权重之和 = 1。
因子详解
timeDecay(时间衰减)
基于 accessed_at 的指数衰减。最近被访问的条目衰减慢,长期未访问的衰减快。
accessed_at已归一化为max(accessed_at, created_at)(INV-MEM-51)- 避免零值导致的 55 年衰减问题
recallWeight(召回频率)
基于 recall_count 的对数权重。被频繁召回的条目得分高。
touchWriter批量更新recall_count- 5 秒窗口内同一条目多次命中分别计数(修复了早期合并 bug)
trustWeight(信任权重)
基于 Trust 等级的静态映射:
| Trust | 权重 |
|---|---|
| TrustSystem | 1.0 |
| TrustExplicit | 0.8 |
| TrustMulti | 0.6 |
| TrustInferred | 0.4 |
| TrustUnknown | 0.2 |
kindWeight(类型权重)
不同 Kind 有不同的 GC 保护力度:
constraint/instruction/environment:GC 豁免(不参与评分)fact/collective:较高权重preference/correction:中等权重context(仅 cold-start):较低权重
GC 豁免类型
以下 Kind 完全免疫 GC 淘汰:
KindConstraintKindInstructionKindEnvironment
豁免条目仍计入配额,但不参与 retentionScore 排序。
淘汰流程
定时触发 GC
↓
查询非豁免条目(按 retentionScore 升序)
↓
score 最低的条目优先淘汰
↓
每批 N 条(节流),避免数据库压力
↓
QuotaSink.RecordMemoryDelta(-N) 更新配额
与 TTL 的关系
TTL 是硬过期(到期直接删除),retentionScore 是软排序(超配额时低分先淘汰)。两者互补:
- TTL 处理"这条目注定要过期"
- retentionScore 处理"配额紧张时谁先走"
INV-MEM-26
GC runMaxEntries 使用 recall-frequency weighted 淘汰,不是纯 LRU。
相关文档
- 记忆 GC 概览 →
memory-gc.md - 记忆 GC 与配额联动 →
memory-gc-quota.md - 记忆 Trust 等级 →
memory-trust-levels.md