Memory 算法性能调优报告
更新日期:2026-10-03。独立 worktree 中的性能分支已同步默认分支 master
(仓库没有使用 main 这个名称),基线为 5c98ff9c,合并提交为 6d1511ac,
最终算法实现为 9393edbe。
完整分析、历史对照、原始数据和复现方式
保存在英文报告中。本页主表以最新 master 为基线,旧报告的大幅提升倍数
不再当作相对当前主线的增量收益。
同步与新增优化
主线已经合入邻接覆盖索引、同一请求内的转移缓存、调用方记录快照复用、模型 keep-alive 和数据库压缩。这些改动完整保留,收益计入基线。
合并冲突时保留了主线的关键规则:先按意图和相似度排列完整邻域,再应用访问 预算。同分时仍按记录 ID、边类型排列。在这个规则下复用本 PR 已计算的余弦 标量分数,避免为每条边重复计算相似度,也避免维护两套邻接缓存。
本轮另外复用了向量解码缓冲区:同一请求内逐条解码、立即计算分数,然后复用数组。 存储格式、浮点计算顺序和缓存生命周期保持不变。与刚合并主线的版本单独比较, N=10,000 混合召回的单次分配从约 59.35 MB 降到 49.11 MB,减少约 17%。 这是累计内存分配量,不是进程峰值内存。
再次测量
N 是记录数;使用 N=1、10、100、1,000、10,000,108 个用例,每个版本交替 运行 5 轮,共 1,080 个最终样本。下面为 CPU 时间中位数;MB 使用十进制。 机器、数据和脚本与原审计一致,使用真实临时 SQLite WAL 和 128 维本地向量。
单位:CPU 微秒/次,最新主线 → 最终 PR。
| 路径 | N=1 | N=10 | N=100 |
|---|---|---|---|
| 按重要性取前 10 条 | 22.9 → 21.4 | 45.6 → 42.3 | 50.1 → 41.4 |
| 同来源最新记录 | 15.9 → 14.4 | 15.9 → 14.7 | 21.0 → 14.6 |
| 关键词检索 | 4.3 → 3.4 | 37.8 → 30.2 | 361.6 → 288.7 |
| 混合召回 | 82.2 → 80.0 | 339.3 → 316.2 | 3,037.5 → 2,555.0 |
| WHY 召回 | 47.7 → 45.9 | 453.9 → 423.5 | 3,236.2 → 2,687.0 |
| 向量语义候选 | 11.6 → 13.4 | 54.0 → 53.5 | 70.6 → 64.0 |
| 两跳邻域 | 17.4 → 15.2 | 50.1 → 59.3 | 368.4 → 59.3 |
| N 条原子插入 | 75.7 → 76.6 | 278.9 → 177.5 | 2,291.2 → 1,185.3 |
N=10,000,单位:CPU 毫秒/次。
| 路径 | 主线 | 最终 PR | 倍数 |
|---|---|---|---|
| 按重要性取前 10 条 | 0.9576 | 0.0398 | 24.04× |
| 同来源最新记录 | 0.6016 | 0.0146 | 41.35× |
| 关键词检索 | 33.7453 | 26.5098 | 1.27× |
| 混合召回 | 93.0620 | 66.5310 | 1.40× |
| WHY 召回 | 91.0855 | 67.1605 | 1.36× |
| 向量语义候选 | 1.8507 | 0.9890 | 1.87× |
| 两跳邻域 | 40.3057 | 0.0595 | 677.77× |
| N 条原子插入 | 524.3310 | 431.6040 | 1.21× |
| 显式提供实体的图写入 | 37.8323 | 2.3085 | 16.39× |
稠密图 N=100 的混合召回为 18.324 → 16.866 ms,约 1.09×。主线 已经带来大部分图缓存收益,因此不再沿用旧基线的 6.51×。普通 N=10,000 混合 召回的累计分配为 78.85 → 49.10 MB,减少 37.7%。
小规模仍有取舍:N=10 邻域查询为 50.09 → 59.34 µs;N=1 向量/文本语义路径 分别为 11.57 → 13.36 µs、11.75 → 13.79 µs。N=10,000 实体集合扫描约慢 4%,保留策略接近持平(170.104 → 171.657 ms)。这些退化保留在数据中。 未改算法的向量读取也有时间波动,不能把较小的差别全部归因于算法。以上是共享 开发机器上的观测,不是线上延迟承诺。
完整最终数据:主线、 最终 PR。额外的解码缓冲 对照采用 3 轮、200 ms,每轮测混合/WHY 召回;它没有混入上述最终样本。
当前复杂度结论
| 部分 | 相对当前主线的变化与限制 |
|---|---|
| 来源/时间、重要性/时间的有限查询 | 兼容索引的查询约为 O(log N + K);全库时间排序改为顺序索引扫描 |
| 多路召回 | 主线已有邻接缓存。设 E_U 为展开节点读到的邻边数,余弦相关成本从 O((N+E_U+C)d) 降为 O(Nd+E_U+C);每个邻域的完整排序仍保留 |
| 精确向量扫描 | 仍是 O(Nd);固定维度下,临时解码数组的累计分配从 O(Nd) 降为 O(d) |
| 语义候选与 Diff | 前 K 名的选择从 O(M log M) 改为 O(M log K),选择空间从 O(M) 降为 O(K) |
| 有限 BFS | 按实际邻域读记录与边,保留原插入顺序、节点/深度限额;不再随无关的全库规模加载数据。高出度仍有成本 |
| 原子写入 | 事务内复用预编译语句;索引维护仍有 O(B log(N+B)) 工作及提交 I/O |
| 未命中、保留策略、导入 | 子串/实体未命中仍可能全库扫描;保留策略一般 O(E+N log N),逐条精确比对的批量导入仍可能 O(BN+B²) |
关键词与精确向量检索没有改成近似算法。访问预算限制访问数量,但不能免除读取、 排列高出度邻域的成本。小规模耗时不足以独立证明 Big-O,结论还结合代码、查询 计划、分配量和确定性的操作计数。
验证
- 最终实现通过
go build -o mnemon .、make test、Memory/命令层 race 检查, 以及全部 258 项 CLI E2E 断言。 - npm 测试 13 项通过;上游 OpenCode 运行时和 ZCode shell hook 套件在本机 通过。macOS 上跳过了 Windows PowerShell 专用探针,未将其写为已通过。
- 独立遍历对照已更新为主线
5c98ff9c,覆盖四种意图、三档预算、重叠锚点、 同分、环路、删除节点、零/负相似度及维度不匹配,分数和来源标签一致。 - 验证调用方无序快照不被修改、时间锚点结果不变,以及解码数组扩缩容、非法数据、 有符号零、非正规数、无穷和 NaN 的位值。原有索引迁移、事务回滚、压缩和 BFS 等价性检查也通过。
保留原有等分锚点/结果顺序的不确定性,不承诺逐字节排序不变。未调用付费模型, 未运行 Agency/Docker 集成总入口;基准不包含 CLI 启动、网络或冷文件缓存。