AS-OF:2026-09-22。四轮实测探究的时间快照,数字仅对当日环境负责;复跑方式见 §7 探针资产。 口径:本机 AMD AI Max 395(高性能机,低端/移动端应按更差预估;跨机引用一律用比值不用绝对值);moon 0.1.20260915;vitro/engine@0.4.0;Rust 侧用
native/target/release/vitro_cli.exe现成产物(冻结区,只跑未改)。 复跑:2026-09-22 同日晚经贡献者机(Intel i9-14900HX 笔本)重建全部探针后四轮复跑——核心比值全部复现、无一翻转,wasm 反超面扩大至 7/7;§1–§4 数字保持原机 as-of 不动,复跑数字与新发现见 §8,压力两维(arrinit/body)初测倍率已经 §9 勘误重估。 复跑 2:2026-09-26 S6 执行器落地后(vitro/engine@0.5.0)原机四轮复跑 + 执行层首测(兑现 §10 义务①)——管线/压力/时间旅行全部复现,bubble200 修正为可跑完(§11.4),wasm 反超面 6/7→2/7,构建时间新发现(cmd/run 链接 cliff,§11.8),全 MoonBit 栈对拍 356/366(§11.5);见 §11。 复跑 3:2026-09-29 S7 批五号(wasm-gc 单出口,2f18e10)落地后,原机按 §7 全探针复跑——本轮最大变量是环境而非代码:本机每进程启动开销已从同年 9-26 的 5.8-13ms 涨到 145-190ms(同机同二进制实测),dangerouslyDisableSandbox无改善 ⇒ §1/§2/§9 的「逐进程/逐文件」口径本轮不可复跑,逐层与逐文件绝对值一律不得引用;可引用结论 = 执行层(§12.2):wasm-gc 跑完整引擎比 native 快 2-2.8×,而管线层只能记「持平或略优」;§11.9-4 的「管线 1.24× 翻转」按不可复现、归因不可定销账(同日方法对齐 A/B:0.5.0 与 HEAD 中位重合)。另发现全量 native release 构建因 gateway 的+native声明必失败(LNK1561,已给验证过的拆包修法),以及启动开销可归因到「进 main 之前 ~148ms」。详见 §12。 探针纪律:全部探针与产物置于tmp/perf_probe/(gitignore/tmp/覆盖),git 工作区零流入;当日git status与探针前逐字一致。 结论速览:①管线层 MoonBit(native)比 Rust oracle 慢 1.4–1.6×,压力端恶化至 ~3×;②时间旅行(unified)是性能累赘实锤——每步全量快照 21μs(全速 320×),vs CPython 慢 3–4 个数量级,病灶是每步 CPU 而非内存;③wasm-gc 主场景 6/7 场景持平或反超 native,比 native 快 1.7×(lexer)/2.3×(GC);④路线裁定:bytecode→wasm 生成器为全速执行正解,模板超级指令搬运计划退役。——四条均经贡献者机复跑复核(§8)。
1. 第一轮:活跃区管线基线(native)
四层 dump 入口(cmd/ 差分工具,native release)对 baseline 365 例,3 轮中位,端到端口径(含进程启动与写盘):
| 入口(层) | baseline 365 | knr 81 | leetcode 138 | gap 16 |
|---|---|---|---|---|
| dump_tokens(lexer,raw+pp 双遍) | 0.37s | 0.13s | 0.22s | 0.02s |
| dump_ast(parser) | 0.26s | 0.10s | 0.19s | 0.02s |
| dump_typeck | 0.26s | 0.12s | 0.24s | 0.02s |
| dump_compile(codegen) | 0.30s | 0.13s | 0.25s | 0.02s |
- 四层全跑 ≈1.2s,每例全管线 ≈3.3ms;单文件全管线延迟中位 12.3ms(n=10,含启动);gap 16 例 0.02s ≈ 纯启动下限
- 构建/防线:
moon clean后全量 release native 构建 6.2s(37 tasks,不含 core 预编译恢复);moon check热 0.65s;moon test全绿 2.4s(例数以 factsmoonbit_test_passed真值为准——原机记录时点后 +1,见 §8.3-①) - 语料全量仅 ~350KB,"MB/s 吞吐"无意义,以每例毫秒与总耗时为准
2. 第二轮:用户场景 + Rust oracle 对比 + 压力测试
用户场景(教学 IDE 后端 = vitro_cli compile/run,执行层 Rust 承担,moonbit 执行器未到 S6):baseline 365 例全量 compile 中位 8.2ms、run 9.9ms,p90 11.3ms,零超时;6 个非 0 退出逐一归因全是诊断用例(e2_angle_local_header / e2_include_cycle / e2_include_not_found_* / e3_static_assert_fail / j1_declarator_depth),预期行为。
同层对比(两侧均 native release,同口径):
| 维度 | Rust | MoonBit | 倍率 |
|---|---|---|---|
| 进程启动 | 4.6ms | 11.4ms | 2.5× |
| tokens 层目录批处理(baseline 365) | 0.24s | 0.35s | 1.4× |
| compile 层逐文件单文件中位 | 8.9ms | 13.3ms | 1.5× |
压力测试(自生成 6 维度 × 3 规模档 17 文件,tmp/perf_probe/stress/;排除 4 个两侧皆设计性拒绝文件后 13 文件逐维度):
| 维度 | MoonBit/Rust 倍率(小→大档) |
|---|---|
| 深嵌套循环(14 层) | 1.40 → 1.61× |
| 大数组初始化(5 万元素) | 1.47 → 2.39× |
| 大平铺多函数(8000 个) | 1.93 → 2.85× |
| 巨体单函数(5 万语句,684KB) | 1.97 → 3.03× |
| 海量局部变量(5000 个) | 2.32 → 3.27×(最差) |
规律:差距随输入规模扩大拉大,纯吞吐趋近 3×。优化定位优先看 locals(槽位分配)/ flat(全局符号注册)/ body(块线性扫描)。
设计性拒绝两侧同构(压力语料意外收获):表达式链超 AST 深度预算 512(Rust ParseError code 1006 / MoonBit stage=parse fail_json)、全局数据区 60KB 上限(MoonBit 拒绝文本与 Rust 逐字相同——照搬纪律的体现)。出口形态不同:Rust rc=1+stderr,MoonBit rc=0 + fail_json 产物(产物名 <stem>.c.compile.json,stem 含 .c)——moon dump 工具 rc=0 不代表成功,须查产物 ok 字段。
3. 第三轮:时间旅行性能裁定
裁定:时间旅行现状实现是性能累赘(实锤)。 初始结论曾误判"57ms 封顶、成本可控"——系 baseline 小语料步数太小无法暴露 O(步数×状态) 爆炸;换真实程序 + 外部对象(CPython 同逻辑)对比后反转:
| 程序 | CPython | Vitro run 全速 | Vitro unified 时间旅行 |
|---|---|---|---|
| fib(20) 递归 | 0.5ms | 18.6ms | 6.1s |
| 冒泡排序 200 元素 | 3.3ms | 20.1ms | 60s 超时跑不完(§11.4 修正:75s 上限下 68.8s / 1,621,540 步跑完,原判定系超时设置截断) |
| 500×500 嵌套循环 | 13.9ms | 26.4ms | 60s 超时跑不完 |
- 全速 run vs CPython:1.9–37×(可用);unified vs CPython:4300–18000×(灾难)
- 记录开销:每步 21μs(fib20 共 284,591 步/6.1s),全速同程序 65ns/步 → 320×
- 归因(读码
native/src/unified/):每步全量快照(vm.snapshot/snapshot_into:变量+数组+指针+access log)+ payload 全历史驻留;教学单步语义是语句级,指令级全量记录无消费方 - 内存维度实测修正(曾误判"移动端直接 OOM"):ctypes 采样峰值——run 2.0MB,unified fib 28.3MB / bubble200 46.6MB / arr_10000(万元素数组)51.6MB,内存温和(几十 MB 级);engine.rs 注释中 63.6GB 前科系 replay 负索引 bug(已修)非常态。真病灶是每步 CPU(collector 无条件重建快照对象),不是内存
- VM guest 地址空间 =
MEM_SIZE1MB(moonbit/bytecode/memory.mbt与crates/vitro_runtime/src/memory_state.rs同构同值):全局区 64KB 上限(可用 60KB)、堆 0x5000 起、栈自 1MB 顶下延。状态天然有界 → 全量检查点上界 1MB/个,checkpoint 方案上界可证明 - 常态资源画像:单次 run 峰值工作集 2.0MB/提交 0.4MB(轻量级,与任务管理器常驻读数 39.4MB 是不同口径)
优化方案(权重修正版,按杠杆排序):
- 按需物化(主攻):collector 惰性化,每步只记最小事实(步号/PC/写集),变量表/数组快照仅在 UI 请求该步时从最近检查点+重放构建——直接砍掉 21μs 大头
- checkpoint + 确定性重放:每 N 步全量检查点,回退=最近检查点+重放 ≤N 步(教学 VM 确定性是天然优势;重放千步 <1ms)
- 写集 undo log:每步只记"地址+旧值",单步回退 O(1);collector 已有
AccessType::Write观测基建 - 语句边界粒度 + 环形历史窗口(次要):指令级不记;学生实际回退最近几十步,环形覆盖封顶内存
- 协议解耦:
StepPayloadv0.1 已冻结(61/61 回放)、TS 层免役——优化全部动在引擎内部,呈现协议不动 - 预期:每步 21μs → <0.5μs,冒泡排序时间旅行从 60s+ 跑不完进秒内;移动端真实约束是低端机延迟 ×3–5 后是否无感(按重放 <1ms 账,成立)
4. 第四轮:wasm-gc 全面测试 + 路线裁定
背景:主场景是 wasm(浏览器/TS 层),此前全部数据是 native。独立 MoonBit 模块(tmp/perf_probe/wasm_bench/,mooncakes 装 vitro/engine@0.4.0,不触碰工作区)8 场景 argv 参数化基准,双后端同题对比,逐场景扣除启动开销。
首轮单点:2000 次 tokenize(856B×4 源)——moonrun(V8/TurboFan)137ms vs native exe 230ms,wasm 快 1.7×。
二轮全面(12 文件语料):
| 场景 | wasm-gc 纯算 | native 纯算 | 倍率(w/n) |
|---|---|---|---|
| lexer(×200) | 37.7ms | 62.0ms | 0.61× |
| parser(×150) | 65.3ms | 82.4ms | 0.79× |
| typeck(×100) | 58.3ms | 61.5ms | 0.95× |
| codegen(×100) | 82.4ms | 92.2ms | 0.89× |
| GC 分配压力(Map+Array ×200) | 14.8ms | 34.3ms | 0.43× |
| lexer 大输入(12 文件拼接 ×50) | 15.0ms | 12.3ms | 1.23×(唯一弱项) |
| 深递归 400 层 ×2000 | 毫秒级安全 | 毫秒级 | — |
- 启动:moonrun(V8+wasm 实例化)21.6ms / native 10.3ms
- 产物体积:wasm 375KB vs exe 820KB(-54%)
- 唯一弱项=大批量:大输入慢 23%;缩放检查 12× 输入=18.3× 时间(超线性,疑似 GC/内存增长;native 亚线性 9.2×)。绝对值 μs 级,教学规模(~450B/文件,15μs/次)无感;批量属 CI/对拍管道场景由 native 承担
- 总评:6/7 场景 wasm-gc 持平或反超 native;管线全链折算 ≈ Rust 的 0.9–2.8×,典型负载基本追平——"月兔完整实施后会更差"在主场景不成立(native 后端 1.5–3× 的劣势只属于次要的桌面场景)
- 未测口径:SpiderMonkey/JSC(moonrun=V8)、浮点密集、js 后端
路线裁定:
- 全速执行正解 = bytecode→wasm 生成器(用户提出,实测与读码坐实):opcode 包 Instruction 为栈式三元组(opcode+单 operand+loc),wasm 亦栈式——
PushConst→i32.const、算术→i32.*;1MB 平铺内存→wasm memory 16 页,指针=i32 地址 load/store 直译;越界=wasm 原生 trap 白送且可转教学诊断(现 VM 手写 bounds check);host libc→wasm import。主要工程量仅一处:跳转→wasm 结构化控制流(stackify 类;第一版可函数内 dispatch loop 保守形态,照样吃 V8 JIT)。平台一次覆盖:浏览器/Node/wasmtime/移动 webview;iOS W^X 限制消失(JIT 是引擎特权) - 模板超级指令搬运计划退役(收回"可搬月兔"旧建议):其前提"自研解释器承担全速执行"在 wasm 主场景下不成立;组合爆炸维护债照搬即负资产。解释器只服务单步/时间旅行,观测才是价值
- 与双模式架构对齐:run 全速=wasm 生成器产物;unified/单步=月兔解释器+按需物化(§3)
5. 路线总图(性能改进杠杆,按收益排序)
| # | 动作 | 空间 | 批次归属 |
|---|---|---|---|
| 1 | 时间旅行按需物化 + checkpoint + 写集 | 每步 21μs→<0.5μs(320×) | S6 后执行器批的前置设计输入 |
| 2 | bytecode→wasm 生成器(run 全速) | 对比解释器形态 10–100× | 复用 S5 bytecode+14 键 schema |
| 3 | 压力三维(locals/flat/body)记账不动手 | ~3×,教学规模无感 | 触发线:真实场景端到端 >100ms |
| 4 | 编译管线 | 已毫秒级 | 不动 |
| — | 模板超级指令搬运 | 退役 |
6. 测试方法学坑(全部亲历,防复发)
- vitro_cli 子命令是字面量:
[exe, file, "-o", out]漏写dump-compile会静默打印 usage(365 例"全失败"假象)——差分驱动脚本必须断言输出形态 - MoonBit 缺参 fail 路径有 backtrace 成本:测启动开销必须用正常路径调用(缺参 76ms vs 正常 11.4ms 假象)
- moon dump rc=0 不代表成功:失败走 fail_json 产物,查产物
ok字段 - 小语料测不出超线性爆炸:baseline 几百步的程序把时间旅行测成"57ms 封顶";压力语料必须让步数上真实规模
- 绝对值不可跨机外推:本机 AI Max 395;跨机引用一律用比值(vs CPython / vs native)
- 忽略区探针也有构建约束:
moon.modimport 是 module 依赖,包级 import 必须写moon.pkg;const名大写;Windows 路径反斜杠禁止进字符串字面量(os.path.basename先处理) - 内存采样禁止轮询(贡献者机复跑亲历,同日):采样循环按 interval 轮询
GetProcessMemoryInfo会拖慢被测子进程——unified fib20 实际 8.1s 被拖成 >60s 假超时(拖慢 8×+)。峰值工作集应在进程退出后单次读内核维护的PeakWorkingSetSize(等效且零干扰);分钟级长程序轮询失真不明显,秒级/亚秒级程序必中招(§3 的 run 2.0MB 疑同因低估,见 §8.3-④) - (2026-09-26)Rust
dump-tokens必须同时给--out与--raw/--pp之一:缺任一 rc=1,压力 17 文件全体假拒绝——新写驱动前先跑一例核对子命令参数形态(坑 1 同族复发,亲历) - (2026-09-26)MoonBit dump 产物为紧凑 JSON(
{"ok":true}无空格):按"ok": true带空格形态文本匹配全 miss;ok字段判定需兼容两种空格形态(坑 3 的匹配层细节) - (2026-09-26)moon build 指定包用相对 module 根的裸包名:
moon build lexer可、moon build moonbit/lexercanonicalize 失败;且增量判定对 mtime 不敏感(touch 不触发重编)——单包编译实验须做内容变更,或改用"逐包推进"(见坑 11) - (2026-09-26)全量构建时间分解用"逐包推进":
moon build <pkg>按依赖序逐包推进、每步计时,一发定位慢点;moon -v输出经管道全缓冲,逐命令时间戳测不出(亲历无效实验,白付一次全量) - (2026-09-26)
unified默认--max-steps 100000:fib20(284,591 步)被静默截断且摘要报"可能存在无限循环"——复跑必须显式放大;它也是 §11.4 bubble 修正的直接原因(60s 超时 × 步数上限双截断假象) - (2026-09-26)解析 CLI wrapper 先抓完整
repr采样、再写正则:Rust run 的 wrapper 含全角标点(程序运行完成,返回值:)、完成行之后还可能粘引擎泄漏报告附注、[warning]/[stderr]呈现行混入 stdout、Windows 管道 CRLF、MoonBit 侧 Latin-1 逐字节展开——本轮 5 发才中,全部可由一次采样避免(防误剥程序自打的伪装附注:附注剥除须验证块体纯度,且只剥尾部)
7. 探针资产与复跑
| 资产 | 位置 | 复跑 |
|---|---|---|
| 管线吞吐 | tmp/perf_probe/bench_pipeline.py |
python bench_pipeline.py --rounds 3 |
| 多维对比(启动/批处理/逐文件/用户场景) | tmp/perf_probe/bench_compare.py |
python bench_compare.py |
| 压力语料生成(6 维度 × 3 档) | tmp/perf_probe/gen_stress.py |
python gen_stress.py |
| 时间旅行三线对比 + 内存采样 | tmp/perf_probe/ext_cmp/(含 C/Python 等价基准) |
见脚本内联 |
| wasm-gc 全面基准(8 场景) | tmp/perf_probe/wasm_bench/ |
`moon build --release --target <native |
| 执行层对比(2026-09-26 新增) | tmp/perf_probe/bench_moon_run.py |
python bench_moon_run.py(MoonBit run.exe vs Rust run × baseline;预编译 exe 直跑) |
| 压力驱动(§9.3 同口径重建,2026-09-26) | tmp/perf_probe/run_stress.py |
python run_stress.py(dump vs dump 逐层计时 + 查产物 ok 字段 + 执行层附加段) |
| 时间旅行四线对比(2026-09-26 重建) | tmp/perf_probe/ext_cmp/run_cmp.py |
python run_cmp.py(CPython/Rust run/Rust unified/MoonBit run;内存=退出后单次读 PeakWorkingSetSize) |
| wasm-gc 8 场景驱动(2026-09-26 重建) | tmp/perf_probe/wasm_bench/run_bench.py |
moon.mod 依赖随发版升级 → 双后端构建 → python run_bench.py |
| 全 MoonBit 栈对拍(2026-09-26 新增) | tmp/perf_probe/diff_moon_run_full.py |
python diff_moon_run_full.py(baseline 逐例 stdout+返回码对拍 MoonBit cmd/run vs Rust run) |
探针位于 gitignore 覆盖区(
/tmp/、moonbit/_build/),不入库;清理不影响本档案结论的可复现性(生成器可重造全部语料)。 2026-09-22 贡献者机复跑注:上表探针未随库留存(持有人机本地),复跑时按本表口径全部重建(脚本重写、口径对齐),重建版同位于tmp/perf_probe/(gitignore 区,同样不入库):bench_pipeline.py/bench_compare.py/gen_stress.py+run_stress.py/ext_cmp/run_cmp.py(三 .c 基准内嵌) /wasm_bench/(gen_bench.py单源生成模块 +run_bench.py驱动)。复跑结果见 §8。
8. 贡献者机复跑(2026-09-22 同日晚)
AS-OF:2026-09-22 晚。贡献者复现验证轮:按 §7 口径重建全部探针后在本机复跑四轮,目的=验证 §1–§4 结论是否机器无关。核心比值全部复现,无一翻转。本节数字为贡献者机 as-of,与 §1–§4(AI Max 395)并列;跨机只比比值。 口径:Intel i9-14900HX 笔本(24 核 32 线程;CPUID 报 Family 6 Model 183);moon 0.1.20260920;工作区 HEAD
317dbbf(git 干净);vitro/engine@0.4.0;Rust 侧同用native/target/release/vitro_cli.exe现成产物(只跑未改)。
8.1 逐轮结果(比值口径,✅=复现)
| 维度 | 贡献者机 | 原机(§1–§4) | 判定 |
|---|---|---|---|
| release 全量构建(moon clean 后) | 9.11s / 37 tasks | 6.2s | ✅ 量级一致 |
moon test |
210/210 绿·AS-OF 2026-09-22(冷 2.86s/热 0.99s) | 全绿 2.4s(例数旧值,见 §8.3-①) | ✅ |
moon check 热 |
0.68s | 0.65s | ✅ |
| 四层 dump 吞吐(baseline 365) | 0.55/0.37/0.37/0.41s | 0.37/0.26/0.26/0.30s | ✅ 层序一致,整体 ~1.4× |
| 进程启动(Rust/MoonBit) | 14.4/23.5ms | 4.6/11.4ms | ✅ 倍率 1.6×(原 2.5×) |
| tokens 批处理倍率 | 1.3×(0.61/0.46s) | 1.4× | ✅ |
| compile 逐文件倍率 | 1.49×(26.3/17.7ms,p90 33.4/25.3) | 1.5× | ✅ 精确复现 |
| 用户场景非 0 退出 | 6 例清单与 §2 逐字一致 | 同左 | ✅ |
| 单文件全管线延迟(4 进程) | 132.5ms | 12.3ms | ✅ 归因=本机启动开销(4×~24ms 启动主导,非管线变慢) |
| unified fib20 | 7.9s / 284,591 步(与 §3 逐字同) = 27.8μs/步 | 6.1s / 21μs | ✅ |
| unified 冒泡 200 | >60s 跑不完 | 同 | ✅ |
| unified nested500 | 52.9s(灾难级) | >60s | ✅ 灾难判定不变 |
| unified 内存峰值(fib/bubble/nested) | 29.4/47.7/28.2MB | 28.3/46.6/— | ✅ 吻合(内存温和结论成立) |
| wasm-gc vs native 反超面 | 7/7(lexer 0.54× / GC 0.47× / typeck·codegen 0.66× / biglex 0.57×;启动 22.6/33.8ms) | 6/7(biglex 1.23× 唯一弱项) | ✅ 且更强(原弱项本机反超) |
| wasm 产物体积 | -44%(543KB/970KB) | -54% | ✅ 同向 |
- diff 驱动复测(d15a3be 后形态):
typeck_diff gap/parser_diff gap均 0.5s(提交声明 1.3s/1.2s,"秒级"成立) - wasm-gc 绝对值与 §4 不可比(复跑载荷不同:12 文件 90.4KB 内嵌语料),比值口径下结论增强;native 后端 1.5× 级劣势属于次要桌面场景的判定不变
8.2 压力五维(本机倍率 MoonBit/Rust,小→大档)
| 维度 | 本机初测 | 同口径重估(§9.3) | 原机(§2) | 判定 |
|---|---|---|---|---|
| 深嵌套循环(14 层) | 1.29→1.65× | 同初测 | 1.40→1.61× | ✅ |
| 海量局部变量(5000) | 2.40→2.42× | 同初测 | 2.32→3.27× | ✅ |
| 大平铺多函数(8000) | 3.25→3.81× | 同初测 | 1.93→2.85× | ⚠️ 系统性偏高 |
| 大数组初始化(5 万) | 6.31→13.87×(跨口径) | ~3.96×(697/176ms) | 1.47→2.39× | ⚖️ 勘误(§9.3) |
| 巨体单函数(5 万语句) | 2.71→0.54×(跨口径假反超) | ~3.5×(1124/318ms) | 1.97→3.03× | ⚖️ 勘误(§9.2/9.3) |
勘误(2026-09-23):初测 arrinit/body 两行系跨口径(Rust
compile不序列化产物 vs MoonBitdump_compile序列化 29–62MB 产物 JSON),重估后"13.87×"与"0.54× 假反超"均不成立;真缺口转为 §9.2 的 Rust compile 命令 O(n²)。后续引用压力倍率一律以重估列为准,初测数字仅作轨迹保留。
设计性拒绝同构复现:global_reject 拒绝文本两侧逐字一致(3 条;容器形态 Rust=数组、MoonBit=\n 合并单串——文本同构、容器异构,复跑脚本按文本口径机判);expr_reject 两侧同拒。勘误线索:Rust E1006 实测文本为"嵌套过深(超过 256 层)",§2 记"AST 深度预算 512"——疑两层预算(解析深度/AST 深度),待读码核对后勘误 §2(§8.3-⑤)。
8.3 新发现登记(复跑增量,按影响排序)
moon test真值 +1(已裁定):本机复跑实测 210 全绿,reports/facts.json的moonbit_test_passed当时为过时 cached 值;同日晚 CIfacts --run刷新真值为 210,与本机一致——裁定:上游真实增量,非环境差异。对账纪律:测试例数一律引 facts 真值键,文档不写裸数(§1 同步)。- Rust compile 命令 O(n²)(已归因闭环,初判勘误):初判"codegen 超线性"经逐层计时+读码反转——编译管线全程线性(dump-compile 5 万语句 318ms),超线性在
compile命令相对裸管线多走的算法检测层:native/src/compiler/cfg.rs两处 O(n²)(build_seq每语句建块+连边blocks.iter().find全表扫;find_unreachable_blocksDFS 每节点全量重扫边表)。§2"优化定位优先看 locals/flat"不受影响(管线无辜)。归因过程与交叉验证见 §9.2;修复前禁止以该路径作对比分母(§9.4)。 - arrinit/body 初测倍率系口径假放大(勘误):初测跨口径(Rust
compile无产物序列化 vs MoonBitdump_compile有,29/62MB JSON 实证)。同口径重估:arrinit 13.87×→3.96×、body 0.54×(假反超)→3.5×(§9.3)。§8.2 表已修正。 - §3 的 run 峰值内存 2.0MB 疑为低估:本机 run 退出后读
PeakWorkingSetSize实测 8.6MB;§3 的 2.0MB 来自轮询采样,run 全速 <20ms 退出,轮询大概率未及采样(坑 7 同因)。unified 值两机吻合(§8.1)支持此判断;"内存温和"结论不受影响,反而更成立。 - E1006 深度口径(见 §8.2 末):实测 256 vs 记载 512,读码核对后择一勘误。
8.4 复跑资产
同 §7 注:全部重建探针位于 tmp/perf_probe/(gitignore 区)。四轮命令:python bench_pipeline.py --rounds 3;python bench_compare.py;python gen_stress.py && python run_stress.py;python ext_cmp/run_cmp.py + wasm_bench/(python gen_bench.py → moon add vitro/engine@0.4.0 → moon build --release --target <native|wasm-gc> → python run_bench.py)。
9. 深挖:压力两维归因反转与对比口径裁定(2026-09-23,贡献者机)
本节是 §8.2/§8.3 初测的归因闭环与勘误,单源记录——后续引用压力倍率、Rust compile 缺口、月兔优化裁定一律以本节为准,勿再散引初测数字。
9.1 逐层计时(3 轮中位,ms)
| 语料 | MB tokens | MB ast | MB typeck | MB compile | Rust dump-tokens | Rust dump-compile |
|---|---|---|---|---|---|---|
| arrinit_s | 86 | 61 | 65 | 167 | 36 | 42 |
| arrinit_m | 142 | 113 | 109 | 367 | 52 | 98 |
| arrinit_l | 237 | 193 | 199 | 697 | 89 | 176 |
| body_s | 139 | 139 | 146 | 237 | 62 | 67 |
| body_m | 287 | 302 | 353 | 585 | 133 | 151 |
| body_l | 527 | 609 | 708 | 1124 | 252 | 318 |
读法:①两侧管线(含 Rust)全程线性——Rust dump-compile 67→151→318ms(语句 2.25×/2.1×);②同口径比值:tokens 层 ~2.1×、全管线 3.5×(body_l);③MoonBit body 各层均匀 2–3×,非单层塌陷。
9.2 真缺口:Rust compile 命令的算法检测层 O(n²)
vitro_cli compile(body_l)=2067ms vs dump-compile=318ms → 差值 1749ms(87%)在管线之外;差值曲线 20/183/1749ms(1万/2.5万/5万语句)超线性。
compile走engine::compile_pipeline::run_multi_file_pipeline(session 管线),相对cmd_dump_compile的裸四段管线多出:算法检测、补全快照、诊断/警告装配等附加阶段- 根因
native/src/compiler/cfg.rs(algorithm_detector 的 CFG 特征提取)两处 O(n²):build_seq(cfg.rs:399)——每条语句单独建基本块(5 万语句 = 5 万块/5 万边),fall-through 连接时blocks.iter().find(|b| b.id == from)每连一条边线性扫全块表 → 建图 O(n²)find_unreachable_blocks(cfg.rs:56)——DFS 每出栈一个节点就全量重扫整张边表找后继 → O(V×E)
- 交叉验证:flat_l(8000 个小函数,同为 5 万语句)compile 仅 175ms——每函数块数 O(1),总量线性,与两处 O(n²) 的"单函数巨体"触发形态吻合;
update_completion_snapshot只扫顶层声明(structs/globals/funcs 签名),排除 - 教学场景影响:几十行 → 几十个块,O(n²) 不可测;系压力语料才触发的债,baseline 363 例全小文件故从未暴露
- 处置:登记不修(与 5e315e6 O2 债同形态);若将来修复,冻结区走 §2 白名单(缺陷修复)+红→绿(先造单函数巨体压力锚用例);修复前禁止以该路径作性能对比分母(§9.4)
9.3 口径勘误:arrinit/body 初测倍率
初测跨口径:压力表拿 Rust compile(不序列化产物)比 MoonBit dump_compile(序列化产物)。产物体积实证:arrinit_l Rust 侧 62MB / MoonBit 侧 29MB JSON,body_l 达 88MB——序列化+写盘本身就是差值大头。
同口径(dump vs dump)重估:arrinit 13.87× → 3.96×(697/176ms);body 0.54× 假反超 → 3.5×(1124/318ms)。§8.2 表已更新,初测数字保留作轨迹。勘误教训入坑:跨引擎对比必须两侧同出口形态——compile 类"只报成败"命令与 dump 类"序列化产物"命令不可互比。
9.4 对比口径裁定(917251e 门 1 先例)
蓝图第一手复核记录第三/四轮:名义红 3.83× 系对照物失真(理想化 Rust 孪生比现役解释器快 23×),换产品口径后门 1 翻转为通过,教训入档——"比值结论必须声明分母引擎"。本轮是同构问题的镜像:病灶分母(Rust O(n²) compile)会让月兔显得好,方向相反、结构相同。
裁定三条:
- 禁止以 Rust compile 的算法检测路径作分母(§9.2 修复前);
- 月兔优化的度量只用三个健康口径:①自身优化前后同语料同口径;②vs Rust 健康管线(dump 口径)的比值;③教学绝对负载校准(≤10M 步 ≤1s、99 分位 ≤3s,沿复核记录第四轮);
- "Rust 区不优化"是冻结纪律使然(oracle 只许白名单/安全修复/防线维护),不是为对比服务的策略——O(n²) 按 §9.2 处置,不充当你追我赶的背景板。
9.5 月兔优化空间(档案闭合项不再投入)
已闭合(917251e 门 0–3 + 5e315e6 裁决):惯用法层(FixedArray 无去界检公开原语、编码形态 ±4%——"无隐藏杠杆,不再追加")、载体层(packed 1:3.8 实测)、VM 热循环(MoonBit-V8 快于现役解释器 3.3×、慢于 JIT 2.8×,S6 按条件 A 每指令 ≤迷你 VM×3 验收)、typeck O2 债(perf_budget 闸 8/200 挡着)。
真杠杆(§5 重申,门 1 数据背书):
- 时间旅行按需物化 + checkpoint + 写集(每步 21μs→<0.5μs,320×)——勘察期 C-2"Trap 回退改重放(消每步 1MB 快照)"即同方向;
- bytecode→wasm 生成器(10–100×)——门 1 证 wasm-gc/V8 为优势交付目标,路线裁定更硬;
- 管线压力维度(重估后 2–4×):维持"记账不动手"(触发线:真实场景端到端 >100ms);若触发,顺序 lexer(2.1×,码元访问/分配热点)> codegen > typeck(闸)。
10. 遗留与后续触发线
- wasm-gc 的 SpiderMonkey/JSC、浮点密集、js 后端三口径未测(不影响主线结论)
- typeck/codegen 在 wasm 上的比例数据已补(§4),但 timeck Map 重结构的大批量超线性根因(GC/内存增长)未深挖——批量管道仍走 native,无行动义务
- 执行器(S6 后)落地时:①把执行层纳入本探针体系(那是性能真正会动的层);②时间旅行按 §3 方案实现,不照搬 Rust 全量快照现状
- locals/flat/body 三维优化触发线:真实教学场景端到端 >100ms 或某语料跑不完
11. S6 执行器落地后复跑(2026-09-26,原机)
AS-OF:2026-09-26。S6 vm 片完成(HEAD 6c90c7f)、0.6.0 发版批决策前;vitro/engine@0.5.0;moon 0.1.20260920;原机 AMD AI Max 395(与 §1–§4 同机)。baseline 语料 366 例(= §1 的 365 + 上游 1 例)。 义务兑现:§10 行动义务①"执行器落地时把执行层纳入本探针体系"——新增 §11.3 执行层首测与 §11.5 全栈对拍。 探针纪律:新增/重建脚本置
tmp/perf_probe/(§7 表已更新);当日工作区另有 6 个并发改动文件(vm_diff/gen_host_route/ci 等另一开发线),本批零触碰、探针全部落在 gitignore 区。 结论速览:①§1/§2/§9 全部复现、无一翻转;②执行层首测:baseline 端到端 MoonBit/Rust = 1.42×,计算密集全速执行差 6–16×(杠杆 2 的 S6 后第一手证据);③时间旅行 21–23μs/步复现、fib 步数逐字复现,bubble200 修正为 ~69s 可跑完(§3 原判定系超时截断);④wasm-gc 反超面 6/7→2/7(管线三场景一致 1.24×,登记待观察);⑤构建新发现:cmd/run 链接 199s(run.c10.8MB 单 C 单元,cc -O2 超线性),编译期工具链债登记不动手;⑥全 MoonBit 栈对拍 356/366 逐例一致,新登记 va_copy 缺陷与自定义 include 缺口(§11.9)。
11.1 管线与防线(vs §1)
| 项 | 本次 | §1(0.4.0) | 判定 |
|---|---|---|---|
| 四层 dump 吞吐 baseline366(3 轮中位) | 0.451/0.287/0.284/0.344s | 0.37/0.26/0.26/0.30s(365 例) | ✅ +1.1–1.2×,层序形状一致 |
moon check 热 |
833ms | 0.65s | ✅ |
moon test |
实测时点(2026-09-26)433/433 5.04s;facts moonbit_test_passed 同日为 434(并发开发线 +1,§8.3-① 同形态) |
210 例 2.4s | ✅ 全绿,时间随例数近线性 |
11.2 多维对比与用户场景(vs §2)
| 项 | 本次 | §2 | 判定 |
|---|---|---|---|
| 进程启动 rust/moon | 5.8/13.0ms = 2.2× | 4.6/11.4ms = 2.5× | ✅ |
| tokens 批处理 baseline | 1.33× | 1.4× | ✅(stress17 批处理 2.4× 系新采口径,登记) |
| compile 逐文件 baseline | 1.58×(15.2/9.4ms) | 1.5× | ✅ |
| 用户场景 compile/run 中位 | 9.3/10.8ms(p90 11.0/12.6) | 8.2/9.9ms(p90 11.3) | ✅ |
| 非 0 退出 | 6 例与 §2 逐字一致 | 同 | ✅ |
| Rust dump-compile 异常 | 9 例 = 6 诊断 + include 族 3 例 | 6 例 | 口径注记:dump-compile 对自定义 include 3 例 rc=1 而 compile 不拒——命令间失败集合差异,非回归 |
11.3 执行层首测(新增,S6 义务①)
三程序全速(3 轮中位,含启动;内存=退出后单次读峰值工作集,坑 7):
| 程序 | CPython | Rust run | MoonBit run.exe | MB/Rust |
|---|---|---|---|---|
| fib(20) 递归 | 0.54ms | 22.5ms | 43.0ms | 1.92× |
| 冒泡 200 | 3.00ms | 22.6ms | 142.7ms | 6.32× |
| 500×500 嵌套 | 17.1ms | 30.2ms | 475.3ms | 15.7× |
- baseline366 端到端 run:MoonBit 中位 15.3ms(p90 16.9)/ Rust 10.8ms = 1.42×——教学小程序编译主导,执行差距被掩盖;计算密集程序暴露解释器差距 6–16×。峰值内存 MoonBit 9.2MB / Rust 7.8MB,均温和
- 含义:条件 A 验收的是"≤迷你 VM×3"的月兔内部标尺;本表补 vs Rust oracle 的真缺口——全速执行差距落在 §5 杠杆 2(bytecode→wasm 生成器,10–100×)的覆盖域内,坐实"解释器只服务单步/时间旅行、全速执行交给 wasm 生成器"的分工
11.4 时间旅行(vs §3)
| 程序 | CPython | Rust run | Rust unified | 步数 | 每步 | 峰值内存 |
|---|---|---|---|---|---|---|
| fib(20) | 0.54ms | 22.5ms | 6.63s | 284,591(与 §3 逐字同) | 23.3μs | 29.2MB |
| 冒泡 200 | 3.00ms | 22.6ms | 68.8s 跑完 | 1,621,540 | 42.4μs | 47.7MB |
| 500×500 | 17.1ms | 30.2ms | >75s 超时 | — | — | 28.0MB |
- 每步开销与内存峰值与 §3/§8.1 精确吻合(21μs/27.8μs;28.3/46.6/28.2MB)✅ "内存温和、真病灶每步 CPU"结论加固
- §3 修正一处:bubble200 的"60s 跑不完"实为 60s 超时设置截断——75s 上限下 68.8s 完成(162 万步);其每步 42.4μs 比 fib 的 23.3μs 贵 ~1.8×,与"数组大快照更贵"一致。nested500 灾难判定不变。unified vs CPython 12,000–23,000×,优化方案(§3)的量化前提原样成立
11.5 全 MoonBit 栈对拍(新增)
moonbit/cmd/run(批五号全栈入口:lexer→parser→typeck→codegen→VM)× baseline366 逐例对拍 Rust vitro_cli run 的 stdout+返回码:
| 归类 | 例数 | 说明 |
|---|---|---|
| 逐例一致 | 356 | stdout 行序列+返回码全同;全部 366 例无崩溃无超时 |
| 两侧同拒 | 6 | 编译诊断用例(e2/e3/j1),文案异构、语义同构 |
| MoonBit 拒、Rust 成功 | 3 | 缺口②:自定义 include 未闭环(§11.9) |
| 真语义 DIFF | 1 | 缺口①:va_copy 未生效(§11.9) |
- 非缺陷形态差异(对拍口径已归一,记录备查):Rust CLI 把引擎附注(
[warning]note/泄漏报告/stderr 行)合并进 stdout 流,MoonBit cmd/run 三通道分离(后者符合 E-P1-5 设计);cmd/run 对非 ASCII 程序输出 Latin-1 逐字节展开(main.mbt 注释已声明,Go 驱动归一)——伪装用例靠"只剥尾部附注块+验证块体纯度"防误剥 - 对拍脚本
diff_moon_run_full.py留档tmp/perf_probe/(gitignore 区,§7 表),本轮方法学坑(全角标点 wrapper/CRLF/Latin-1 展开/附注剥除防误伤)全部固化在脚本内注释,可直接复跑(§6 坑 13)
11.6 压力五维(vs §9.3,dump vs dump 同口径,3 轮中位)
| 维度(小→大) | 本次 MB/Rust | §9.3 重估列 | 判定 |
|---|---|---|---|
| 深嵌套 nest_4→14 | 1.63→1.98× | 1.40→1.61× | ✅ |
| 平铺 flat_500→8000 | 2.05→3.14× | 1.93→2.85×(§2 初测) | ✅ 同向 |
| 巨体 body_500→50000 | 2.10→3.80× | ~3.5× | ✅ |
| 大数组 arr_1000→10000 | 1.57→2.09× | ~3.96×(l 档) | ✅ 同向(arr_50000 本轮两侧同拒,大档不可测) |
| 局部变量 locals_1000→5000 | 2.51→3.53× | 2.32→3.27× | ✅ |
- 设计性拒绝两侧同构复现:arr_50000(全局数据区 60KB)+ expr 全三档(E1006)= 4 文件,MoonBit 走 fail_json(rc=0+
ok:false)、Rust rc=1 - 逐层计时形状同 §9.1(body_50000:MoonBit tok/ast/tck/cpl = 575/695/827/1657ms vs Rust dump-compile 436ms),管线线性、差距均匀分布;维持"记账不动手"(触发线核对:真实场景端到端 10–15ms ≪ 100ms)
11.7 wasm-gc(vs §4,0.5.0 首测,5 次中位扣启动)
| 场景 | 本次 w/n | §4(0.4.0) | 判定 |
|---|---|---|---|
| lexer ×200 | 0.71× | 0.61× | ✅ 反超保持 |
| GC 压力 ×200 | 0.65× | 0.43× | ✅ 反超保持 |
| parser ×150 | 1.23× | 0.79× | ⚠️ 翻转 |
| typeck ×100 | 1.24× | 0.95× | ⚠️ 翻转 |
| codegen ×100 | 1.24× | 0.89× | ⚠️ 翻转 |
| lexer 大输入 ×50 | 1.91× | 1.23× | ⚠️ 弱项扩大 |
| 启动 moonrun/native | 26.7/12.2ms | 21.6/10.3ms | 同量级 |
- 反超面 6/7→2/7:三管线场景收敛到同一 1.24×,系统性而非噪音(5 次中位);绝对差值 μs 级教学负载无感(百次 20–30ms),批量管道仍走 native
- 处置:登记待观察——0.6.0 前复跑若同形,值得归因 0.4.0→0.5.0 间哪个包的代码形态在 V8 下退化;暂无行动义务。深递归场景本轮无分辨率(native 扣启动后为负);产物体积未复测(§4 的 -54% 口径不变)
11.8 构建时间(新发现,归因闭环)
全量 release native 冷态 151–294s / 43 tasks(§1:6.2s / 37 tasks),方差 1.55×(293.5→189.4→151.4→186.8s)。逐包推进分解(坑 11):
| 组 | 耗时 | 说明 |
|---|---|---|
| 15 个库包合计 | ~4s(每包 0.0–0.4s) | lexer/parser/typeck/codegen/vm/host 等 |
| dump 四件各 4–5s | ~19s | 链接闭包 4.7–7.7MB |
| cmd/run 链接 | 198.9s | run.c 10.8MB 单 C 编译单元 |
- 归因:cmd/run 是唯一链接 S6 执行器闭包(vm+host+libc+memory)的入口,生成的
run.c达 10.8MB,cc -O2 超线性(对照:dump_compile.c 7.7MB→5.2s、dump_ast.c 4.7MB→4.1s——7.7→10.8MB 体积 1.4×、时间 38×,cliff 明确);debug 全量 4.1s 无此问题;热态复跑 3.5s(全缓存) - 编译器矩阵定案(同机同文件补测):MSVC cl 14.51 /O2 = 159.3s(独立复测;moon 源码
build_lower/compiler/msvc.rs固定/O2)vs llvm clang 22.1(msvc-target,同 ABI 同头文件)16.0s vs MinGW-w64 gcc(彼时 16.2.0)31.8s——病态锁死 MSVC cl 优化后端(10×/5×),非 MoonBit C 产物对编译器普遍病态、非本机环境问题;对照口径:cl 与 clang 同 ABI 同头,唯一差异是优化器 - 绕过手段(本机已终验):moon 支持
MOON_CC环境变量覆盖 C 编译器(源码compiler_flags.rsENV_MOON_CC,clang 走非 MSVC 通用分支)——MOON_CC=clang全量 release 构建 17.1s / 43 tasks rc=0(默认路径的 12–17×);运行期产物语义等价(同一 C 源不同编译器),但 clang 路径非 moon 官方默认,是否切换作发版批拍板项 - 性质:编译期工具链债,不影响运行期;§1 的 6.2s 时代执行器闭包尚不存在,与 §1 不可直接互比。CI 的
moon test走 debug 档不触发该 cliff,受影响的只是本机 release 全量构建 - 单函数归因(2026-09-26 深挖闭环):run.c 共 257,275 行,病态 100% 锁定
moonbit_init——moonc 为整个模块闭包生成的全局初始化巨函数:单函数 18,498 行 / 589KB,本质上是一个巨型直线基本块(18,457 条语句 / 仅 1 个 if / 零循环零 goto,只复用 18 个 distinct 临时变量——初记"~1.8 万个局部临时变量"系把 18,403 次引用误作变量个数,勘误);挖空该函数后 cl /O2 159.3s → 6.3s,文件仅缩 5.6%(602,900 / 10,776,823 B;初记"10%"系 MiB/MB 口径混用,勘误);clang 编同一文件 13–16s 无异常,gcc 全量 30s→清空后 21s(仅 1.4×——该函数对 gcc/clang 基本无害,病态 MSVC 特有)。cliff 真身不是"文件大"而是"这个单函数" - 两机复核(贡献者机 i9-14900HX / VS 18.5 / MSVC 14.44+14.50):clang -O2 13.5s、gcc -O2 31.3s 与本机几乎重合(单线程相当,排除硬件解释);MSVC cl /O2:14.50 = 71–73s、14.44 = 76s vs 本机 14.51 = 159.3s → 2.2× 工具集版本退化;clang-cl /O2 = 16.7s(同 ABI 同头同 MSVC 目标,4.4× 全在 MSVC 优化后端);端到端默认 cl 82.3s vs
MOON_CC=clang23.2s(43 tasks rc=0) - 同机版本 A/B(本机补装 14.50.35717)——初测 1.81× 已勘误:独立测量对(88.0s vs 159.3s)混入热漂移,用户交替 A/B(14.51→14.50→14.51→14.50,同份 run.c)定案 101.14s vs 68.66s = 1.47×(区间 96–126 vs 68–81 不重叠;冷首跑可达 1.94×);挖空 init 后 14.51 = 4.93s 反而快于 14.50 = 5.63s——退化是该函数形状特有,非通用变慢(此条比倍率本身更锋利)。定案形态:moonbit_init 巨函数 × MSVC 优化后端 = 病态基底(cl 下 ~20×、gcc 下仅 1.4×),14.51 工具集形状特有再乘 ~1.5×;绕过
MOON_CC=clang两机验证(17.1s / 23.2s,rc=0;前提:仅 generated-C 路径,direct-object MSVC 目标忽略非 cl 兼容 MOON_CC——builders.rs 警告实锤)。另有今天即可用的包级绕过:link.native.cc-flags覆盖默认 flags(has_user_flags 非空即不塞 /O2,compiler_flags.rs:1063/1318 + builders.rs:1113 实锤) - 处置:登记不动手(纯编译期成本,运行期/CI/日常增量不受影响);复现资产见下两条
- ✅ 已提报:moonbitlang/moon#2254(2026-09-26 晚,rustin-beep 身份 API 创建,open 待 triage)——两轮用户审阅批(数字勘误 1.81×→交替 A/B 1.47×、巨型直线基本块勘误、/O2 落点改 compiler_flags.rs、link.native.cc-flags 现有绕过、TL;DR 置顶、/d2 建议移出)+独立复跑全数通过(1.52×/清空方向/gcc 1.4×/init 155 行)后提交;源码基线 tag
perf-cliff-repro-20260926已推远端(040fbb1)。哈希口径勘误(用户第三批发现):整文件 sha 依赖构建目录——moonc 发射的#line指令内嵌绝对源路径(10,964 行,A/B 两份差 230,244 B,e9c1d0a vs 136ec81c);路径无关指纹=moonbit_init 区间(void moonbit_init() {至闭合},602,899 B 不含尾换行)sha256=08943e7c…,跨克隆逐字节一致;issue/tag 描述/dc 草稿已全改此口径;干净克隆重建交错 A/B 第三次复现 1.59×(154.91/97.63)。外部贡献者打 label 403("Must have admin rights"),留给官方 triage。Context 节已补(2026-09-27,用户两轮拍板)——"who is hitting this":定位=教学导向的白箱 C 子集引擎(纯 MoonBit 编写,自管 guest 完整内存模型:自有地址空间/堆状态机/每次访存受检)+ 443 测试与 Clang 逐字节对齐(用途=支撑"产物正确、纯构建期问题"的诊断可信度,非规模宣传);触发叙述="Being a teaching-scale project, we did not expect to hit a build-time cliff of this size"→推论"门槛不高(链接若干包到一个可执行就会撞)";示好=愿充当回归样本(MIT/一条命令复现/可跑预发布工具链回报计时)。位置在 Environment 与 Notes 之间(动线:技术事实→谁在撞→建议方向)。用户纠偏记录(表述纪律):初稿为"装高手"把"教学"定位藏掉、写成通用编译器口吻,被用户点出"怎么写得跟工业级编译器一样"——正解=说别人没有的具体技术事实(能掌控内存的白箱)而非堆通用规模数字;用户素材中的"平台级项目""三出口架构"等用词未采用(前者偏夸大、后者所指不明)。release 页已标[repro asset]前缀+中英双语性质声明(防路人误认为产品发行版) - 第二位贡献者审阅批之一(2026-09-26 晚,8 条意见全数实测后销项;该审阅者=issue 中的 Reporter 2,即此前提供跨机数据(i9-14900HX / VS18.5 / MSVC 14.44+14.50)的长期贡献者,已授权公开该关联):
- ①标题倍率勘误:原
~20x slower than clang无支撑——20× 实为"cl 有/无 init"的自身形状敏感度,非 vs clang 口径;实测 cl vs clang = 87–126s vs 12–16s = ~5–10×(随工具集/热态)。已改标题与正文(标题现为~5-10x slower than clang; 14.51 regressed ~1.4-1.6x) - ②机理断链修正:原文归因"new SSA-based loop optimizer"与实测零循环自相矛盾;实测结构=扁平常量表初始化(18,495 语句中 18,347 条
base[i]=v元素 store、98.2% 纯整数字面量,主体是 17,425 元素堆数组 + 644/88 两个小数组)。已重写为形状描述+撤回 pass 级猜测(pass 归因留待微软侧) - ③
/Bt+直接测量替代"删除推断":c1.dll(前端) 0.329–0.370s vs c2.dll(后端) 85.56s(14.50)/119.35s(14.51)——前端仅占 0.3%,版本差 1.40× 全在后端;已写进 issue(取代"请上游跑 WCTR"的表述,义务自扛) - ④
/d2ReducedOptimizeHugeFunctions实测(新缓解手段):14.51 119.8→32.1s(3.7×)、14.50 86.0→40.1s(2.1×);开启后 14.51(32.1s) 反超 14.50(40.1s)——第三次以独立手段印证"退化是形状特有"。blast radius 实测极小:全文件 182 函数中仅 init 超阈值(第二名 1,050 行),且 init 每进程仅跑一次→减少其优化的运行期代价可忽略。已作为"已验证缓解"入 issue Notes(并声明非请求 moon 默认加此未文档化 flag) - ⑤ReducedOptimizeThreshold 语义勘误:该开关语义是"对超阈值(默认 20,000 指令)巨大函数减少优化以缩短编译时间"且 opt-in(VS2019 16.4 引入;TensorFlow/Unreal 均需显式设置)——原文当"太大所以慢"的依据,方向反了。已改为"实测用它有效,与该诊断一致"(MS 博客链接已核 200+ 含该 flag 与 20000 阈值)
- ⑥平台无关理由补强(策略):gcc 同形状也慢 1.4×(30→21s) + 单 TU 使缓存/并行最小粒度=整个 10.8MB(改一行废整条 ccache 条目、TU 永远只占一核) + 该单元亦是交给 LTO/调试器的粒度 → 论证从"MSVC 的 bug"升格为"moonc 代码生成器的结构缺陷"(后者才排得上期)
- ⑦release asset 已挂:perf-cliff-repro-20260926 含
run.c(10,776,823 B 直链下载)+perf-cliff-repro-kit.zip(探针 7.3KB:矩阵//Bt+//d2/挖空对照);上游验证门槛从"装 moon 构建"降至"一行 cl 命令",issue 的 Option B 已改指该直链 - 未销项:第二台物理机的 14.51 数据(贡献者机未装 14.51;同机 clean clone 不计)——记为待办,用于独立确认版本退化
- ①标题倍率勘误:原
- 第二位贡献者审阅批之二(2026-09-27,病因因果)——"单基本块"系未验证因果,已实测推翻:
- 他的实验:不改任何原有语句,只在函数体插 K−1 个不可折叠分支把巨块切 K 块 → 切块收益仅 ~33%(他的基线 67.83s→K=16 45.47s,0.67),K≥16 饱和,K=256 回升;clang 不受影响。结论:真正驱动成本的是"单函数承载的指令总量"(函数级优化域规模),"单基本块"只是伴生现象
- 本机独立复现(交替两轮,排除热漂移):K=1 = 88.05/84.09s vs K=16 = 55.88/56.49s(均值 86.07→56.19 = 0.65),clang @K=256 = 11.22s;归一化与他精确吻合(他 0.66–0.74 / 我 0.65–0.71)
- 补充实验(他止步处:因 33 处跨行复合初始化怕劈断语法而停手——我的顶层语句边界扫描器解决了):把 moonbit_init 拆成 N 个 static 函数(开头 25 条声明提升为 file-static,按顶层语句边界切分,依次调用)。交替确认:基准 87.09/91.49s vs 拆 4 函数 5.88/5.96s = 15.1×;拆 2 = 19.14s(4.7×);拆 64 = 4.29s
- 决定性对比:拆成 4 个函数(5.92s)比"删空全部代码"(4.93–6.63s)还快 → MSVC 成本几乎全部来自"单个函数的规模",与代码总量无关;且饱和极早(N=4 已拿到 ~99% 收益),处方(per-package init chaining)无需细粒度
- 语义验证(闭环):拆 4 版链接成 exe(
libruntime.lib+libfs.lib,手工 LIB 补静态 CRT),跑 5 个 baseline 用例——rc+stdout 与原版逐字节一致(SAME 5/5) → 拆分方案语义等价、可行 - 完整干预阶梯(cl 14.51 /O2,归一化到各自基线):切块 K=16 0.65 /
/O10.75–0.88 //d20.42 / 拆 2 函数 0.22 / 拆 4 函数 0.07 / 拆 64 0.05 / 删空 0.06–0.10 - 结论与销项(✅ 已 PATCH 2026-09-27):处方方向正确且已量化("拆成几个函数"即可,4 段饱和);病因措辞已改——谁若按"缺基本块边界"去修(插 dummy 分支)最多白干 2/3。#2254 五处修订已上线:①Actual 病因句改为"the block shape is a symptom, not the cause"并指向新节 ②新增 1c 干预阶梯(切块 0.65–0.67/
/O10.75–0.88//d20.42/拆 2 = 0.22/拆 4 = 0.07/拆 64 = 0.05/删空 0.06–0.10,含拆分的机械做法、5/5 语义验证、以及"只插块边界最多白干 2/3"警示)③Notes #1 补量化(4 段即饱和,无需 per-package 粒度)④⑤口径统一——"Reporter 2" → "second contributor's machine"(用户拍板:第二贡献者已做完实验、不参与后续处理,由我们负责整合与叙述;不称 external reviewer)。dc_draft 同步补干预阶梯(对微软=直接印证其 huge-function 阈值设计)
- 新 issue 观察(2026-09-27,#2255):Windows Defender 把官方
moonfmt.exe隔离为Trojan:Win32/Bearfoos.B!ml(报告者 moon 0.1.20260904,VirusTotal 0 检出)。与 #2254 无技术因果(一个是 AV 误报二进制、一个是编译器优化时间),但同属"Windows 工具链摩擦",且为本轮"首跑惩罚=AV/Defender 扫描"的归因提供同环境侧证(我们这台机器上 Defender 确实活跃)。处置:不评论(我们未遇到该问题,信息量低),仅记录。 - 第三轮评估(2026-09-28,依赖清除后复盘;材料=用户两轮评估汇总+本会话三轮补测)——先勘误后采纳:
- 勘误(报告三处):①"24 行源码"错——
main.mbt实为 1,095 行 / 81,757 B(17,425 个数字的物理排布,报告 0 节与 5.5 节自相矛盾,5.5 自己已修正);②tag 177.9s vs HEAD 134.3s 并列展示有误导——两份 init 结构逐字节等价(见下),32% 差异是测量方差,非版本差异;③"门槛=元素数上万"仍是外推(其 5.1 只测两个极端) - ✅ 结构等价严格证明(5.2,本会话独立核验通过):tag vs HEAD init 区间逐行不同 18,432 行,抹掉所有数字后 0 行差异 ⇒ 纯标识符编号平移(用户口径 5.2 精确;我此前"percent-level timings unchanged"的措辞被其 5.3 方差数据打掉——同文件散布 109/117.9/142.3s,百分比级不可证)
- ✅ 阈值曲线(5.1+5.3+本会话三轮补测合成):语句数 1→4,006→8,006→12,006→17,431,cl /O2 ≈ 0.3/3.1/12.9/29.5/109s(热);每语句成本 0.774→1.611→2.457→6.253 ms,前两段吻合平方律(k≈2.0),末段跳 k≈3.5;复测方差:N=4000 = 2.88/2.94s(±2%),N=8000 = 12.66–15.43s(±10%),N=12000 = 33.13/38.82s(±8%)——曲线形状可信,单点绝对值有 ±10–15% 散布
- ✅ /d2 阈值实测定位(报告"未做"的关键对照,本会话补齐,方向推翻其推断):语句数 4,000→0.99×(无效果);8,000→2.73×(已生效);12,000→3.45×;17,431→4.16× ⇒ MSVC huge-function 阈值落在 4,000–8,000 语句之间(报告推断"12k–17.4k"错;按 ~1.4 指令/语句折算 ≈6k–11k 指令,低于文档默认 20,000——说明 moonc 的 store 序列展开后指令数远超语句数,或 14.51 的实际阈值行为与文档记载有出入,留给微软判定),且收益随规模单调递增
- ✅ 5.4 caveat 实测复现:函数构造(非字面量)的 init = 3 行/144B/2 语句、悬崖不复现——本会话补测 hello_probe.c(1 语句)= 0.06s;字面量要求已写进 issue Option C
- issudedraft 状态:
issue_revision_draft_0928.md三处修订方向全部成立,但需两处再修:①删"percent-level timings are unchanged"(改"structure and timings unchanged"或引方差区间);②Option C 补实测阈值曲线(4k 无感/8k 已触发)替代"未测中间地带"句;③门槛句不再写"上万",改引实测曲线——✅ 三处已修并 PATCH(2026-09-28,用户批准):修订内容=①Context 门槛句改实测曲线(1→4k→8k→12k→17.4k 语句 ≈ 0.3/3/13/30–39/110–142s,每语句成本超线性,±10–15% 散布声明)②Steps 重排 A/B/C:A=minimal(mb_probe.zip 3.7KB 直链,生成器一行,字面量 caveat 引实测)/B=run.c 直链/C=full sample(补git checkout perf-cliff-repro-20260926+注明 tag 带旧依赖而 main 零依赖可离线)③Source baseline 补 HEAD 现状(fe7c1f49…,结构等价:18,432 行差抹数字归零)+阈值实测(4k=0.99×/8k=2.73×/12k=3.45×/17.4k=4.16×,低于文档 20k 指令默认)+删"percent-level"(方差不可证);TL;DR Repro 行补 minimal 提及。mb_probe.zip已上传 release(3,736B;release body 同步登记);本地 issue_draft.md 已同步线上版。不重打 tag 的裁定维持(老 tag=数字基准;新 tag 等 Bytes 改造落地后打perf-cliff-fixed-*形成 before/after 对)
- 勘误(报告三处):①"24 行源码"错——
- 跟进待办:①DC 双报告——英文草稿已备
D:\code\build_cliff_probe\dc_draft.md(三问式:/O2 剖面/阈值覆盖/文档化缓解;附 run.c 或 release 直链);②moonbit-docs MOON_CC 文档 PR(等 #2254 表态);③MOON_CC 换编译器不触发重编(no work to do)实测后单开;④第二台物理机的 14.51 数据;⑤DC 提交后回 #2254 贴链接互链 - 上游尽调(2026-09-26,免重复):moonbitlang/moon 全 issue 库检索无人报告过 MSVC 对大型生成 C 单元的编译超线性——本报告为首例;相邻工作:#1958 已拆分的是 moon 运行时库 C(
lib/runtime/*.c)而非 moonc 为用户模块生成的单元;#1378(open)优化档位 profiles 仍是 feature 请求;#2085 确认 Windows 探测顺序 MSVC > MinGW > system cc(默认撞 cliff 是有意设计);#1714(open)正在完善 clang 工具链行为;#1091(open)MOON_CC 暂不支持带参。业界背景:MSVC 大 TU 慢于 clang 为常识(Firefox 2018 转 clang-cl、Developer Community 单文件 15× 病态先例),issue 措辞应落在"moon 默认组合(单单元 × cl /O2)的乘积效应 + MOON_CC 文档露出",勿写成"MSVC 是 bug"
11.9 遗留与拍板项(2026-09-26 新增)
- va_copy 缺陷(
e1_va_copy,D 级 29 用例未覆盖):va_copy(ap2, ap)后从副本va_arg读取全得 0——Rust 侧8.0 13.0vs MoonBit8.0 0.0(第一遍 va_arg 正确、副本游标丢失,hostva_*族);host 包小改,可随 0.6.0 修复批 - 自定义 include 未闭环(
include_custom_header/e2_has_include_chain/e2_include_guarded,D 级未覆盖):cmd/run 单文件入口只把主文件装入源表,自定义 .h 不落盘装载(与 CWD 无关、.h 实际存在,已实测排除环境因);Rust oracle 按磁盘解析成功——涉及 lexer/入口约定,工程量较大。两项均不阻发版(cmd/run 为仓库开发工具,不在 mooncakes 对外面),建议进发版批三决策的已知缺陷清单,工程量不同可分开拍板 - 构建 cliff(cmd/run 链接 199s)是否上工具链债清单:随发版批拍板(§11.8)
- wasm 管线三场景 1.24× 翻转:0.6.0 前复跑定性(§11.7)——已定性(2026-09-29,§12.2):「不可复现、归因不可定」——同日方法对齐 A/B 下 0.5.0 与 HEAD 中位逐场景重合,两版本都没有 1.24×;本条按此销账。本轮唯一硬结论 = 执行层 wasm-gc 快 2-2.8×(新基线)
- §10 触发线核对:管线三维维持"记账不动手";时间旅行优化方案(§3)量化前提复验成立,仍按计划作为执行器批前置设计输入
12. S7 wasm-gc 单出口落地后复跑(2026-09-29,本地 HEAD 工作区)
AS-OF:2026-09-29 11:00-12:00。触发 = S7 批五号「wasm-gc 单出口落地」(
2f18e10,gateway 建包 + Node 宿主)。 口径:被测 = 本地 HEAD 工作区(3a51667,与2f18e10仅差一个 docs 提交,代码同);机 = AMD Ryzen AI Max+ 395 / 16 核 32 线程 / Win11 build 26200(与 §1-§4 同机);moon0.1.20260920;vitro/enginemoon.mod = 0.6.0(0.7.0 发版批未执行);Rust 侧用现成native/target/release/vitro_cli.exe(源无更新,find -newer= 0)。 探针纪律:产物全部落tmp/perf_probe/(gitignore/tmp/覆盖),工作区零流入;本次新增探针与定标见 §12.8。 结论速览:①环境那一项已闭环——会话内进程创建 ~148ms 是本 agent 会话特有(会话外 3.5-5.0ms,同分钟对照),不用重启、不用改 VBS/HVCI/Defender;权威数字已在会话外整套复采;②**§11.9-4 已销账**:0.5.0 与 HEAD 在清环境下逐场景重合到 ±0.05 ⇒ 「管线 1.24× 翻转」判为 §11.7 当日测量假象;③编译管线没退化(tokens 0.357/ast 0.241/typeck 0.237/compile 0.275s,与 §1 重合);wasm-gc 侧 lexer 0.62-0.65、parser 0.80、GC 0.33-0.49 偏 wasm,typeck/codegen 持平;④执行层最硬:wasm-gc 跑完整引擎比 native 快 2.0× / 2.7× ⇒ §11.3 的「落后 6-16×」是 native 后端的性格;⑤**「大输入是 wasm 唯一弱项」与实测相反**:16× 点 wasm 0.70-0.74×、增长两侧都≈线性;⑥全栈对拍 360/6/0/0(va_copy 与自定义 include 两缺口已闭环);⑦时间旅行逐字复现(步数·每步·峰值内存),§3 方案量化前提成立;⑧moon build --release --target native全量因 gateway+native声明必失败(LNK1561),已定位到 moon 的通用行为并验证了拆包修法;⑨探针套件暴露并修掉一个真缺陷(subprocess(text=True)依赖 UTF-8 环境变量,会话外必崩)。
12.1 环境:会话内进程创建开销(定案:会话特有;权威数字改用会话外采集)
| 度量 | 2026-09-26(实录/探针构建期) | 2026-09-29 实测 | 倍率 |
|---|---|---|---|
vitro_cli.exe 启动(§11.2 记 5.8ms) |
5.8ms | 146.5ms | 25× |
探针 native exe 场景0(§11.7 记 12.2ms) |
12.2ms | 193.3ms | 16× |
| moonrun 启动(§11.7 记 26.7ms) | 26.7ms | 159.5ms | 6× |
python -c pass |
— | 358.0ms | — |
- 不是沙箱:
dangerouslyDisableSandbox复测无改善(146.5 vs 148.8ms)。不是被测二进制的锅:2026-09-26 构建、当时记 12.2ms 的旧探针 exe 本次实测 193.3ms ⇒ 纯环境侧。 - 本机当日
Defender RealTimeProtection=True / BehaviorMonitor=True / TamperProtected=True,另有Androws*(Android VM)等第三方组件在跑——候选原因未定,效果确定。 - 泄流型工具另有每文件写盘税:
bench_pipeline扣启动定标后仍偏高 ~1.8-2.3×(每轮写 366-732 个文件)。 - 处置(已闭环):该开销只影响 agent 会话内部,机器本身正常(会话外 3.5-5.0ms),不需要重启、不需要改 VBS/HVCI/Defender。已在普通窗口用同一套探针整套复采(入口
tmp/perf_probe/run_all_user.cmd,日志tmp/perf_probe/user_run_logs/),§12.2 / §12.4 / §12.5 的权威数字全部改用该批。会话内采集的绝对值永久作废、只作轨迹。 - 方法学结论(入规程):该开销下唯一可靠形态 = 同进程内重复 + 同源空转场景自校准(
wasm_bench形态——加数与减数同源,开销对消)。禁用固定常数扣启动:该值在 140-190ms 间漂移 ±30%,<500ms 的测量做减法会翻符号(本次run_cmp的 fib 扣完变负即此)。
深挖追加(12:10-12:15,同环境):该开销不只是大,还会在一个 run 内漂,单点定标会被击穿。实测:同一 0.5.0 二进制同小时三次跑,parser 纯算 0.67/1.42/0.67(2× 抖动);HEAD 某轮把 lexer 纯算压成 2.4ms(真值 ~37ms),整轮作废。修法已验证:驱动器改成每个场景前后各测一次场景0、取两次均值作该场景基线(run_bench_head/run_bench2.py),drift 中位即落到 ±2-5ms,3 轮比值可复现(见 §12.2 修订表)。⇒ 探针学纪律:空转基线必须与被测场景同轮次交替测,不能整轮只测一次。
决定性对照(12:23,用户普通窗口):同一脚本 tmp/perf_probe/launch_cost.py 在普通 cmd 窗口(非 agent 会话)跑 ⇒ 114KB 4.6 / 2.5MB 6.0 / 7MB 4.7ms,CreateProcess 1.7ms、进 main 前 5.0ms、退 main 后 1.3ms;同一分钟本会话内复测仍是 145.3-151.4ms ⇒ 该开销是本 agent 会话的进程派生链特有的,不是机器策略。⇒ 撤回先前「VBS/HVCI × Defender 实时」的归因(那些策略在两侧完全相同,故不是原因)。本会话内的绝对值一律不得引用;干净数字必须在普通窗口采集(§12.9 给了整套入口)。
12.2 wasm-gc 场景(权威口径:会话外清环境 + 漂移控制 + 双版本 3 轮)
探针 tmp/perf_probe/wasm_bench_head/(新):依赖经 .mooncakes/vitro/engine 目录联接指向本地 moonbit/(HEAD),非 mooncakes 发布版。口径与 §4/§11.7 同题同法(外层计时 / 场景0 = 空转 / 扣启动 / 5 轮中位 / moonrun(V8·TurboFan) vs native exe)。场景 1-7 = 原管线面;场景 8-9 = 新增执行层 VM 面(run_vm:tokenize→parse→typeck→codegen→setup_from_output→vm.run());场景 10-12 = lexer 规模梯子(模块级预建的 1×/4×/16× 大输入,构造只进场景0)。
本节数字来自会话外清环境(普通控制台窗口,启动开销 3.5-5.0ms、drift ±1.4ms),两侧同用漂移控制版
run_bench2.py(每场景前后各测场景0取均值)、5 轮中位。会话内那几轮(单点定标、被 §12.1 的开销与漂移击穿)只作轨迹,不得引用。
A/B 对照(决定性,双版本各 3 轮,同一小时同一方法):用 mooncakes 0.5.0 的旧探针(tmp/perf_probe/wasm_bench/,2026-09-26 构建产物,即 §11.7 同源)与 HEAD 对跑:
| 场景(纯算 wasm/native) | 0.5.0 三轮 | 0.5.0 中位 | HEAD 三轮 | HEAD 中位 |
|---|---|---|---|---|
| 1 lexer ×200 | 0.61/0.64/0.63 | 0.63 | 0.64/0.65/0.62 | 0.64 |
| 2 parser ×150 | 0.77/0.79/0.79 | 0.79 | 0.80/0.80/0.80 | 0.80 |
| 3 typeck ×100 | 0.96/0.96/0.96 | 0.96 | 0.98/0.97/0.94 | 0.97 |
| 4 codegen ×100 | 0.90/0.92/0.93 | 0.92 | 0.94/0.92/0.92 | 0.92 |
| 5 GC 压力 ×200 | 0.48/0.47/0.50 | 0.48 | 0.36/0.49/0.33 | 0.36 |
| 6 lexer 大输入 ×50 | 1.32/1.39/1.42 | 1.39 | 1.41/1.32/1.49 | 1.41 |
⇒ 两版本中位逐场景重合到 ±0.05(唯一 0.12 的差在 GC —— 该场景纯算仅 17-47ms,最短) ⇒ §11.7 的「三管线场景一致 1.24×」既非 0.4.0→0.5.0 的版本效应,也不可复现,判为当日测量假象。§11.9-4 按「不可复现、归因不可定」销账(§11.7 未记录绝对值,无法回溯是哪个环节偏了);不再写「HEAD 回到 0.71-0.98×」这种把噪声当结论的措辞。清环境下三轮逐位重复(多数场景 ±0.02),方法本身已可信。
HEAD 全场景(会话外清环境,漂移控制,纯算 wasm/native):
| 场景 | §4(0.4.0) | §11.7(0.5.0) | HEAD r1/r2/r3 | 判定 |
|---|---|---|---|---|
| 1 lexer ×200 | 0.61× | 0.71× | 0.64/0.65/0.62 | wasm 快 ~1.6× |
| 2 parser ×150 | 0.79× | 1.23× | 0.80/0.80/0.80 | wasm 快 ~1.25× |
| 3 typeck ×100 | 0.95× | 1.24× | 0.98/0.97/0.94 | 持平(wasm 略优) |
| 4 codegen ×100 | 0.89× | 1.24× | 0.94/0.92/0.92 | 持平(wasm 略优) |
| 5 GC 压力 ×200 | 0.43× | 0.65× | 0.36/0.49/0.33 | wasm 快 2-3× |
| 6 lexer 大输入 ×50 | 1.23× | 1.91× | 1.41/1.32/1.49 | wasm 慢 ~1.4× |
| 8 VM 执行 fib(20) ×10 | — | — | 0.49/0.49/0.49 | 🆕 wasm 快 2.0× |
| 9 VM 执行 nested300 ×3 | — | — | 0.37/0.37/0.36 | 🆕 wasm 快 2.7× |
| 10 大输入 1× ×50 | — | — | 1.33/1.28/1.32 | wasm 慢 ~1.3× |
| 11 大输入 4× ×50 | — | — | 0.87/0.86/0.89 | 持平 |
| 12 大输入 16× ×50 | — | — | 0.74/0.72/0.70 | wasm 快 ~1.35× |
- 执行层最硬:场景 8/9 三轮分别 0.49/0.49/0.49 与 0.37/0.37/0.36(绝对值 100-500ms,远离噪声底)。wasm-gc 下跑完整引擎(S6 的 vm/host/memory 闭包,即 gateway 的
+wasm-gc闭包)比 native 快 2.0× / 2.7× ⇒ §11.3 的「执行层落后 Rust 6-16×」是 native 后端的性格,不是引擎的性格。这条为路线裁定(wasm-gc 为主交付面)再添一手证据。 - 管线层:持平或略优,不是反超。lexer 0.62-0.65(wasm 快 ~1.6×)、parser 0.80(~1.25×)、GC 0.33-0.49(2-3×)偏 wasm;typeck 0.94-0.98、codegen 0.92-0.94 基本持平。与 §4 的原始读数同量级(§4: lexer 0.61 / parser 0.79 / typeck 0.95 / codegen 0.89)⇒ 0.4.0→HEAD 之间这条线没有实质变化。
- 「lexer 大输入是唯一弱项」不成立(方向相反):规模梯子 1× 1.28-1.41×(wasm 慢)→ 4× 0.86-0.89(持平)→ 16×(单输入 ~1.4MB)0.70-0.74×(wasm 快 ~1.35×)。增长指数:native 4×→16× 为 4.04×、wasm 3.36×(对 4× 输入)⇒ 两侧都接近线性,谈不上超线性;与 §4/§11.7 记的「wasm 超线性、native 亚线性」相反。1× 点(纯算 ≈12-18ms)仍靠近噪声底,只有 4×/16× 两点算硬;据此把 §10 的该遗留项改为「方向存疑、待复核」。
- 启动(清环境):native
场景07.6-9.5ms / moonrun 17.1-18.0ms(§11.7: 12.2 / 26.7ms)。 - 产物体积:探针 wasm 619KB / native exe 1,235KB。gateway 产物体积未复测(§4 的 -54% 口径不变)。
12.3 全 MoonBit 栈对拍(diff_moon_run_full.py,正确性面)
cmd/run(lexer→parser→typeck→codegen→VM 全栈)× baseline 366 例,逐例对拍 Rust vitro_cli run 的 stdout 行序列 + 返回码:
| 归类 | §11.5(0.5.0) | 本次(HEAD) |
|---|---|---|
| 逐例一致 SAME | 356 | 360 |
| 两侧同拒 | 6 | 6 |
| MoonBit 拒 / Rust 成功 | 3 | 0 |
| 真语义 DIFF | 1 | 0 |
- §11.9 登记的两个缺口(va_copy 未生效、自定义 include 未闭环)均已闭环(
apply_reply幽灵栈值修复;cmd/run的SourceProvider接线)。366 例无崩溃、无超时、无非预期差异。 - 本口径不受 §12.1 环境开销影响结论(归类判据是 stdout/返回码,不是时间)。
12.4 管线 / 多维 / 压力(会话外清环境真值)
本节原为会话内虚高数字(全部作废,只留 §12.1 的轨迹)。以下为会话外清环境复采(两轮独立复跑)。
四层 dump 吞吐 baseline366(3 轮中位):tokens 0.357 / 0.370、ast 0.241 / 0.246、typeck 0.237 / 0.241、compile 0.275 / 0.280s。
- 与 §1(0.37/0.26/0.26/0.30s)基本重合,比 §11.1(0.451/0.287/0.284/0.344s)更快 ⇒ 编译管线没有退化;层序形状一致,knr/leetcode/gap 按语料规模同比缩放。
多维对比(bench_compare.py):
| 项 | 本次(清环境) | 实录对照 | 判定 |
|---|---|---|---|
| 段1 进程启动 rust/moon | 4.0 / 9.7ms | §11.2: 5.8 / 13.0ms(2.2×) | ✅ 同向(2.4×) |
| 段2 tokens 目录批处理 baseline | rust 0.233 / moon 0.338s = 1.45×(moon/rust) | §2: 0.24 / 0.35s = 1.4× | ✅ 精确复现 |
| 段2 stress17 | rust 0.589 / moon 1.254s = 2.13×(moon/rust) | §11.2 注记 2.4× | ✅ 同向 |
| 段3 compile 逐文件 baseline | rust 中位 7.2 / moon 10.7ms = 1.49×(moon/rust);总 2.774 / 4.120s | §11.2: 1.58×;§2: 1.5×;§8.1: 1.49× | ✅ 比值精确复现(绝对值见下注) |
| 段3 异常集合 | rust 9 例 = 6 诊断 + include 族 3 | §11.2 注记 9 例 | ✅ 逐字同 |
| 段4 用户场景 | compile 中位 6.4ms(p90 7.5)/ run 中位 8.0ms(p90 9.2) | §2: 8.2 / 9.9;§11.2: 9.3 / 10.8 | ✅ 同量级 |
| 段4 非 0 退出 | 6 例:e2_angle_local_header / e2_include_cycle / e2_include_not_found_angle / e2_include_not_found_quote / e3_static_assert_fail / j1_declarator_depth |
§2/§11.2 同 6 例 | ✅ 逐字同 |
- ⚠️ 一处跨日绝对值异常(登记):段3 的比值 1.49× 与 §8.1/§2 逐字吻合,但 rust 侧绝对值从 §11.2 的 15.2ms 降到 7.2ms(2.1×),moon 侧 9.4→10.7ms 基本不动。当前
native/target/release/vitro_cli.exe的 mtime 是今日 10:58(find -newer= 0 ⇒ 二进制比全部 .rs 新,但**§11 之后被重建过**)。⇒ 比值可用,跨日绝对值不可直接比;要追究得比对两次构建的 flags。 - 会话内那组方向是错的(段3 曾算成 0.93×):根因是会话不仅加启动税,对文件写入也加税,而 dump 类每轮写 366-732 个文件、两侧不等比放大。
压力五维(run_stress.py,dump vs dump 同口径,3 轮中位)——比值 = moon/rust(>1 = moon 慢):
| 维度(小→大) | 本次 | §11.6 | 判定 |
|---|---|---|---|
| 深嵌套 nest_4 → 14 | 1.71 → 1.55× | 1.63 → 1.98× | ✅ 同量级(趋势差在噪声内) |
| 平铺 flat_500 → 8000 | 2.24 → 2.67× | 2.05 → 3.14× | ✅ |
| 巨体 body_500 → 50000 | 2.16 → 3.41× | 2.10 → 3.80× | ✅ |
| 大数组 arr_1000 → 10000 | 1.68 → 2.38× | 1.57 → 2.09× | ✅ |
| 局部变量 locals_1000 → 5000 | 2.50 → 3.08× | 2.51 → 3.53× | ✅ |
- 设计性拒绝两侧同构复现:
arr_50000(全局数据区 60KB)+expr_1000/5000/20000(E1006)= 4 文件;MoonBit 走fail_json(rc=0 + 产物ok:false)、Rust rc=1 —— 与 §11.6 逐条同。 - 执行层附加段(端到端 run,含编译):rust 16.6-84.9ms / moon 41.0-85.2ms,比值(moon/rust)1.00-3.10×;
locals_5000两侧持平(1.00×)而nest_14/arr_10000达 3.10× ⇒ 形状依赖明显,样本仅 5 个,不作一般结论。
12.5 时间旅行与执行层(会话外清环境真值)
unified(单进程长跑,两环境同值 ⇒ 会话开销无关):
| 程序 | CPython | Rust unified | 步数 | 每步 | 峰值内存 |
|---|---|---|---|---|---|
| fib(20) | 0.51ms | 6.32s | 284,591 | 22.20μs | 29.0MB |
| 冒泡 200 | 2.83ms | 58.24s | 1,621,540 | 35.92μs | 47.8MB |
| 500×500 | 13.90ms | >75s 超时(--max-steps 5000000) |
— | — | 28.0MB |
- 与 §11.4(6.63s / 23.3μs;68.8s / 42.4μs;nested 超时;29.2 / 47.7 / 28.0MB)逐项吻合,步数逐字复现(284,591 / 1,621,540)⇒「每步 CPU 是病灶、内存温和」的裁定与 §3 优化方案的量化前提原样成立。
全速执行(3 轮中位):
| 程序 | CPython | Rust run | MoonBit run | MB/Rust | 峰值(moon/rust) |
|---|---|---|---|---|---|
| fib(20) | 0.51ms | 17.9ms | 33.4ms | 1.87× | 9.2 / 7.8MB |
| 冒泡 200 | 2.83ms | 20.0ms | 132.3ms | 6.60× | 9.3 / 7.9MB |
| 500×500 | 13.90ms | 24.0ms | 437.8ms | 18.27× | 9.2 / 7.9MB |
- 与 §11.3(22.5/22.6/30.2ms、43.0/142.7/475.3ms、比值 1.92 / 6.32 / 15.7×)吻合 ⇒ 「计算密集 6-16×」结论复现;峰值内存与 §11.3 的 9.2 / 7.8MB 逐字同。
- baseline366 端到端
run:MoonBit 中位 13.1ms(p90 15.5,0 失败)/ Rust 7.8ms(p90 8.7,6 非 0)⇒ MoonBit/Rust = 1.68×(§11.3 记 1.42×,同向、略高)。会话内那组(153.7 / 155.0ms,比值 1.00×)纯属开销主导,作废。
12.6 gateway native 构建失败:根因隔离 + 修法验证(深挖,与性能无关)
- 现象:
cd moonbit && moon build --release --target native(全量)报Failed with 131/218 warnings, 0 errors→Error: failed to run build for target Native / Caused by: failed when building project,EXIT=127。 - 定位:C 层唯一错误 =
LINK : fatal error LNK1561: 必须定义入口点,紧跟正在创建库 ...\gateway\gateway.lib之后;其余 5 个cmd/*目标全部编译链接成功(run.exe冒烟hi 42通过)。两次全量构建复现(一次与其他会话并发、一次静默后独占),与并发无关。 - 根因判断:
moonbit/gateway/moon.pkg声明supported_targets = "+wasm-gc +native"+pkgtype(kind: "foreign_library"),但 native 后端对该包仍尝试链接可执行文件 ⇒ 无入口点 ⇒ LNK1561。 - 为什么一直没暴露:
ci.yml只跑moon build --release --target wasm-gc gateway(234 行)、--target native cmd/serve(223 行)、--target native cmd/run(310 行)——从不做全量 native release 构建,+native声明从未被验证。 - 影响:任何人按文档跑「全量 native 构建」(§11.8 的 151-294s 那条)现在都会失败;§11.8 构建时间口径本轮无法复测。局部构建不受影响。
- 根因隔离(4 行最小模块):新建
tmp/perf_probe/fl_probe/(一个foreign_library包 + 一个 native executable 消费者,形态照搬 gateway / cmd-serve)⇒moon build --release --target native lib复现 LNK1561(0 warnings / 0 errors),而--target native app(消费者)RC=0、--target wasm-gc libRC=0。⇒ 是 moon 对foreign_library包单独做 native 构建的通用行为,与代码规模 / 警告数 / gateway 内容无关;也解释了cmd/serve为何一直没事(它只是消费方)。 - 两条直觉修法均被证伪:
- ① 去掉
+native→ native 消费者立刻Selected backend 'native' is incompatible with the dependency graph. 'app' requires 'lib' which supports [wasm-gc]⇒ 不可行(cmd/serve正是 native 消费者)。 - ②
pkgtype改回默认library→[4219] #export_name "hello" can only be used in a foreign library⇒ 不可行(4 个导出面必须foreign_library)。
- ① 去掉
- ✅ 已验证修法 = 拆包(
tmp/perf_probe/fl2/实测全程通过):核心逻辑放library包(supported_targets = "+wasm-gc +native",被 native 消费者与 wasm 外壳共用);另建一个只含#export_name面的foreign_library外壳,supported_targets = "+wasm-gc"单目标。实测:全量moon build --release --target nativeRC=0(10 tasks)、native 消费者冒烟输出hi、--target wasm-gc wrap产出 wasm 且导出面在;产物侧唯一 import 是{"module":"_","name":"hi","kind":"global"}(importedStringConstants,非功能性 import)⇒ 不破坏 gateway 现有的「零功能性 imports」性质。 - 落地牵连面(未动手):wasm 产物路径会从
.../build/gateway/gateway.wasm变为外壳包路径 ⇒scripts/wasm_gateway/host.js默认路径 +ci.yml(234 行)要同步;新包须进scripts/moonbit/pkg_deps的 L8 登记、mbti_sync、moonbit_surface白名单/边表;moonbit CHANGELOG/README 包图连坐。⇒ 这是一批活而非一行修,故本轮只交验证过的配方,不擅自重构。 - 无论选哪条路,CI 都应补一条全量 native release 构建门——本次漏检的根因就是「声明了 target 却没有任何步骤构建它」。
- 上游定位与提 issue 判断(2026-09-29 查证):
- 官方 v0.10.4 发布说明已写明「native 后端编译静态/动态库仍在打磨,该特性目前主要面向 Wasm/JS 后端」;第三方项目
XiLaiTL/moobile(docs/EVIDENCE.md)也撞到同一处并记为「与官方文档所述一致」,绕法是自编生成的 C。⇒ 「native 不支持 foreign_library」不是未知缺陷,不提(提了会被当 known 关掉)。 - 但症状中有一块文档没覆盖,值得提一条窄口径 issue:①
supported_targets = "+native"被moon check --target all静默接受,只在 C 链接阶段炸;且与编译器无关——MOON_CC=clang下同一模块失败,只是换成 lld 的措辞lld-link: error: subsystem must be defined;②爆炸半径 = 整个模块:模块内只要有一个foreign_library(哪怕没有任何 native 可执行文件链接它),模块级moon build --release --target native就整体失败 ⇒ 一个 wasm-gc 库产物会毒化全模块的 native 构建;③对照:同形状的纯library包(全新模块、同样+wasm-gc +native)单独 native 构建 RC=0 且不进链接步骤(只产.core/.mi),而foreign_library会先产.lib/.obj/.exp再跑一次 exe 链接 ⇒ 差别只在pkgtype;最小复现只需 3 个文件(tmp/perf_probe/flmin/)。 - 建议口径:只请求「早失败/清晰诊断(像现有的
Selected backend 'native' is incompatible with the dependency graph那样) + 不毒化整模块」,不要写成「请实现 native foreign_library」。草稿备于tmp/perf_probe/moon_issue_draft_foreign_library_native.md(未提交)。 - 源码级定位(2026-09-29,浅克隆
moonbitlang/moon@22eb0ba):①crates/moonutil/src/package.rs的PackageKind+ 遗留force_link;②build_lower/lower_build.rs:204-211由is_main/force_link反推 pkgtype;③build_lower/compiler/build_common.rs:247把-pkg-type传给 moonc——仓库自己的dummy_core/bundle_all_targets.jsonl.snap:9就证明-target native也照发-pkg-type foreign_library,且 moonc 接受了;④计划层为它生成ArtifactKey::Executable,最终落到compiler/msvc.rs:68 link_executable_command(调用点lower_build.rs:1204)——LNK1561 就在这一步。⇒ PR #1877 正文写明「native 的拒绝留给 moonc」,而 moonc 没拒绝 = 契约缺口(不是「功能没做完」)。 - 关联检索(确认无重复):#1877(merged,即上述契约来源)/ #2251(open,DSL 迁移跟踪,与 #1877 同作者)/ #1887(open,native 库链接参数语法)/ #992(closed,
link_configs)/ #2195(closed,MSVC 本地化输出乱码——我们看到的LNK1561: ���붨����ڵ�乱码错误文本就是它,已修)。提 issue 地点 =moonbitlang/moon(与 §11.8 的 #2254 同仓库)。 - PR 判断(是否替上游动手):先提 issue 带定位,PR 等上游确认语义。修法有两种互斥语义:①拒绝(与 #1877 「留给 moonc」一致,但会让「wasm 导出 + native 消费」组合彻底无解)②native 下按
library处理(我们的场景直接可用,但等于替未完成特性开路)——选哪条是上游的设计决定,猜错等于白干;且 moon 集成测试是jsonl.snap快照制,改行为要连锁重生成,本机还需完整 Rust 工具链构建。⇒ 性价比最高的贡献 = issue 里给到源码定位 + 3 文件复现(上游从 issue 到修复可能只要几分钟),并在 issue 里主动提出「确认语义后我可提 PR + 测试」。 - 提交时机(2026-09-29 拍板):草稿已就绪但暂缓提交——国庆+中秋连休窗口(约 13 天),上游本就零响应(#2254 提交 3 天 0 评论 0 标签),假期内提交只是排队。随手可发:
tmp/perf_probe/moon_issue_draft_foreign_library_native.md即可粘贴终稿。关键点:最小复现是独立 3 文件模块(tmp/perf_probe/flmin/),不依赖本仓库任何代码 ⇒ 本条不受仓库正在进行的 gateway/serve/CI 修复批影响,无需重新取证。
- 官方 v0.10.4 发布说明已写明「native 后端编译静态/动态库仍在打磨,该特性目前主要面向 Wasm/JS 后端」;第三方项目
12.7 本轮方法学坑(已入 .agents/skills/vitro-workspace-review/references/04-工具链与踩坑.md)
- safe-delete 钩子拦探针的
rmtree:bench_pipeline/run_stress首跑 RC=1,stderr[safe-delete][SAFE_DELETE_BULK_CONFIRM_REQUIRED] {"count":739,"threshold":50,"scope":"turn"}——每轮删除输出目录在文件数 >50 时被拒,且同 turn 内逐次删除累计计数。处置:删除全部改为os.rename改名让位(*_old_<ns>),语义等价(每轮仍是空目录),已写入两个脚本。⇒ 以后写探针不要用删除做目录复位(记 04-D5)。 - 机器级启动开销(§12.1):逐进程口径失效;自校准形态是唯一可靠出路(记 04-C8)。
- 禁用固定常数扣启动(±30% 漂移会翻符号,同上条)。
moon.mod的import必须带版本号:import { "vitro/engine" }⇒moon.mod only supports versioned registry dependencies;本地工作区依赖的正确接法 ="vitro/engine@<本地 moon.mod version>"+.mooncakes/vitro/engine目录联接(记 04-A17)。- MSYS bash 的 fork 本身很贵(
ls×10 ≈ 350ms/次级别)⇒ 别用date +%s%N包 bash 循环测进程启动(记 04-C9)。
12.8 复跑资产
| 资产 | 位置 | 复跑 |
|---|---|---|
| wasm-gc 场景探针(新,本地 HEAD 依赖 + 执行层 + 规模梯子) | tmp/perf_probe/wasm_bench_head/ |
python run_bench.py(原版) / python run_bench2.py(漂移控制版,推荐);BENCH_NATIVE_EXE / BENCH_SCENES / BENCH_ROUNDS 可覆盖 |
| 0.5.0 旧探针(方法对齐 A/B 用) | tmp/perf_probe/wasm_bench/ |
已拷入 run_bench2.py: BENCH_SCENES=1,2,3,4,5,6 python run_bench2.py |
| 工具启动定标(新) | tmp/perf_probe/calib/calib.json |
见 §12.4 口径 |
| tokens 层形状取证(新) | tmp/perf_probe/tokens_dig.py |
PERF_RUNID=<id> python tokens_dig.py |
| gateway 根因最小模块(新) | tmp/perf_probe/fl_probe/(foreign_library+双 target)/ fl2/(拆包方案) |
各自 moon build --release --target native [pkg] |
| 启动开销时间戳探针(新) | tmp/perf_probe/stamp/(Go,main 入口打时间戳) |
go build -o stamp.exe . |
| 其余 6 套(原样) | tmp/perf_probe/{bench_pipeline,bench_compare,run_stress,bench_moon_run,diff_moon_run_full}.py、ext_cmp/run_cmp.py |
各脚本头注;PERF_RUNID=<id> 规避 safe-delete |
| 本轮原始日志 | tmp/perf_probe/{suite_20260929,suite2_20260929,bench_head_run1..3,bench_cc_compare,bench_ab_050_vs_head,ab_old_drift,dig_20260929}.log、env_diag.txt、fingerprint.txt |
— |
- 改动 2 个原探针脚本(
bench_pipeline.py/run_stress.py)的目录复位方式(删除 → 改名),口径未变;改动原因与语义等价性见 §12.7-1。 - 前置注意:全量 native release 构建会撞 §12.6 的 LNK1561,需逐目标构建(
moon build --release --target native cmd/run等)。 - 新增驱动器
run_bench2.py与旧版并存:旧版仅作轨迹保留,新结论一律引run_bench2(漂移控制)。
12.9 深挖:进程启动开销归因(只读取证)
- 量级见 §12.1。尺寸无关:clang 自编的 114KB
tiny.exe(空 main)与 7MBvitro_cli.exe同价,moonrun也同价。父进程无关:python 父与 PowerShell 父同价 ⇒ 不是 Python/MSYS 的 spawn 路径问题。 - 拆开看:
CreateProcess返回 ≈ 22.6ms(尺寸无关);进程创建 → 子进程进 main ≈ 125ms;main 出口之后 ≈ 3ms。用一个在 main 入口打印time.Now()的 Go 探针(tmp/perf_probe/stamp/)做时间戳锚 ⇒ ~148/151ms 全部花在「进 main 之前」(映像加载 + 扫描),不在退出路径,也不在被测程序的计算里(空 main 一样付)。 - 无预热收敛:同一 exe 连发 12 次,min/med/max = 144.3/159.8/239.3ms,不随重复下降 ⇒ Defender 常见的「扫一次后按哈希缓存」在此不成立;本机
Get-MpPreference的EnableFileHashComputation = False,与该现象相容。 - 签名无关:微软签名的系统 exe(
System32\hostname.exe150 /where.exe146.7ms)与自编未签名(114KB 144.4ms)、7MB Rust(149.4ms)同价 ⇒ 不是针对第三方二进制的签名/信誉校验,而是每次进程创建都付的统一成本(微软自家签名系统工具也不例外)。 - 环境侧(仅作背景,已非归因):
SecurityCenter2只注册 Windows Defender 一个 AV(RealTime / BehaviorMonitor / TamperProtection / NIS 全开,AMRunningMode = Normal),无第三方 AV/EDR 滤镜驱动;VBS在运行(VirtualizationBasedSecurityStatus = 2)且HVCI / 内存完整性在运行(SecurityServicesRunning = 2);bindflt(Windows Bind Filter Driver)Running/Auto;无内存压力(63.6GB 中空 35.1GB,页面文件 71/4096MB,CPU 4%);Smart App Control 关闭(VerifiedAndReputablePolicyState = 0,非 SAC)。 - 归因已改(决定性对照):同一脚本在普通 cmd 窗口跑 ⇒ 114KB 4.6 / 2.5MB 6.0 / 7MB 4.7ms、
CreateProcess1.7ms、进 main 前 5.0ms、退 main 后 1.3ms;而同一分钟在本会话内复测仍是 145.3-151.4ms ⇒ 该开销是本 agent 会话的进程派生链特有的。上面那些策略(VBS/HVCI/Defender 实时)在两侧完全相同,故不是原因——先前按「特征相符」做的归因已撤回,保留取证供后来者对照。⇒ 不需要为本项重启机器(机器本身 4.6-6.0ms,正常)。 - 会话内绕不过(已穷举):
CREATE_NO_WINDOW168.5 /DETACHED_PROCESS145.1 /CREATE_NEW_CONSOLE489.6ms(⇒ 控制台分配不是主因,但它本身也贵) /dangerouslyDisableSandbox无效 / WMIWin32_Process.Create、Start-Process、cmd /c均被工具策略拦截 ⇒ 未能从会话内建立干净的派生链。最可能的机制是 agent 注入层(同层的safe-delete钩子已实证注入进 Python 内部并劫持os.remove),但证据只到「会话特有」,机制未坐实。 - 处置(已执行):①不要为本项重启(机器本身正常);②已在普通窗口跑完整套
tmp/perf_probe/run_all_user.cmd,日志落tmp/perf_probe/user_run_logs/,§12.2 / §12.4 / §12.5 已改用该批真值;③基线对照:launch_cost_pre_reboot.txt(会话内 144.2 / 22.5 / 151.4 / 2.9ms)vs 清环境(3.5-5.0ms / CreateProcess 1.4-1.6ms / 进 main 前 4.0-4.9ms / 退 main 后 1.1-1.3ms)。不要据此判「引擎变慢」。
12.10 深挖:tokens 层形状差异(解释 §12.4 的方向矛盾)
工具 tmp/perf_probe/tokens_dig.py(逐文件 dump-tokens 单侧计时;n=5 中位)。
口径自警(重要):本表整体在会话内采集,且用固定常数扣启动(§12.1 已判其脆弱)⇒ 只作方向性参考;权威口径见 §12.4 的清环境压力五维(同一批语料、dump vs dump)。
| 语料 | KB | MoonBit 扣后 | Rust 扣后 | 比值 |
|---|---|---|---|---|
| body_500 | 6.9 | 23.9ms | -13.7ms | 噪声底,不可比 |
| body_5000 | 68.4 | 59.8ms | 3.8ms | 噪声底,不可比 |
| body_50000 | 683.7 | 509.5ms | 201.6ms | 2.53× |
| flat_500 / flat_2000 | 18.7 / 74.9 | 30.8 / 79.1ms | -4.8 / 5.3ms | 噪声底 |
| flat_8000 | 303.5 | 198.1ms | 58.8ms | 3.37× |
| locals_5000 | 162.8 | 102.8ms | 17.7ms | 5.81× |
| arr_1000 / arr_10000 | 3.9 / 38.2 | 21.2 / 46.9ms | -14.9 / -2.7ms | 噪声底 |
- 方向差异的成因 = 语料形状(清环境复核):
baseline是 366 个小文件(MoonBit/Rust 1.45×),stress17由大文件主导(2.13×)——两侧都是 MoonBit 更慢,只是小文件批量时差距小一半;大文件上逐字节差距显形,且差距随形状变(locals 最差)。⇒ 会话内那次把它读成「小文件 moon 更快(1.20×)」是写盘税不等比放大造成的假方向,已作废。 - 但不支持「超线性」:body 梯子(6.9KB→68.4KB→683.7KB)MoonBit 为 23.9→59.8→509.5ms,每 10× 尺寸为 2.5× / 8.5× 时间(指数 ≈ 0.93-1.0)⇒ 近似线性。与 §2/§11.6「差距随规模拉大」相容,但那是常数因子随形状变化,不是复杂度变化 —— 该措辞宜统一。
- 与 §12.2 的 16× 梯子合看(那里 native 4×→16× 略超线性、wasm 近似线性):两处都表明「增长指数」不是稳定结论,单点噪声太大,维持待复核,不翻案。
12.11 遗留与拍板项(2026-09-29,会话外复采后更新)
- 环境启动开销(§12.1/§12.9):已闭环 —— 定案为本 agent 会话特有(会话内 ~148ms / 会话外 3.5-5.0ms,同分钟对照),不需要重启、不需要动 VBS/HVCI/Defender;整套探针已在普通窗口复采,权威数字见 §12.2/§12.4/§12.5。⇒ 后续任何「逐进程」口径,一律在会话外采集(入口
tmp/perf_probe/run_all_user.cmd)。 - gateway
+native(§12.6):两条直觉修法(去+native/ 改library)均已实测证伪;拆包配方已实测通过(library 核心 + wasm-gc-only 外壳:全量 native RC=0、导出面在、消费者冒烟过)。现在只剩「是否落地」+ 落地时的连坐清单(host.js / ci.yml / pkg_deps / mbti / surface / 包图),并建议同时补一条 CI 全量 native release 构建门。 - §11.9-4 已销账:0.5.0 与 HEAD 在清环境下逐场景重合到 ±0.05(§12.2)⇒ 「三管线场景 1.24× 翻转」判为 §11.7 当日测量假象,按「不可复现、归因不可定」关闭。本轮硬结论 = 执行层 wasm-gc 快 2.0× / 2.7×(场景 8/9 三轮全 0.49 / 0.36-0.37),以此作新基线;管线层:lexer 0.62-0.65、parser 0.80、GC 0.33-0.49 偏 wasm,typeck/codegen 持平。
lexer 大输入方向存疑(§10 遗留项改写):1× 慢 1.28-1.41×,但 4× 持平、16× 反超到 0.70-0.74×(单输入 ~1.4MB)⇒ 「大输入是 wasm 唯一弱项」与实测相反;增长指数两侧都≈线性(native 4.04× / wasm 3.36× 对 4× 输入),不存在「wasm 超线性」。维持「待复核」,不翻案。- 压力三维(locals/flat/body)维持「记账不动手」:清环境比值 locals 3.08× / body 3.41× / flat 2.67×(§11.6: 3.53 / 3.80 / 3.14),同量级;触发线(真实场景端到端 >100ms)未越。
- 跨日绝对值异常(新,登记待查):段3 逐文件 compile 的 rust 侧绝对值 15.2ms → 7.2ms(moon 侧 9.4→10.7ms 不动),而比值 1.49× 与 §8.1 逐字吻合;当前
vitro_cli.exe是今日 10:58 构建的产物 ⇒ 怀疑 §11 之后 oracle 被重建过(flags 未知)。比值可用、跨日绝对值不可比。
13. S8 收官批全量性能复跑 + HEAD vs 0.7.0 同时段 A/B(2026-10-04,本地 HEAD 工作区)
AS-OF:2026-10-04 13:00-13:35。触发 = 新版本(S8 收官批,HEAD
c3351d6)全量性能验证。 口径:被测 = 本地 HEAD 工作区(c3351d6,moon.mod 仍 0.7.0);A/B 对照 = tagvitro-engine-0.7.0(git archive到tmp/perf_probe/ab070_tree/重建);机 = AMD Ryzen AI Max+ 395 / 16C32T / Win11(与 §1-§4/§12 同机);moon0.1.20260920;Rust oracle =native/target/release/vitro_cli.exe(Oct 3 22:06,find -newer= 0)。 探针纪律:产物全部落tmp/perf_probe/(gitignore/tmp/覆盖),工作区零流入;当日工作区另有用户并发的 demo 改动(7 文件 + 2 新增),本批零触碰。 结论速览:①无回归 —— 同小时交替 A/B(HEAD vs 0.7.0,5 轮)四层管线 0.86-1.01×、执行层计算密集三程序 0.99-1.08×,新版与上一发布版性能等价;②§12 全部比值基线复现(wasm/native 11 场景、时间旅行每步、执行层缺口、压力五维、moon/rust 逐文件 1.50 vs 1.49);③全栈对拍 361/6/0/0(语料 +1);④方法学新增:会话启动税(§12.1)可用 Windows 计划任务绕开 —— 派生链脱离 agent 注入层,启动开销回落 6.3ms(会话内 168ms),不必再人工开普通窗口;⑤低轮次中位在本机当前噪声下极脆(首轮冷启动 + 周期性尖峰),复采一律 ≥5 轮。
13.1 方法学:绕开会话启动税(可复用,替代 §12.1 的「必须人工开窗口」)
§12.1/§12.9 定案「agent 会话内进程创建 ~148ms、权威数字必须在普通窗口复采」。本轮实测给出无需人工开窗口的等价手段:把探针套件交给 Windows 计划任务跑。
| 派生链 | 114KB tiny | 7MB vitro_cli | 进 main 前 |
|---|---|---|---|
| agent 会话内(bash → python → 子进程) | 166.7ms | 168.4ms | 166.7ms |
| Windows 计划任务(Task Scheduler 派生) | 5.0ms | 6.4ms | 4.6ms |
| §12.9 普通 cmd 窗口(对照) | 4.6ms | 4.7ms | 5.0ms |
- 做法:PowerShell
Register-ScheduledTask(-Execute <python> -Argument <脚本> -WorkingDirectory D:\code\Vitro)+Start-ScheduledTask。任务由 Task Scheduler 服务派生,不在 agent 进程树内 ⇒ 不继承会话注入层。 - 编排器
tmp/perf_probe/run_suite_clean.py:把 §12.8 的 8 组探针串成一发(可--steps/--rounds裁剪),日志落user_run_logs_clean/<stamp>/,末尾写DONE.txt供轮询。 - 坑:
cmd /c/Start-Process/ WMIWin32_Process.Create在工具策略下被拦,Register-ScheduledTask可用(且cmd.exe从 Bash 调用一律被拦,故编排器写成 Python 而非.cmd)。
13.2 同时段 A/B:HEAD(S8) vs 0.7.0(决定性)
脚本 tmp/perf_probe/ab_head_vs_070.py(每轮 A/B 交替,5 轮),baseline367 同语料同口径,同一小时内:
| 项 | A=HEAD | B=0.7.0 | A/B |
|---|---|---|---|
| dump_tokens | 0.393s | 0.408s | 0.96× |
| dump_ast | 0.247s | 0.255s | 0.97× |
| dump_typeck | 0.240s | 0.278s | 0.86× |
| dump_compile | 0.305s | 0.301s | 1.01× |
| run fib(20) | 38.5ms | 35.7ms | 1.08× |
| run 冒泡200 | 138.9ms | 137.1ms | 1.01× |
| run 500×500 | 449.9ms | 452.9ms | 0.99× |
| run baseline 前 80 例(端到端) | 1.041s | 0.899s | 1.16× |
- 四层管线 0.86-1.01×(HEAD 不慢于 0.7.0);计算密集执行 0.99-1.08×(等价)。⇒ S8 批未引入可测回归。
- 唯一 >1.1 项(baseline 80 例端到端 1.16×)由进程启动主导(80 进程 ×~10ms),且为整段 sweep 交替(非逐例交替),段内漂移可致偏 ⇒ 不作结论,登记(§13.8-3)。
- 旁证:dump 工具 exe 体积 HEAD/0.7.0 逐一相同(637440 / 930304 / 366592 / 821760),但 moonc 把绝对源路径写进
#line(§11.8 已录)⇒ 哈希必然不同,哈希不可判等,只能实测。
13.3 四层管线 + 多维(vs §12.4)
run_suite_clean.py 的 3 轮版本中位被尖峰污染(tokens baseline 1.223s),重采 5 轮 ×2 次:
| 层(baseline367,3-5 轮中位) | 复跑 r1 | 复跑 r2 | A/B 的 A 列 | §12.4 | 判定 |
|---|---|---|---|---|---|
| dump_tokens | 0.429s | 0.417s | 0.393s | 0.357 / 0.370s | ✅ 同量级 |
| dump_ast | 0.296s | 0.283s | 0.247s | 0.241 / 0.246s | ✅ |
| dump_typeck | 0.299s | 0.261s | 0.240s | 0.237 / 0.241s | ✅ |
| dump_compile | 0.358s | 0.397s | 0.305s | 0.275 / 0.280s | ✅ |
- 首轮冷启动 + 周期性尖峰是主噪声源:rounds 常现
[1.6, 0.28, 0.30, 0.31, 0.25]形态(首轮 ~5×),3 轮中位会被尖峰抬 2-3×。⇒ 复采纪律:≥5 轮(bench_pipeline.py默认 3 轮建议改 5)。 - 语料 baseline = 367 例(165KB)(§12 时 366,+1 新例);knr 81 / leetcode 138 / gap 17。
- 多维(02 步):段1 启动 rust 6.0 / moon 13.7ms = 2.28×(§12.4 2.4×);段3 逐文件 compile moon/rust 总耗时 1.50× / 1.51×(§12.4 1.49×),单文件中位 rust 8.9-9.2 / moon 13.6-13.7ms;段4 用户场景(Rust-only)compile/run 中位 10.1 / 10.9ms(§12.4 6.4 / 8.0 系当日 oracle 重建后的低值,§11.2 为 9.3 / 10.8 ⇒ 本轮与 §11.2 更近);非 0 退出 6 例逐字同。
- 段2(tokens 目录批处理)本轮 2 轮中位 moon 0.68-0.72s,比同操作的 01 步 5 轮中位(0.417-0.429s)高 1.6-1.7× ⇒ 该段只有 2 轮且复用同一输出目录,尖峰即翻倍,本环境不可信;需要 tokens 批处理比值时以 01 步 5 轮为准。
13.4 wasm-gc 双后端(vs §12.2)
wasm_bench_head(依赖经 .mooncakes/vitro/engine 目录联接指向本地 HEAD;旧副本系 0.6.0 陈旧拷贝,已改名让位)双后端 ×3 轮(场景 0 前后自校准 / 5 轮中位):
| 场景(纯算 wasm/native,<1 = wasm 快) | 本轮 r1 / r2 / r3 | §12.2(HEAD) | 判定 |
|---|---|---|---|
| 1 lexer ×200 | 0.64 / 0.59 / 0.59 | 0.62-0.65 | ✅ |
| 2 parser ×150 | 0.77 / 0.75 / 0.72 | 0.80 | ✅ |
| 3 typeck ×100 | 0.90 / 0.98 / 0.93 | 0.94-0.98 | ✅ |
| 4 codegen ×100 | 0.92 / 0.93 / 0.97 | 0.92-0.94 | ✅ |
| 5 GC 压力 ×200 | 0.47 / 0.44 / 0.46 | 0.33-0.49 | ✅ |
| 6 lexer 大输入 ×50 | 1.15 / 1.25 / 1.47 | 1.32-1.49 | ✅ |
| 8 VM 执行 fib(20) ×10 | 0.51 / 0.49 / 0.50 | 0.49 | ✅ wasm 快 2.0× |
| 9 VM 执行 nested300 ×3 | 0.36 / 0.36 / 0.38 | 0.36-0.37 | ✅ wasm 快 2.7× |
| 10 / 11 / 12 大输入 1× / 4× / 16× | 1.28 / 0.86 / 0.75 | 1.28 / 0.86 / 0.70 | ✅ |
- 启动 native
场景09.5-10.8ms / moonrun 20.4-22.7ms(§12.2 7.6-9.5 / 17.1-18.0,同量级略高);产物体积 wasm 622,279B / native exe 1,238,528B。 - 方法对齐对照(0.5.0 旧探针,同小时)lexer 0.65/0.62/0.64、parser 0.89/0.78/0.80、typeck 1.06/0.99/1.18、codegen 0.94/1.04/0.98、GC 0.48/0.47/0.47、biglex 1.33/1.34/1.28 —— 与 §12.2 的 0.5.0 列(0.63/0.79/0.96/0.92/0.48/1.39)重合 ⇒ 方法本身可信,§11.9-4 的销账维持。
- 执行层最硬结论沿用:wasm-gc 跑完整引擎比 native 快 2.0× / 2.7×(场景 8/9 三轮全 0.49-0.51 / 0.36-0.38)。
13.5 时间旅行 + 执行层(vs §12.5)
口径补注(2026-10-04 复核,补前文未写明):下表
unified三列是 Rust oracle(vitro_cli unified,冻结区)的实测,不是 MoonBit 侧——探针(ext_cmp/run_cmp.py线 3)只测过 Rust unified,moonbit/cmd/亦无 unified 入口。⇒ MoonBit 引擎的时间旅行至今无任何实测数字;MoonBit 侧已按 ⑤-5.1 拆掉每步 1MB 全量快照(time_travel/engine.mbt:155/253,Trap 回退改「检查点+正向重放」),但该改造的效果从未被量过。引用本节数字时勿当作「MoonBit 引擎的时间旅行性能」;测法与缺口见 §14。
| 程序 | CPython | Rust run | MoonBit run | MB/Rust | unified | 步数 | 每步 | 峰值 |
|---|---|---|---|---|---|---|---|---|
| fib(20) | 0.51ms | 20.8ms | 36.2ms | 1.74× | 6.48s | 284,591 | 22.76μs | 28.9MB |
| 冒泡 200 | 2.07ms | 21.0ms | 135.2ms | 6.43× | 61.81s | 1,621,540 | 38.12μs | 48.0MB |
| 500×500 | 14.24ms | 28.3ms | 447.1ms | 15.80× | >75s 超时 | — | — | 27.5MB |
- 与 §12.5(22.20 / 35.92μs;29.0 / 47.8MB;1.87 / 6.60 / 18.27×)逐项吻合,步数逐字复现(284,591 / 1,621,540)⇒「每步 CPU 是病灶、内存温和」的裁定与 §3 优化方案量化前提原样成立。
- baseline367 端到端 run:MoonBit 中位 16.1ms / Rust 9.7ms = 1.66×(§12.5 1.68×)。
13.6 压力五维(vs §12.4,run_stress.py dump vs dump 同口径,3 轮中位)
| 维度(小→大,比值 = moon/rust) | 本轮 | §12.4 | 判定 |
|---|---|---|---|
| 深嵌套 nest_4 → 14 | 1.72 → 1.67× | 1.71 → 1.55× | ✅ |
| 平铺 flat_500 → 8000 | 2.11 → 3.11× | 2.24 → 2.67× | ✅ |
| 巨体 body_500 → 50000 | 1.80 → 3.25× | 2.16 → 3.41× | ✅ |
| 大数组 arr_1000 → 10000 | 1.94 → 2.46× | 1.68 → 2.38× | ✅ |
| 局部变量 locals_1000 → 5000 | 2.57 → 3.47× | 2.50 → 3.08× | ✅ |
- 设计性拒绝两侧同构复现:
arr_50000(全局数据区 60KB)+expr_1000/5000/20000(E1006)= 4 文件;MoonBit 走fail_json(rc=0 + 产物ok:false)、Rust rc=1 —— 与 §11.6/§12.4 逐条同。 - 执行层附加段(端到端 run,含编译)moon/rust 0.99-2.99×(§12.4 1.00-3.10×),形状依赖同前;
locals_5000两侧持平(0.99×)。
13.7 正确性:全 MoonBit 栈对拍(非性能面,一并复核)
cmd/run(lexer→parser→typeck→codegen→VM)× baseline 367 例,逐例对拍 Rust vitro_cli run 的 stdout + 返回码:
| 归类 | §12.3(366 例) | 本轮(367 例) |
|---|---|---|
| 逐例一致 SAME | 360 | 361 |
| 两侧同拒 | 6 | 6 |
| MoonBit 拒 / Rust 成功 | 0 | 0 |
| 真语义 DIFF | 0 | 0 |
- +1 SAME 即新语料例;§11.9 两缺口(va_copy / 自定义 include)保持闭环,366→367 例无崩溃无超时无非预期差异。
13.8 遗留与登记
- 低轮次中位脆(首轮冷 + 周期尖峰):§12 口径「3 轮中位」在本机当前状态下会被抬 2-3×;后续复跑一律 ≥5 轮。
tmp/perf_probe/out/持续膨胀(本轮后 7.1GB、含 893 个*_old_*陈旧目录)——改名让位法只改名不清理(§12.7-1),长期需一次性清理;不影响任何结果(计时只覆盖被测 exe)。- baseline 端到端 A/B 1.16× 未定(启动主导 + 整段 sweep 非逐例交替),登记待「逐例交替」复测;计算密集三程序已证等价,故不作回归线索。
- 跨日绝对值不可比已知项再确认:§12.11-6 的 oracle 重建疑云 + 本轮环境抬升(同时段 A/B 显示 HEAD 本身 0.393/0.247/0.240/0.305,比同日 01 步 5 轮中位低 5-20%)⇒ 判据永远是比值或同时段 A/B,不是跨日绝对值。
- 压力三维(locals/flat/body)维持「记账不动手」:触发线(真实场景端到端 >100ms)未越。§10 遗留项(wasm 大输入方向、SpiderMonkey/JSC 口径)状态不变。
13.9 复跑资产
| 资产 | 位置 | 复跑 |
|---|---|---|
| 干净派生链编排器(新) | tmp/perf_probe/run_suite_clean.py |
计划任务:-Execute <py> -Argument "tmp\perf_probe\run_suite_clean.py --stamp <s> [--steps 01,02] [--rounds 5]";会话内直接跑无效(启动税) |
| HEAD vs 0.7.0 A/B(新) | tmp/perf_probe/ab_head_vs_070.py + tmp/perf_probe/ab070_tree/(tag vitro-engine-0.7.0 经 git archive 重建树) |
AB_ROUNDS=5 python ab_head_vs_070.py(须计划任务) |
| 本轮日志 | tmp/perf_probe/user_run_logs_clean/20261004_{head,r1,r2}/、tmp/perf_probe/ab_out/ab_ab.log |
— |
| 其余 8 套 | 同 §12.8(bench_pipeline / bench_compare / run_stress / ext_cmp/run_cmp.py / bench_moon_run / diff_moon_run_full / wasm_bench_head / wasm_bench) |
各脚本头注 |
前置:全量
moon build --release --target native本轮 35 tasks / 0 errors / 5m46s 通过(gateway 拆包后全量 native 门成立,§12.6 已闭环);cmd/run仍受 MSVC cliff 支配(§11.8)。
14. 时间旅行优化现状 + JIT 正交性(2026-10-04 复核,代码级)
触发:用户问「时间旅行如何优化 / JIT 要不要重启」。本节是读码 + 文档交叉复核结论,无新实测(实测缺口见 §14.2)。
14.1 §3 处方的落地状态(MoonBit 侧 = 存续实现)
| §3 处方(按杠杆排序) | 状态 | 证据 |
|---|---|---|
| ② checkpoint + 确定性重放 | ✅ 已落 | time_travel/engine.mbt:155「不再每步拍 1MB 全量快照(Rust engine.rs:169-170 的 pre_step_snap 机制」+ :253「⑤-5.1:无每步快照(pre_step_snap 不迁)」+ :366 rollback_before_trap(检查点+正向重放到 trap 前一步);S8 三段-c(2026-10-01) |
| ④ 语句边界粒度 + 环形历史窗口(次要) | △ 窗口已落 / 粒度未改 | 环形窗口:time_travel/window.mbt FrameWindow(@deque 两端 O(1) 摊还,参数 2_000/0.2 逐字保留)已落;但 engine.mbt:254 仍是 match vm.step() 之后每指令步一次 collect——语句边界粒度未做(§3「教学单步语义是语句级,指令级全量记录无消费方」原话) |
| ① 按需物化(原「主攻」) | ❌ 未做 | time_travel/collector.mbt:71 collect 仍无条件每步构建完整 StepPayload(local_vars + pointer_snapshots + 语义标签 + 算法推断;照搬 Rust collector.rs) |
| ③ 写集 undo log | ❌ 未做 | time_travel/*.mbt 全量 grep undo / 旧值 / AccessType 零命中 |
⇒ 「消每步 1MB 快照」已兑现(常态 O(1MB)→O(1),trap 帧 O(interval));剩余大头 = 每步 collect 的对象构建——与 §3 原判「真病灶是每步 CPU(collector 无条件重建快照对象)」同址。
14.2 实测缺口(补测前任何「要不要做 ①」都是脑测)
- MoonBit 侧时间旅行零实测:§3/§12.5/§13.5 的全部 unified 数字(21 / 22.76 / 38.12μs 每步)都是 Rust oracle;
moonbit/cmd/只有run/serve,无 unified 入口,探针从未测过 MoonBit 侧(见 §13.5 口径补注)。 - 两个测法:(a) 临时探针模块直调
UnifiedEngine::run_batch(照tmp/perf_probe/wasm_bench_head形态:junction 到本地moonbit/+moon build --release --target native)→ 干净的 μs/步;(b) 驱动cmd/servestep 族数 N 步 → 含 wire 开销,只能当上界。建议 (a),并把它并成scripts/perf_baseline的新 mode(复用刚入库的留证机制,§13.9)。 - 不要动 Rust 侧:
native/是冻结的 diff oracle 且 0.9.0 脱钩、1.0 退役——优化它零收益。
14.3 验收线须产品定
优化须可证伪,例如「任意教学程序整段回放到末尾 ≤3s」。当前无此目标,故 §3 当时给的量化目标(每步 21μs→<0.5μs)只是工程目标,不是验收线(§10 触发线同款逻辑)。
14.4 JIT:与本议题正交,且从未被永久关闭
- 正交:JIT 加速「解释执行 opcode」(全速执行);时间旅行成本在「每步采集」。§3/§4 路线裁定本身就把两者分开——全速执行正解 = bytecode→wasm 生成器(§4.1,已由 wasm-gc 出口拿到执行层 2.0-2.8×);unified/单步 = 解释器 + 按需物化(§3)。
- 现状:F-3「JIT 倾向不搬」,依据「宿主 V8 自带 JIT」;架构审阅
20260921§2.5 判 P1——该依据只对 wasm-gc 出口成立,native 出口不成立(门 1 实测解释器 512ms vs JIT 55ms = 8.8×),建议按出口分别裁定。 - 排期:S9 = 「JIT 复核」;0.8.0 明确含「JIT 评估(只判定书不实现——S9 复核输入)」;W^X 加载器先例已备(kimicc
jit/stub.c:139-206,约 500 行总代价,调查报告 §4.4)。 - ⇒ 不需要"重启":它从未被关闭,是已排期的复核 + 判定书;真正决定其命运的是出口裁定(native 出口是否保留),不是性能数字。
15. S8 交付面全量性能实测(2026-10-04 晚,CLI 口径 + 库级对照)
AS-OF:2026-10-04 21:20–21:35。触发 = 新 CLI 出口(
vitro,a66e5c9)就位后的首次 S8 交付面全量性能实测。 口径:两臂——CLI 臂 =vitro逐进程端到端(含进程创建 + gateway JSON wire);库级臂 =tmp/perf_probe/s8_bench直调引擎(纯算,扣启动)。两臂均经 Windows 计划任务启动(绕 agent 会话启动税:CLI 臂 boot 11.7ms / 库级 9ms,会话内对照 128ms)。 机/构建:AMD Ryzen AI Max+ 395 / 16C32T / Win11;MOON_CC=clang(全量 native 29s)。
15.1 CLI 臂(vitro <cmd>,逐进程端到端,5 轮中位)
| 场景 | 中位 | 派生 |
|---|---|---|
boot(api ping) |
11.7ms | 启动基线 |
compile fib / bubble |
15.5 / 12.9ms | |
run fib(20) / bubble(200) / nested(500×500) |
32.8 / 144.7 / 446.4ms | 对 §13.5 的 Rust run 20.8/21.0/28.3ms → mb/Rust 1.58 / 6.89 / 15.8×(§13.5 记 1.74 / 6.43 / 15.80×,同量级) |
step fib(20) 全量 284,591 帧 |
25,194ms | 88.5 μs/帧(含 wire) |
step bubble 截断 199,999 帧 |
41,871ms | 209 μs/帧 |
api compile(teaching) |
9.5ms | 帧出 algorithm_matches |
api diagnostics_probe |
9.1ms | 八段全出 |
api ast.dump |
8.9ms |
15.2 库级臂(纯引擎 tmp/perf_probe/s8_bench,5 轮中位扣启动)
| 场景 | 纯算 | 派生 |
|---|---|---|
| unified fib(20)(284,591 帧) | 4043ms | 14.2 μs/帧 |
| unified bubble 截断(400,000 帧) | 24,738ms | 61.8 μs/帧 |
| 逐步 batch=1(2000 次调用) | 32.1ms | 16.1 μs/次 |
| seek_to 窗内 ×200 | 1514ms | 7.57 ms/次 |
| seek_to 越窗 ×50(检查点 + 正向重放) | 2779ms | 55.6 ms/次(窗内的 7.3×) |
| detect_algorithms ×2000 | 246.8ms | 61.7 μs/次(判据锚在函数体——写在 main 里合法零命中,实测首撞) |
| diagnostics 认知链 ×2000 | 87.0ms | 43.5 μs/轮 |
| analysis M14 trap ×200 | 1158ms | traps=400 / hints=400(全触发,接线有效) |
15.3 主轴结论
- wire 主导 time_travel 帧流:同一 fib(20) 的 284,591 帧——纯引擎 4.04s vs CLI 端到端 25.19s ⇒ gateway JSON wire 占 ~84%(引擎仅 16%)。与 §3「每步 CPU 是病灶」互补:那是引擎内每步 collect 的成本,此处是出口层每步 encode/往返的成本——教学帧流若经 CLI 批量消费,瓶颈在协议层不在引擎。
- S8 四面首次有 mb 侧实测数字:time_travel(unified 跑完 / 逐步 / seek 越窗)、teaching(判据 ~62μs/次)、analysis(M14 400/400 全触发)、diagnostics(~44μs/轮)。
- 无回归:
run三程序与 §13.5 逐项吻合(nested 1.00×)。 - seek 越窗 55.6ms/次(= 最近检查点 + 正向重放到 trap 前一步,⑤-5.1 落地形态);窗内 7.57ms/次。
15.4 探针资产与复跑
| 资产 | 位置 | 复跑 |
|---|---|---|
| CLI 套件(新) | tmp/perf_probe/cli_bench.py |
计划任务:-Execute <py> -Argument D:\code\Vitro\tmp\perf_probe\cli_bench.py;结果 tmp/perf_probe/cli_bench_out/<stamp>/results.json(会写 DONE.txt) |
| 库级套件 | tmp/perf_probe/s8_bench/(run_bench.py);计划任务包装 run_s8_task.py |
包装会自动设 S8_EXE 指向 _build/.../s8_bench/src/src.exe(直接跑 run_bench.py 的自动发现会误选 dump_*.exe) |
测量纪律:两臂都必须在计划任务/普通窗口跑(会话内进程创建 ~128ms 会污染快场景);测量期间勿构建——同批实测中一次
step因并行构建把vitro.exe换掉而rc=1,复跑即 rc=3 正常。
16. wasm-gc 出口全场景性能实测(2026-10-04 晚,Node 宿主 + gateway)
AS-OF:2026-10-04 21:45–21:55。触发 = 用户拍板「wasm-gc 是主出口(用户最多),必须全域测」——CLI(
vitro)只服务少数高手/agent,且 10 个cmd/*全supported_targets="native",CLI 测不了 wasm-gc。 口径:Node 宿主(system Node 25——js-string 必需,PATH 里的 22 报illegal cast)+gateway wasm-gc产物(moonbit/_build/wasm-gc/release/build/gateway/wasm/wasm.wasm,867,318B),经g.invoke(ndjson)发与 native CLI 同一批协议请求(可直接对照)。探针tmp/perf_probe/wasm_cli_bench.js;驱动wasm_bench.py(外层 wall + 场景 0 校准;计划任务)。 boot(Node 启动 + wasm 实例化)= 45.5ms。
16.1 结果(14 场景,5 轮中位)
| 场景 | wall | 派生 |
|---|---|---|
| boot | 45.5ms | |
compile fib / bubble ×50 |
75.3 / 86.2ms | 0.60 / 0.75 ms/次 |
run fib(20) / bubble(200) / nested(500) |
99.4 / 243.3 / 442.9ms | 11.1 / 38.9 / 132.2 ms/次 |
step fib(20) 全量 284,591 帧 |
6,145.6ms | 21.4 μs/帧 |
step bubble 199,999 帧 |
8,060.6ms | 41.9 μs/帧 |
seek 窗内 ×200(建流 12 万帧) |
2784.2ms | seek 11.3 μs/次 |
seek 越窗 ×50(检查点 + 正向重放) |
4160.6ms | seek 28.0 ms/次(窗内的 2477×) |
diagnostics_probe ×200 |
206.4ms | 0.79 ms/轮 |
| teaching(compile 帧)×200 | 153.4ms | 0.54 ms/轮 |
ast.dump ×200 |
140.7ms | 0.46 ms/轮 |
memory.regions ×200 |
190.9ms | 0.70 ms/轮 |
16.2 与 native CLI 臂对照(同请求序列,pure 口径——各扣自身启动:native 11.7ms / wasm 45.5ms)
⚠️ 口径注:不可用 wall 直接比——wasm 的 boot(Node 启动 + wasm 实例化 45.5ms)远大于 native CLI(11.7ms),wall 差会把 wasm 的启动税算进来。下表两侧均为 pure = wall − boot。
| 场景 | native CLI pure | wasm-gc pure | 比值 |
|---|---|---|---|
compile fib |
3.8ms | 0.60ms | 0.16× |
compile bubble |
1.2ms | 0.81ms | 0.68× |
run fib(20) |
21.1ms | 10.8ms | 0.51× |
run bubble(200) |
133.0ms | 39.6ms | 0.30× |
run nested(500×500) |
434.7ms | 132.5ms | 0.30× |
step fib(20) 284,591 帧 |
25,182.6ms | 6,100.1ms | 0.24× |
step bubble 199,999 帧 |
41,859.5ms | 8,015.1ms | 0.19× |
⇒ wasm-gc 在全部七项上快 native CLI 1.5–6.3×(含 run 与 compile)。
16.3 结论
- wasm-gc 全面优于 native CLI(1.5–6.3×) ⇒ 印证「wasm-gc 是主出口」;native 出口最差的是帧流(
step,wasm 快 4–5×)与编译(compile,wasm 快 6.3×)。 - wasm 的 wire 成本极低:wasm
stepfib(20) 6.15s(含 gateway 编解码 + Node 宿主)vs native 纯引擎 4.04s 仅 1.5×;而 native CLI 是 25.19s ⇒ native CLI 的 25s 主要来自 native 运行时壳层(同引擎在 V8 上只 6.1s)。与 §15.3「wire 占 84%」合读:那是 native 侧的壳层成本结构(协议层 74μs/帧),wasm 侧不成立(gateway 层仅 ~7μs/帧)。 - compile 面 wasm 亦优(0.60–0.81 ms/次 vs native 1.2–3.8ms)。
- seek 有效且成本随距离陡增:窗内 11.3μs vs 越窗 28.0ms(2477×)——越窗 = 最近检查点 + 正向重放(⑤-5.1 形态)。正确性已验证:seek 响应
payload.step_index== 目标步;seek 后step.next从目标继续(wasm_seek_verify.js)。
16.4 探针资产与坑
| 资产 | 位置 |
|---|---|
| wasm 套件(新) | tmp/perf_probe/wasm_cli_bench.js(14 场景)+ wasm_bench.py(驱动) |
| seek 正确性验证(新) | tmp/perf_probe/wasm_seek_verify.js(判据 = payload.step_index == 目标) |
| 出口形态 | 宿主 scripts/wasm_gateway/host.js(builtins:['js-string'] + g.invoke);产物 moonbit/_build/wasm-gc/release/build/gateway/wasm/wasm.wasm |
坑(两条,均在探针侧):
- Node 版本:wasm-gc 的 js-string 需 Node 25——PATH 里的 22.22.2 报
illegal cast(host.js头注已记判定面在 25)。 step.next首批可返 0 帧(延迟一帧):建流循环若在 0 帧break⇒ 建流失败。首版实测踩坑:seek 目标退化为 0 ⇒ 测出 3.8μs 的假数(修后为 11.3μs 窗内 / 28.0ms 越窗)。
17. 跨实现执行性能对照(2026-10-04 晚)——mb vs Clang / CPython / V8
AS-OF:2026-10-04 22:05。触发 = 用户问「和其他实现对比呢」。 口径:程序内计时(排除进程启动),三程序与
ext_cmp/同源(fib(20) / bubble 200 / nested 500×500);mb 侧 =runpure −compilepure(只比执行)。探针tmp/perf_probe/xlang_cmp.py。
| 程序 | Clang -O2 | CPython 3.13 | Node 25 / V8 | mb-wasm(gc) | mb-native |
|---|---|---|---|---|---|
| fib(20)(21,891 次调用) | 0.011ms | 0.515ms | 0.163ms | 10.2ms | 17.3ms |
| bubble 200 | 0.008ms | 2.460ms | 0.429ms | 38.8ms | 131.8ms |
| nested 500×500 | 0.140ms | 13.786ms | 2.372ms | 131.9ms | 430.9ms |
mb / 各基准(倍数;每格 = wasm / native):
| 程序 | vs CPython | vs V8(JIT) | vs Clang -O2 |
|---|---|---|---|
| fib(20) | 19.8× / 33.6× | 62.6× / 106× | 927× / 1573× |
| bubble 200 | 15.8× / 53.6× | 90× / 307× | 4850× / 16475× |
| nested 500×500 | 9.6× / 31.3× | 55.6× / 182× | 942× / 3078× |
17.1 结论
- mb 的 VM 全速执行远慢于 CPython(wasm 9.6–19.8×、native 31–54×)。CPython 是纯字节码解释器(无 JIT)——最公平的可比对象;V8 有 JIT、Clang 是静态优化,仅作上界。
- nested(纯算术、零内存访问)也慢 9.6×(wasm)/ 31.3×(native) ⇒ 不是内存安全检查或教学插桩的锅,是 VM 解释循环本身的效率。
- 执行层层级(nested 500×500,ms):Clang-O2 0.14 < V8 2.37 < CPython 13.79 < Rust VM 28.3(§13.5)< mb-wasm 131.9 < mb-native 430.9。
注意:Rust oracle 的 VM 亦慢于 CPython(28.3 vs 13.8 = 2.05×)⇒ 该短板自 Rust 期继承,非 MoonBit 迁移引入。
- 与 §16 合读:mb 的采集 / 时间旅行层(每步 collect)与 Rust 打平甚至更快(§16.3),但全速执行层是根本短板 ⇒ 优化优先级 = VM 解释循环(§4.1 的 bytecode→wasm 生成器只给 2–2.8×,量级不足以补齐 10–30× 的差距,需单独评估)。已挂 issue #41(主项 + native CLI 壳层待评估次级项)。
- 口径注:Clang
-O2会对固定规模做常量折叠 / 向量化(bubble 0.008ms 系整段被优化),仅作上界不作等价比;CPython 数字经调用计数复核(fib(20)=6765 / calls=21891)。