Notist
On this page
  1. 内容执行内核重构与性能验收
  2. 范围与表示
  3. 验证
  4. 测量方法
  5. 结果
  6. 边界

内容执行内核重构与性能验收

范围与表示

公开 Node/Expr 分离版本先提交为 efec73e。本轮移除过渡执行模型:

  • 删除 notist-eval/src/frame.rs、EvaluationState、PresentCheckpoint 与捕获代换函数。

  • 内容值保存不可变构造计划;不透明调用与循环持有共享检查代码和 COW 词法环境快照。绑定计算内容插值,挂载直接生成最终 Node。

  • 重复挂载共享代码和环境,不缓存最终挂载结果;后续绑定通过 COW 保持词法遮蔽与各次循环捕获独立。

  • 聚合预算溢出只截去当前输出后缀,从不可变源码边界构造 Error,不备份或回滚已修改的调用字段。

  • 无映射、无表达式且结构有效的具体内容可直接共享孩子存储。来源展开链在输出时附加,空原链共享同一展开后缀。

  • core 删除 PendingEvaluation;RExpr.expression 直接保存 TypedExpr。Node 表达式、内容孩子、Call、Content 森林和循环模板使用共享 COW 存储。serde 的共享容器透明编码。

  • EvaluationContext.has_mappings 为自定义宿主保守返回 true;pipeline 和 benchmark 宿主声明实际映射情况。

  • is_evaluated_interpolation 更名为 is_group,不再用执行历史描述普通内容。

逻辑预算继续计入会溶解的挂载;不按最终节点数重新定义配额。循环、资源请求、未准备输入、局部失败恢复、非空属性分组和实际构造身份规则保留。已知失败在检查树中统一表现为 Error,来源孩子保留供检查,执行不访问这些孩子。

验证

  • cargo test --workspace --all-features --locked --offline --no-fail-fast -- --test-threads=1:780 项通过,88 个测试/文档测试目标,无警告。

  • python3 -m unittest discover -s tools -p 'test_*.py':53 项通过。

  • benchmark:58 个场景通过语义和完整结果自校验。

  • git diff --check:通过。

新增直接验证代码存储共享、词法环境快照、未使用循环不执行 subject、具体内容共享后修改隔离、错误源码孩子不执行,以及来源链的共享、顺序与独立修改。原有预算测试改为验证生产内核的重复执行、源码不变性和独立构造计数,不保留失去意义的 checkpoint 对照执行器。

历史源码插桩探针属于固定版本实验:SSG 探针测试固定在 18f893a;字段/checkpoint/来源探针固定在 e5c65a3。字段探针对闭包内核明确拒绝运行,避免把其它操作的开销冒充已经删除的旧字段成本。新内核使用维护中的 eval-bench 驱动测量。

测量方法

原始证据目录:/tmp/opencode/notist-execution-kernel-final

当前代码、构建环境、二进制和哈希冻结在 manifest.json、workspace.patch、source/ 与 bin/;完整源冻结成功完成。比较使用三个冻结版本:原始基线、efec73e 对应的适配层实现、新闭包内核。

三轮重新计时,每个版本每轮一个新进程、每个场景五次采样、目标每次 20 ms;顺序为「原始/新内核/适配层」「适配层/新内核/原始」「原始/新内核/适配层」。采用进程内采样中位数,再取三个进程中位数。相同 rustc 1.97.1 和 release 构建环境。分配统计由独立插桩二进制采集;同一场景的模块与文档源代码在三个版本间完全相同。

时间包含求值及结果销毁,不含解析、检查、HTML 或磁盘 IO。未固定 CPU 频率、未隔离后台负载;这是初步暖态合成场景对照,不是整站构建速度或 RSS 预测。旧结果保留调用外壳,新结果按属性溶解,因此原始基线与新内核不是完整结果树相同的纯实现 A/B。每个版本各自进行完整结果校验。

结果

场景

原始 µs

适配层 µs

新内核 µs

新/原始耗时

原始/新分配次数

ready_text/128

12.69

31.90

3.22

0.25

11/6

native_text/128

77.05

126.52

74.29

0.96

3088/2842

code_calls/128

203.70

297.22

130.68

0.64

7982/5296

capture_uses/128

90.95

135.38

79.07

0.87

3508/2865

replay_call/128

183.87

248.87

118.52

0.64

7096/4669

loop/128

145.60

196.51

116.18

0.80

6611/5054

capture_dead_branch/128

14.94

26.57

1.77

0.12

736/74

many_parameters/128

49.07

100.75

35.55

0.72

903/494

read_text/128

267.02

372.99

192.29

0.72

11443/8629

json_cached/128

389.34

493.06

311.55

0.80

16073/13259

nested_expansion/16

15.87

20.19

10.68

0.67

535/356

新内核在本次 58 个场景中均快于适配层;56 个快于原始基线。剩余 native_text/1 约慢 15%,strict_lets/128 约慢 3%;前者是单个小调用的固定开销回退,后者需要更受控的测量区分小差异与噪声。不能宣称所有负载均加速。

code_calls/128 的瞬时增量请求堆峰值从 189047 降至 126565 字节,结果存活增量从 160106 降至 79560 字节。ready_text/128 的结果存活增量很小,主要因为结果复用基准已持有的输入孩子;输入存储并未凭空消失。这些计数排除预先保留的输入、程序和暖缓存,不是总堆或 RSS。

paired-comparison.json 保存三版全部逐场景事实、时间、分配与运行顺序;paired-*.json 和 logs/ 保存重新计时的原始结果。不要把最初因源快照在测量中变化而未通过完整性验证的 notist-execution-kernel-performance 目录当作最终证据。

边界

此内核不再有旧执行树适配或捕获代换。环境仍按名称查询,COW 保存整个当前词法映射,不是最小自由变量槽位布局;构造计划仍有绑定与挂载遍历,不是字节码 VM。后续可据 profiling 优化这些独立成本,不应把它们误称为尚未清除的旧 Frame 桥接。