Notist
On this page
  1. 路径复用优化与整站 A/B
  2. 结果
  3. 实现
  4. 测量方法
  5. 时间与内存
  6. 分配证据
  7. 回归验证
  8. 限制

路径复用优化与整站 A/B

结果

基于 9a3c5f7,在 perf/path-reuse 分支实施局部路径复用,不引入全局路径 ID 或授权缓存。7 组交错 A/B 中,优化后均更快;配对耗时变化中位数为 -4.22%。独立诊断构建的成功分配 API 调用减少约 120 万次 malloc、346 万次 realloc;峰值 RSS 基本不变。18 次完整构建的全部输出均与冻结基准一致。

实现

  • src/resources.rs:绝对路径直接规范化,不先与根目录 join 后再重建;normalize 按输入长度一次预留缓冲区,避免逐分量扩容。不改变词法规范化规则。

  • src/resource_session.rs:read/source_shared 解析一次路径,随后读取、解码、缓存查找和诊断共用它;grant 返回借用的根相对路径,不创建临时 PathBuf。请求计数、数据授权和输入缓存规则保留。

  • src/publication/mod.rs:输出冲突检查使用借用路径作为 BTreeMap 范围边界;已发现祖先冲突时短路,不再复制范围起点或继续查后代。

  • crates/notist-ssg/src/build.rs:链接和嵌入解析借用已有输出路径,空路径链接借用 origin,目录默认页只拼接一次。

  • DocumentIndex 的来源/输出索引只做精确查询,改为 HashMap;仍先按来源路径排序确定输出别名优先级,不使用哈希表迭代顺序选择目标。出版产物排序和冲突检查仍使用原有有序结构。

没有更改磁盘边界检查、symlink 策略、来源身份、相对路径基准、别名优先级或错误信息;没有跳过产物内容核对。

测量方法

证据目录:/tmp/opencode/notist-path-reuse-verified-20261109。基准目录:/tmp/opencode/notist-hotspots-9a3c5f7-20261109。工具:tools/profile_path_reuse.py、tools/test_profile_path_reuse.py。

  • 基准使用相同提交的普通 release 与 frame-pointer 可执行文件,并核对摘要;候选冻结源码后以相同 BUILD_ENV 构建,两种配置各有独立 Cargo target。

  • 候选的五个已修改 Rust 文件均与冻结副本逐字节摘要一致。

  • 复制独立站点输入,不修改 consumer 或先前证据目录。

  • 工作负载为 CLI 完整站点 build:51,739 页,78,004 项输出,共 451,812,631 字节。

  • 两次预热后进行 7 组普通 release A/B,逐组交替 before→after/after→before;不剔除样本。

  • 另以 frame-pointer 构建各运行一次分配 probe,不将探针耗时混入普通计时。

  • 共 18 次构建,每次在计时结束后核对全部输出的长度与 SHA-256;最终再验证冻结源码、二进制、输入与输出。

时间与内存

指标,中位数

基准

优化后

wall

9.215 s

8.702 s

user CPU

8.234 s

7.848 s

system CPU

1.164 s

1.132 s

maxrss

2,830,328 KiB

2,831,248 KiB

两组 wall 中位数之比改善约 5.56%,与“逐组求比值后取中位数”的 4.22% 是不同统计量;优先报告配对结果。7 组配对变化为 -3.43%、-9.26%、-5.56%、-8.70%、-2.45%、-4.22%、-0.92%。配对中位数的局部 bootstrap 95% 区间为 -8.70%~-2.45%,仅反映本机这组样本,不是跨机器独立重复的保证。峰值 RSS 差约 920 KiB,均约 2.70 GiB,不声称降低峰值内存。

首次向空输出目录发布的基准预热为 11.805 秒,候选预热为 8.944 秒;二者条件不同,不能据此宣称首次发布加速。计入统计的样本均已有产物,仍重新执行完整构建,发布阶段核对未变内容;不是编辑后的增量构建。

分配证据

成功分配 API 调用,父进程精确计数

基准

优化后

减少

malloc

132,729,790

131,528,192

1,201,598

realloc

14,726,628

11,267,873

3,458,755

calloc

37

37

0

分配包装器调用原 glibc 实现;不包含扩展子进程、采样器自身递归分配或同时存活对象的归因。malloc/calloc 以 1/2048、realloc 以 1/256 概率采栈,两次分别得到 122,669/108,556 条记录,均找到应用帧,记录丢失为 0。原始样本中,最近应用分配点为 resources::normalize 的 realloc 样本从 10,935 条变为 0 条;基准逆概率估计约 280 万次,对应移除逐分量扩容的预期。没有采到不等于一般性证明所有输入都不会 realloc;这些数字也不表示每次 realloc 都发生物理复制。

这是组合改动的总收益,未分别对每项做消融,不能将全部改善单独归给 HashMap、预留容量或某个路径调用点。没有重新采 CPU 栈,因此不声称原先约一成的路径比较 CPU 已降到某个比例,也不声称解决全部宿主路径开销。

回归验证

  • CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 CARGO_PROFILE_TEST_DEBUG=0 cargo test --locked --offline --workspace -j2 -- --test-threads=2:845 项通过,0 失败。

  • python -m unittest discover -s tools -p 'test_profile_*.py':67 项通过,0 失败。

  • 定向 rustfmt 检查与 git diff --check 通过。

  • 新增路径词法规范化、绝对/相对路径及非 UTF-8 测试。

  • 新增缓存命中、路径别名、UTF-8 错误和缺失文件情况下只解析一次路径的测试;原有请求预算、授权和输入视图测试全部通过。

  • 文档索引测试同时使用正序和逆序输入,确认精确来源优先、输出别名及目录索引选择不变。

  • profiling 工具新增禁止覆盖证据、基准提交匹配和二进制篡改检测测试。

初次常规 debug 全工作区构建在链接时写入失败;仅清理本 worktree 此次生成的 Cargo target,禁用测试调试信息后重新完成全部测试。另一个准备超时的证据目录未用于测量。本报告只使用 verified 目录中的完整实验。

限制

没有测试不同规模站点、serve 编辑、LSP/Worker 交互或严格冷缓存场景。本轮不引入路径驻留,也不扩展 SourceId 的语义;后续是否需要构建局部路径身份,应由新的调用栈和复用边界证据决定。