Skip to content

docs(vm): discuss execution architecture redesign - #21

Draft
Eric-Song-Nop wants to merge 13 commits into
perf/ordinary-property-kernelfrom
vm/primitive-execution-core
Draft

docs(vm): discuss execution architecture redesign#21
Eric-Song-Nop wants to merge 13 commits into
perf/ordinary-property-kernelfrom
vm/primitive-execution-core

Conversation

@Eric-Song-Nop

@Eric-Song-Nop Eric-Song-Nop commented Sep 12, 2026

Copy link
Copy Markdown

本 PR 当前只保留设计计划与兼容性清单,基于 PR #19。之前的实现已撤回;benchmark 工具、报告、比较数据和已撤回实现的验证记录均已从当前 PR 内容移除。

当前没有引擎代码改动,没有完成优化,也没有可申报的性能收益。

计划仍待根据设计讨论修订,尤其是撤回“首版必须采用 SSA”的决定,重新评估如何保留原有完整编译体系并改进执行架构。现有文档不是已确认的实施方案,PR 尚不具备合并条件。

后续目标仍是同时完成合理、可维护的架构与 issue #16 本轮问题的解决。本文不关闭 #16,也不声称完成 #20 的 Task/Fiber 设计。

@lodyai
lodyai Bot force-pushed the vm/primitive-execution-core branch from a701862 to 7788c22 Compare September 12, 2026 09:55
@Eric-Song-Nop Eric-Song-Nop changed the title feat(vm): migrate to primitive execution architecture docs(vm): discuss execution architecture redesign Sep 12, 2026
Save the compiler and publication refactors, instruction contracts, profiling, and owned frame/slot execution with the in-progress S04 call, binding, conversion, and unwind migration.

Validation: driver 76, run 9, and eval 142 tests pass; formatting, source layout, and boundary scan pass. Three native-stack tests remain failing. S04 is not accepted and S05-S10 remain pending; this is an implementation checkpoint.
Return root handoffs through the bytecode entry before invoking the legacy
driver, and separate ordinary call dispatch from larger cold temporaries.
Track real module host delimiters and verify captured bindings, readonly
imports, unwind cleanup, and finite versus infinite recursion.

Add scoped call preparation diagnostics and share unary-plus primitive
semantics to preserve BigInt errors and callback numeric representations.
Update migration evidence and boundary canaries with the implementation.
@Eric-Song-Nop

Copy link
Copy Markdown
Author

S04 实测回归:benchmark、硬件计数与 Profile 证据

测量日期:2026-09-13。源码固定为 4fd9900b0672af695ccb632b355ea2e79e459ccf,与本次评论发布前核对的 PR HEAD 相同。没有修改生产代码。

结论:启用 S04 stack-vm 后,完整 50 项固定 microbench 的等权几何平均耗时增加 11.04%;普通调用、原语循环存在显著回退。固定版 Earley-Boyer 在新配置下 5/5 次栈溢出,旧配置 5/5 次通过。硬件计数和真实 release 汇编进一步确认额外指令与栈操作/调用管理热点,不能把这些结果仅归为机器负载或“后续自然会优化”。

这是同提交旧 VM(默认配置)与 stack-vm 配置的比较,不是 S01 前基线到 S04 的累计改进,也不是与 QuickJS 的比较。stack-vm 仍带迁移桥,本实验没有测量每项工作量的新核心覆盖率。

1. 测量方法与可复现身份

  • PocketLab eric-83am;AMD Ryzen 7 7840HS,16 个逻辑 CPU;Linux 6.18.44-1-lts x86_64。
  • rustc 1.94.1 (e408947bf),LLVM 21.1.8。两者均为普通 release,不含 profiling feature;未设置 RUSTFLAGS/CARGO_ENCODED_RUSTFLAGS/CARGO_BUILD_TARGET。
  • 两套构建串行完成后再计时;启动计时和抽查时未观察到其他构建/测试重叠,桌面及后台服务仍在。固定 CPU 2,动态频率未锁定,也未隔离 SMT 同胞线程,不能称为完全隔离环境。
  • 使用现有 docs/reports/data-structure-fixed-final.json50+8 固定工作量,所有文件哈希匹配;每个引擎每项 5 轮,交错顺序,取中位数。没有缩小工作量或提高栈预算。
  • 指标为整进程 wall-clock 时间,包含启动、编译、执行、输出和清理;不是 CPU 时间、纯 VM 时间或自适应 V8 分数。固定 V8 每个注册 benchmark 执行一次 Setup/run/TearDown,保留原断言。
  • 580 个样本:575 成功,5 失败。失败项不计速度比;不发布完整 58 项或 V8 总成绩。
# 在上述提交的干净工作区,两个命令分别执行、输出目录保持独立
cargo build --locked --release -p quickjs-oxide-cli --no-default-features --jobs 2 --target-dir target/s04-benchmark/legacy
cargo build --locked --release -p quickjs-oxide-cli --no-default-features --features stack-vm --jobs 2 --target-dir target/s04-benchmark/stack
python3 scripts/benchmark/fixed.py --manifest docs/reports/data-structure-fixed-final.json --engine legacy=target/s04-benchmark/legacy/release/qjs --engine stack=target/s04-benchmark/stack/release/qjs --repeat 5 --cpu 2 --timeout 60 --output target/s04-benchmark/fixed-58

构建时两者均设置 QUICKJS_OXIDE_BUILD_COMMIT 为上述完整提交。复跑需使用新的输出目录,并准备 manifest 所引用的外部工作量文件。二进制 SHA-256:

legacy  440cf60d9871b584120100396d6d853a8d35ce95720ba491fd4a22229add6494
stack   706cdbe649824225ca29b98945294f796d4d6ba65ffacdf970b8181e52af8d2d

2. Benchmark 完整结果

50 项 microbench 全部可比较。几何平均 legacy / stack = 0.9005465×,倒数耗时倍率为 1.1104368×,即 +11.04%。这是等权用例汇总,不是通用应用性能预测。小幅差异不宣称统计显著。

展开完整 58 项结果(ms;正数表示新配置更慢)
Case Legacy ms Stack ms Stack time change Legacy / stack
empty_loop 645.67 936.99 +45.12% 0.6891x
empty_down_loop 489.13 713.23 +45.82% 0.6858x
prop_read 778.64 1145.60 +47.13% 0.6797x
prop_write 321.90 334.69 +3.97% 0.9618x
prop_update 432.19 449.27 +3.95% 0.9620x
prop_create 395.74 382.73 -3.29% 1.0340x
prop_clone 331.83 323.71 -2.45% 1.0251x
prop_delete 401.80 405.07 +0.81% 0.9919x
array_read 497.36 520.08 +4.57% 0.9563x
array_write 468.12 471.87 +0.80% 0.9921x
array_update 475.65 474.49 -0.24% 1.0024x
array_prop_create 589.52 577.44 -2.05% 1.0209x
array_slice 378.39 379.63 +0.33% 0.9967x
array_length_read 705.06 1045.30 +48.26% 0.6745x
array_length_decr 549.55 564.31 +2.69% 0.9738x
array_push 610.83 607.25 -0.59% 1.0059x
array_pop 567.50 568.61 +0.20% 0.9981x
typed_array_read 356.48 386.59 +8.45% 0.9221x
typed_array_write 289.34 308.09 +6.48% 0.9391x
arguments_read 368.11 437.36 +18.81% 0.8417x
arguments_strict_read 345.54 414.04 +19.82% 0.8346x
global_read 396.17 746.61 +88.45% 0.5306x
global_write 500.17 767.37 +53.42% 0.6518x
local_destruct 139.75 140.36 +0.43% 0.9957x
global_func_call 846.87 1440.89 +70.14% 0.5877x
func_call 832.95 1313.46 +57.69% 0.6342x
func_closure_call 906.30 1554.81 +71.55% 0.5829x
int_arith 699.63 986.92 +41.06% 0.7089x
float_arith 749.24 1097.97 +46.55% 0.6824x
bigint64_arith 465.03 463.14 -0.40% 1.0041x
map_set_string 39.46 39.06 -1.03% 1.0104x
map_set_int 52.61 52.10 -0.96% 1.0097x
map_delete 61.42 60.31 -1.82% 1.0185x
weak_map_set 362.10 358.41 -1.02% 1.0103x
array_for 481.91 487.22 +1.10% 0.9891x
array_for_in 834.03 843.69 +1.16% 0.9885x
array_for_of 572.86 571.27 -0.28% 1.0028x
math_min 804.11 807.38 +0.41% 0.9960x
regexp_ascii 419.70 429.74 +2.39% 0.9766x
regexp_utf16 426.25 427.45 +0.28% 0.9972x
regexp_replace 786.52 793.33 +0.87% 0.9914x
string_length 650.02 647.40 -0.40% 1.0041x
string_build1 321.15 315.16 -1.87% 1.0190x
string_build3 328.16 319.41 -2.66% 1.0274x
string_build_large1 356.84 357.06 +0.06% 0.9994x
string_build_large2 355.68 352.29 -0.96% 1.0096x
int_to_string 314.67 308.20 -2.05% 1.0210x
float_to_string 1832.03 1634.05 -10.81% 1.1212x
string_to_int 180.29 177.44 -1.58% 1.0161x
string_to_float 153.74 155.75 +1.31% 0.9871x
v8-richards 80.12 106.72 +33.21% 0.7507x
v8-deltablue 146.59 192.93 +31.61% 0.7598x
v8-crypto 2219.20 2341.06 +5.49% 0.9479x
v8-raytrace 969.66 1141.79 +17.75% 0.8493x
v8-earley-boyer 2729.55 FAILED
v8-regexp 5452.16 5514.85 +1.15% 0.9886x
v8-splay 3484.48 3861.14 +10.81% 0.9024x
v8-navier-stokes 1817.89 1851.83 +1.87% 0.9817x

**执行能力回归:**固定版 v8-earley-boyer 旧配置 5/5 通过,中位数 2729.55 ms;新配置 5/5 失败,错误均为 InternalError: stack overflow。错误栈包含 loop2 / sc_loop1_98 / deriv_trees。这是失败,不是更快或更慢;尚未区分旧桥递归、原生栈与显式帧预算等具体根因。本结果也不能替代原始自适应 Earley-Boyer 的完整验收。

3. 硬件指令证据:额外执行工作已确认

同一批二进制上另行运行 perf stat -e cycles:u,instructions:u,branches:u,branch-misses:u,四项各交错 3 轮,共 24 个进程,全部成功且精确输出匹配、stderr 为空。每个事件运行比例均为 100%,无计数器 multiplexing。下表每个计数独立取中位数。

这是用户态机器指令/CPU cycles,不是 JS 字节码数,也不是 wall time。它证明回退伴随实际执行工作增加;不提供各原因的独立耗时占比。

工作量 旧机器指令数 新机器指令数 指令变化 cycles 变化 branches 变化
empty_loop 7,507,108,288 13,208,648,130 +75.95% +43.87% +104.36%
func_call 9,810,317,071 13,877,891,640 +41.46% +58.47% +57.62%
int_arith 7,479,269,636 12,503,995,198 +67.18% +41.05% +106.81%
prop_read 9,306,545,042 14,109,778,372 +51.61% +49.51% +76.42%
展开所有硬件计数中位数
工作量 配置 cycles:u instructions:u branches:u branch-misses:u
empty_loop legacy 2,943,654,685 7,507,108,288 1,317,779,146 313,815
empty_loop stack 4,235,107,603 13,208,648,130 2,692,982,925 320,898
func_call legacy 3,801,886,167 9,810,317,071 1,586,903,453 716,852
func_call stack 6,024,921,179 13,877,891,640 2,501,325,501 993,732
int_arith legacy 3,236,806,409 7,479,269,636 1,233,668,095 327,840
int_arith stack 4,565,473,635 12,503,995,198 2,551,290,229 335,347
prop_read legacy 3,496,651,630 9,306,545,042 1,494,734,947 1,163,157
prop_read stack 5,227,683,331 14,109,778,372 2,636,968,628 4,551,586

branches 不是仅指条件检查,也包含 PMU 统计的其他分支。空循环总分支增加 104.36%,但 branch misses 仅从 313,815 增至 320,898(+2.26%);不能把其回退解释成分支预测失误暴增。

4. Profile:真实运行的热点

另外使用 perf record -e cycles:u -F 997,分别采样新旧配置的 empty_loop、func_call、prop_read,共 6 次。输出全部匹配,lost samples 均为 0。perf report --stdio --no-children自身采样占比如下;它们是整个进程内的周期采样分布,不是各项导致的回退百分比。单次短采样用于定位热点,不用于精确拆分成本。

新配置工作量 符号 自身采样占比
empty_loop run::run 44.99%
empty_loop stack::copy_value 15.61%
empty_loop SlotStore::pop 11.54%
empty_loop SlotStore::push 11.14%
empty_loop SlotStore::replace_local 3.92%
empty_loop SlotStore::peek 3.18%
empty_loop SlotStore::local 2.98%
func_call driver::enter_call 6.38%
func_call BytecodeCallRequest::prepare 5.37%
func_call driver::push_frame 5.07%
func_call driver::run_frames 4.45%
func_call prepare_bytecode_frame 2.10%
prop_read run::run 29.30%
prop_read driver::run_frames 12.17%
prop_read prepare_ordinary_read 5.02%
prop_read ordinary_storage::locate 4.42%

空循环中 copy_value/pop/push 合计 38.29%。旧配置的主热点是 execute_inner 36.99%、execute_numeric_instruction 28.21%、read_frame_binding 22.36%。这不表示旧配置没有取值/栈操作成本,而是新配置的这些未内联 helper 已成为独立大热点。

普通调用旧配置也有 prepare_bytecode_host 5.22%、push_active_frame 3.88% 等准备成本;不能把新配置全部构帧成本说成新增分配。新配置中 Vec::extend_trusted 两个独立单态化符号分别占 2.18%、1.72%。

5. 源码与实际 release 汇编相互印证

A. 栈检查的粒度与热循环不匹配,重复调用实际保留。

这不只是源码形式。原 benchmark release 二进制中真实存在:

4c8a47: call SlotStore::peek  ; pop 再次调用 peek
4c8b38: cmp  (%rdx),%rax     ; owner 身份检查
4c8bba: cmp  0x8(%rdx),%rax  ; window ID 检查
4c8bc8: cmp  0x18(%rdx),%rax ; arena 末端检查
4c8bdb: sub  %rcx,%rdi       ; 栈深计算/随后检查
4c8c38: cmp  %rax,%rdi       ; 槽索引边界检查

run 汇编保留对 peek/pop/local/copy_value 的直接 CALL;不能再假设编译器已经消除了这一层。

B. 原语复制仍进入处理全部 Value 的通用未内联函数。

copy_value 实现 同时处理整数、浮点以及 Object/Symbol 的可失败引用操作。汇编入口保存 5 个寄存器,0x4c5dc8 预留 0x80 字节原生栈,0x4c5de4 通过间接跳转分派 Value 类型。整数路径同样进入此函数。其 15.61% 采样占比说明这是真实热点;不表示整数复制发生堆分配

C. 显式帧迁移没有同时合并构帧存储流程。

BytecodeCallRequest::prepare 先调用共享 prepare_bytecode_frame,再创建 Box<FrameCold> 和捕获复用标记,最后由 SlotStore 安装帧窗口 消费准备好的参数/局部容器。共享准备入口仍初始化参数和局部 Vec。

汇编 0x63701b 确实调用 prepare_bytecode_frame0x6371260x6371de 等处确实调用 memcpy。这些复制包含帧/状态搬移,不能全部称为 JS 实参复制。源码、机器码和调用热点共同确认该管理流程存在并消耗 CPU;尚未测出总分配次数或各步骤独立造成的耗时差值。

6. 分析、问题归属与后续验收

  • **当前实现问题:**新核心对每个槽操作分别做通用验证、普通值操作仍通过未内联通用函数、调用保留准备容器再安装显式帧。这些是已观察到的执行成本和热点。容器安全接口没有充分利用同一热循环内连续操作的既有事实;显式帧降低递归承载需求,不等于降低每调用固定成本。
  • **验收盲区:**已有 S01–S04 记录强调语义、所有权、小栈、路径覆盖及成本计数,没有本轮同源吞吐比较。这次结果补出了阶段验收未发现的性能回归。阶段验收通过不能解释为这些新发现已通过验收。
  • **归属:**这些应作为 S04 当前迁移配置的性能/执行能力回归追踪。修复安排在 S08/S09 不改变问题归属;修回旧水平不能记成额外优化收益。同提交比较不确定具体哪个 S01–S04 提交引入了各项回退。
  • **S05–S07:**补齐属性/内部回调/入口覆盖,并定位 Earley-Boyer 失败;不能据计划断言后续迁移自动消除回退。
  • **S08:**针对循环/数值回归,分别验证融合、槽操作/检查成本与 PC 发布改动。
  • **S09:**针对调用回归,分别验证帧布局、参数/局部初始化、容器搬移、分配和容量复用。
  • **S10:**完整同源复测和默认预算 Earley-Boyer 验收。应明确“已知回归已修复,或有逐项量化并明确接受的剩余退化”的性能门槛,而不只是功能测试通过后切默认。

**纠正尚无证据的归因:**PC 逐指令更新在源码中存在,但本次没有隔离其成本,不能列为已证实的主要回退原因。Earley-Boyer 只确认失败,未确认根因。上述 Profile 百分比不是各原因对总回退的贡献;内联/融合/存储变更能挽回多少,需要保持语义的隔离 A/B 实验。

7. 原始证据保留位置

本评论已内嵌完整 benchmark 表、全部硬件计数中位数、热点与关键汇编,便于离开当前会话阅读。原始文件目前保存在 PocketLab 当前工作区的 target/s04-benchmark/没有作为 GitHub 附件上传或提交到仓库

  • fixed-58/{metadata.json,results.json,samples.jsonl,raw/}:580 个样本及全部 stdout/stderr。
  • {legacy,stack}/release/qjs.build.json:完整构建命令、编译器及二进制哈希。
  • evidence/{metadata.json,counters.json,collect.py,collect.log}:硬件实验身份、计数、复现脚本及输出校验记录。
  • evidence/*.stat:24 份原始硬件计数;*.data / *.report.txt:6 份 perf 采样及报告。
  • evidence/{slot-assembly.txt,run-assembly.txt,call-prepare-assembly.txt,copy-value-annotate.txt}:实际 release 汇编与采样注释。

验证:24 个计数进程、6 次采样输出全部匹配;6 份 Profile lost samples 均为 0;二进制 SHA-256 与测量收据一致。

Share prepared property reads across object and primitive receivers, resume object key conversion, and normalize bound callbacks.

Own pending synchronous call requests outside the resident dispatcher, expose bridge profiling, and add regression tests and S05 progress documentation.
@Eric-Song-Nop

Copy link
Copy Markdown
Author

S05 当前检查点复测:基础回归仍在,属性读取新增开销

测量日期:2026-09-13;本次 PR 提交固定为 069249670bcb890994828d6da38bcfa92b6ebc0e。接续 S04 测量评论

**阶段状态更正:**开始和复测结束时核对的 PR HEAD 均为上述提交,但该提交的 迁移账本提交计划 明确写着 S05 实施中、尚未验收。因此本评论是最新 S05 检查点结果,不能称为 S05 完成后的最终验收。

**主要结果:**完整 50 项固定 microbench 中,当前新核心相对本轮重新运行的 S04 新核心,等权几何平均耗时变化 +1.05%;相对当前同提交旧 VM 为 +11.95%。约 1% 的跨提交整体差异不宣称统计显著,当前新旧 VM 的明显差距仍在。固定 Earley-Boyer 在 S04/当前两版新核心均 5/5 次栈溢出,当前旧 VM 5/5 次通过。

1. 方法与比较口径

  • 三配置:s04_stack = S04 4fd9900 + stack-vm;s05_legacy = 当前 0692496 默认旧 VM;s05_stack = 当前 0692496 + stack-vm。
  • S04 二进制在本轮重新执行并与另外两套交错,不是把上次 wall time 拿来跨时段比较。 未重测 S04 默认旧 VM,因此不报告旧 VM 从 S04 到当前的独立时序提升。
  • 同一 PocketLab eric-83am,Ryzen 7 7840HS、16 逻辑 CPU、Linux 6.18.44-1-lts;rustc 1.94.1、LLVM 21.1.8;普通 release、关闭 profiling。构建串行完成后才计时,benchmark 与 perf 分开执行。
  • CPU 2;动态频率/SMT 未隔离,桌面后台服务仍在。启动计时和抽查时未观察到其他构建/测试竞争,不称为完全隔离环境。
  • 与上次相同 manifest、58 个工作量哈希全部匹配。每配置每项交错 5 轮,取整进程 wall-clock 中位数,含启动、编译、执行、输出、清理;不是纯 VM 时间、CPU 时间或自适应 V8 分数。
  • 870 个 benchmark 样本:860 成功、10 失败,失败全部是两版新核心的 Earley-Boyer。失败不计速度比;不生成完整 58 项或 V8 总分。
  • 硬件计数额外覆盖 6 项 × 3 配置 × 3 轮 = 54 次;热点采样覆盖 5 项 × 3 配置 = 15 次。全部输出匹配;所有硬件事件运行比例 100%;15 份采样均无丢失样本。

2. 完整 benchmark

正数表示当前新核心更慢;50 项几何平均是等权用例汇总,不代表任意应用。小幅单项差异不宣称显著。

展开全部 58 项(ms,5 轮中位数)
项目 S04 新核心 当前旧 VM 当前新核心 当前新 / S04 新耗时变化 当前新 / 当前旧耗时变化
empty_loop 939.16 647.23 945.02 +0.62% +46.01%
empty_down_loop 732.06 489.95 707.98 -3.29% +44.50%
prop_read 1134.63 805.68 1204.82 +6.19% +49.54%
prop_write 334.28 310.20 333.43 -0.25% +7.49%
prop_update 441.80 448.31 461.00 +4.35% +2.83%
prop_create 382.37 380.29 381.34 -0.27% +0.27%
prop_clone 325.74 324.80 326.57 +0.26% +0.55%
prop_delete 398.10 404.13 397.64 -0.12% -1.61%
array_read 512.94 526.93 521.25 +1.62% -1.08%
array_write 479.97 472.60 482.54 +0.54% +2.10%
array_update 480.68 481.84 475.18 -1.14% -1.38%
array_prop_create 593.92 593.38 588.11 -0.98% -0.89%
array_slice 374.48 397.77 402.32 +7.43% +1.14%
array_length_read 1030.21 753.08 1082.08 +5.03% +43.69%
array_length_decr 560.94 585.29 564.70 +0.67% -3.52%
array_push 611.02 615.94 604.81 -1.02% -1.81%
array_pop 569.20 590.41 578.40 +1.62% -2.04%
typed_array_read 377.87 341.60 343.27 -9.16% +0.49%
typed_array_write 304.01 287.98 305.04 +0.34% +5.92%
arguments_read 443.01 358.61 426.79 -3.66% +19.01%
arguments_strict_read 415.89 343.60 400.79 -3.63% +16.64%
global_read 743.71 394.16 739.63 -0.55% +87.65%
global_write 759.94 497.00 769.44 +1.25% +54.81%
local_destruct 140.85 142.46 142.44 +1.13% -0.01%
global_func_call 1404.89 847.06 1347.26 -4.10% +59.05%
func_call 1279.99 815.11 1213.32 -5.21% +48.85%
func_closure_call 1514.36 893.11 1447.95 -4.39% +62.12%
int_arith 998.55 695.89 998.08 -0.05% +43.43%
float_arith 1095.07 749.95 1119.12 +2.20% +49.23%
bigint64_arith 460.38 459.15 461.01 +0.14% +0.40%
map_set_string 39.57 38.91 39.39 -0.46% +1.23%
map_set_int 52.71 51.68 51.59 -2.13% -0.19%
map_delete 59.79 59.94 59.75 -0.07% -0.31%
weak_map_set 352.81 343.38 345.19 -2.16% +0.53%
array_for 486.94 496.79 498.43 +2.36% +0.33%
array_for_in 832.39 869.96 850.59 +2.19% -2.23%
array_for_of 572.90 583.62 580.94 +1.40% -0.46%
math_min 802.30 794.04 1318.15 +64.30% +66.00%
regexp_ascii 425.57 424.36 411.92 -3.21% -2.93%
regexp_utf16 429.26 427.73 418.38 -2.54% -2.19%
regexp_replace 787.81 799.75 776.25 -1.47% -2.94%
string_length 651.70 737.31 880.47 +35.10% +19.42%
string_build1 315.57 316.36 312.04 -1.12% -1.36%
string_build3 324.19 323.40 326.02 +0.57% +0.81%
string_build_large1 353.87 354.20 354.62 +0.21% +0.12%
string_build_large2 353.74 356.46 355.10 +0.38% -0.38%
int_to_string 309.82 312.61 316.11 +2.03% +1.12%
float_to_string 1785.44 1577.08 1608.27 -9.92% +1.98%
string_to_int 178.00 179.38 175.20 -1.57% -2.33%
string_to_float 160.43 158.10 152.14 -5.16% -3.77%
v8-richards 108.10 81.45 108.87 +0.72% +33.67%
v8-deltablue 192.14 148.03 195.54 +1.77% +32.10%
v8-crypto 2374.70 2250.29 2396.04 +0.90% +6.48%
v8-raytrace 1151.65 964.05 1143.87 -0.68% +18.65%
v8-earley-boyer FAILED 2672.23 FAILED
v8-regexp 5503.46 5494.92 5563.67 +1.09% +1.25%
v8-splay 3857.20 3455.85 3825.44 -0.82% +10.69%
v8-navier-stokes 1877.67 1850.50 1862.33 -0.82% +0.64%

关键变化:普通调用相对 S04 wall time -5.21%,闭包调用 -4.39%,TypedArray 读取 -9.16%;属性读取 +6.19%。空循环 +0.62%、整数运算 -0.05%,基础回归没有消失。下节硬件计数用于核对执行工作量的变化,不能只凭 wall time 归因。

**Earley-Boyer:**当前旧 VM 中位数 2672.23 ms;两版新核心全部失败,默认预算未改。当前错误 InternalError: stack overflow,栈顶包含 sc_list / loop3。尚未定位具体 native/VM 预算或桥接根因;没有用调大栈、skip 或缩小工作量掩盖。

3. 硬件计数:哪些执行工作确实改变了

perf stat -e cycles:u,instructions:u,branches:u,branch-misses:u;每项每配置三轮交错,各计数独立取中位数。都是用户态机器指令与 CPU cycles,不是字节码数或 wall time。

项目 S04 新指令数 当前旧指令数 当前新指令数 当前新/S04 新指令变化 当前新/当前旧指令变化 当前新/S04 新 cycles 变化
empty_loop 13,208,625,123 7,507,076,201 13,208,397,448 -0.00% +75.95% +1.42%
func_call 13,877,887,553 9,810,294,765 13,786,467,647 -0.66% +40.53% -5.57%
int_arith 12,503,984,892 7,479,302,662 12,503,815,172 -0.00% +67.18% +0.55%
prop_read 14,109,771,044 9,672,044,955 15,855,857,510 +12.38% +63.93% +6.64%
array_read 5,777,725,141 5,967,810,718 5,970,188,589 +3.33% +0.04% +1.29%
typed_array_read 4,142,156,366 3,981,401,090 3,982,571,147 -3.85% +0.03% -6.91%
全部硬件计数中位数
项目 配置 cycles:u instructions:u branches:u branch-misses:u
empty_loop s04_stack 4,291,314,475 13,208,625,123 2,692,977,850 320,834
empty_loop s05_legacy 3,034,073,301 7,507,076,201 1,317,771,514 320,259
empty_loop s05_stack 4,352,216,393 13,208,397,448 2,692,930,119 320,929
func_call s04_stack 5,781,840,924 13,877,887,553 2,501,314,428 1,005,844
func_call s05_legacy 3,707,647,862 9,810,294,765 1,586,900,543 771,128
func_call s05_stack 5,459,758,422 13,786,467,647 2,488,471,053 851,192
int_arith s04_stack 4,516,790,870 12,503,984,892 2,551,289,359 346,977
int_arith s05_legacy 3,188,899,393 7,479,302,662 1,233,674,481 350,554
int_arith s05_stack 4,541,693,465 12,503,815,172 2,551,262,122 343,772
prop_read s04_stack 5,200,891,457 14,109,771,044 2,636,966,956 1,176,782
prop_read s05_legacy 3,682,524,336 9,672,044,955 1,531,959,902 1,170,401
prop_read s05_stack 5,546,044,245 15,855,857,510 2,927,972,778 1,170,543
array_read s04_stack 2,346,810,964 5,777,725,141 913,684,640 579,659
array_read s05_legacy 2,391,091,980 5,967,810,718 941,895,673 581,416
array_read s05_stack 2,377,078,509 5,970,188,589 941,871,315 579,984
typed_array_read s04_stack 1,706,980,515 4,142,156,366 704,160,054 458,356
typed_array_read s05_legacy 1,595,861,251 3,981,401,090 671,198,388 457,617
typed_array_read s05_stack 1,589,027,209 3,982,571,147 671,174,081 460,162

4. 新一轮 Profile 与机器码

perf record -e cycles:u -F 997,各单独一次采样;perf report --stdio --no-children。以下均为进程内部自身周期采样占比,不是对总回退的贡献比例。单次短采样用于识别热点,不用于精确比较几个百分点的占比变化。

  • **空循环:**当前 copy_value 16.27%、push 11.74%、pop 11.08%,合计 39.09%run 44.20%。热点仍集中在原有槽/复制路径。
  • 普通调用:BytecodeCallRequest::prepare 4.70%、enter_call 4.21%、push_frame 3.30%、共享 prepare_bytecode_frame 2.96%,run_frames_with_state 5.86%。调用准备和安装成本仍在。
  • 属性读取:property_driver::read 5.14%、finish_read 3.53%、prepare_ordinary_read 6.48%、run_frames_with_state 5.06%。这次引入/重组的属性读取路径已经成为实测热点。
  • **数组读取的重要覆盖边界:**当前新配置采样中,旧 VmActivation::execute_inner 16.69%、read_frame_binding 15.38%、旧 execute_numeric_instruction 6.47%、旧 execute_hot_instruction 6.29%,还包含旧 host_bridge 属性读取。
  • **TypedArray 读取也仍执行旧路径:**当前新配置的 execute_inner 12.64%、旧 numeric dispatch 8.49%、旧 hot dispatch 4.73%,并出现 RuntimeVmHost::get_property/get_property_with_key。所以“当前新配置的数组/TypedArray 性能接近当前旧 VM”不能作为新核心完整覆盖或新核心专属优化的证据。没有统计全样本 owned/legacy 指令比例。

当前 release 实际汇编:

647347: call 647430 <SlotStore::peek>  ; pop 内部仍再调用 peek

SlotStore::pop/check_current/copy_value 与共享构帧准备相对 S04 源码未改。新二进制中 pop/peek/push/copy_value 仍各有独立符号,run 仍直接 CALL 槽 helper。copy_value 位于 0x644500,大小 885 字节;pop 位于 0x647330。不能称这些开销已被编译器消除或本轮修复。

15 份采样的前 6 个符号(含本轮 S04 对照)

array_read-s04_stack.report.txt

16.92%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
13.93%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
9.95%  qjs      qjs                   [.] quickjs_oxide::engine::vm::dispatch::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_numeric_instruction
8.79%  qjs      qjs                   [.] <quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost as quickjs_oxide::engine::vm::protocol::VmHost>::get_property
8.13%  qjs      qjs                   [.] quickjs_oxide::engine::object::ordinary::<impl quickjs_oxide::engine::api::runtime::Runtime>::prepare_ordinary_read
7.97%  qjs      qjs                   [.] quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost::get_property_with_key

array_read-s05_legacy.report.txt

17.34%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
13.63%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
9.82%  qjs      qjs                   [.] quickjs_oxide::engine::vm::dispatch::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_numeric_instruction
8.28%  qjs      qjs                   [.] quickjs_oxide::engine::object::internal_methods::<impl quickjs_oxide::engine::api::runtime::Runtime>::internal_get_or_missing
8.07%  qjs      qjs                   [.] quickjs_oxide::engine::object::ordinary::<impl quickjs_oxide::engine::api::runtime::Runtime>::prepare_ordinary_read
7.90%  qjs      qjs                   [.] quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost::get_property_with_key

array_read-s05_stack.report.txt

16.69%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
15.38%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
9.89%  qjs      qjs                   [.] quickjs_oxide::engine::object::internal_methods::<impl quickjs_oxide::engine::api::runtime::Runtime>::internal_get_or_missing
7.93%  qjs      qjs                   [.] quickjs_oxide::engine::vm::numeric::add_primitives
7.91%  qjs      qjs                   [.] quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost::get_property_with_key
7.63%  qjs      qjs                   [.] quickjs_oxide::engine::object::ordinary::<impl quickjs_oxide::engine::api::runtime::Runtime>::prepare_ordinary_read

empty_loop-s04_stack.report.txt

43.98%  qjs      qjs                   [.] quickjs_oxide::engine::vm::run::run
15.83%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::copy_value
14.09%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::push
12.15%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::pop
5.21%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::replace_local
2.71%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::local

empty_loop-s05_legacy.report.txt

35.31%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
29.08%  qjs      qjs                   [.] quickjs_oxide::engine::vm::dispatch::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_numeric_instruction
23.74%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
2.82%  qjs      qjs                   [.] quickjs_oxide::engine::object::storage::<impl quickjs_oxide::engine::api::runtime::Runtime>::value_to_boolean
2.19%  qjs      qjs                   [.] quickjs_oxide::engine::vm::numeric::to_numeric_primitive
1.25%  qjs      qjs                   [.] <quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost as quickjs_oxide::engine::vm::protocol::VmHost>::put_local

empty_loop-s05_stack.report.txt

44.20%  qjs      qjs                   [.] quickjs_oxide::engine::vm::run::run
16.27%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::copy_value
11.74%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::push
11.08%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::pop
5.92%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::local
5.69%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::replace_local

func_call-s04_stack.report.txt

15.35%  qjs      qjs                   [.] quickjs_oxide::engine::vm::run::run
7.48%  qjs      libc.so.6             [.] 0x000000000018f413
6.15%  qjs      qjs                   [.] quickjs_oxide::engine::vm::driver::enter_call
4.95%  qjs      qjs                   [.] quickjs_oxide::engine::vm::driver::run_frames
4.08%  qjs      qjs                   [.] quickjs_oxide::engine::vm::driver::push_frame
3.84%  qjs      qjs                   [.] quickjs_oxide::engine::vm::call::request::BytecodeCallRequest::prepare

func_call-s05_legacy.report.txt

12.80%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
11.60%  qjs      qjs                   [.] quickjs_oxide::engine::vm::host_bridge::<impl quickjs_oxide::engine::api::runtime::Runtime>::prepare_bytecode_host
9.03%  qjs      qjs                   [.] quickjs_oxide::engine::heap::gc::<impl quickjs_oxide::engine::heap::Heap>::release_raw_no_drain
7.32%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
5.11%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frames::<impl quickjs_oxide::engine::api::runtime::Runtime>::push_active_frame
4.02%  qjs      qjs                   [.] quickjs_oxide::engine::vm::call::<impl quickjs_oxide::engine::api::runtime::Runtime>::bytecode_for_callable

func_call-s05_stack.report.txt

14.37%  qjs      qjs                   [.] quickjs_oxide::engine::vm::run::run
8.09%  qjs      libc.so.6             [.] 0x000000000018f413
5.86%  qjs      qjs                   [.] quickjs_oxide::engine::vm::driver::run_frames_with_state
4.70%  qjs      qjs                   [.] quickjs_oxide::engine::vm::call::request::BytecodeCallRequest::prepare
4.54%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::pop
4.21%  qjs      qjs                   [.] quickjs_oxide::engine::vm::driver::enter_call

prop_read-s04_stack.report.txt

28.49%  qjs      qjs                   [.] quickjs_oxide::engine::vm::run::run
9.83%  qjs      qjs                   [.] quickjs_oxide::engine::vm::driver::run_frames
9.03%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::copy_value
7.74%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::pop
6.49%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::push
5.91%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::peek

prop_read-s05_legacy.report.txt

16.90%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
12.72%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
9.93%  qjs      qjs                   [.] quickjs_oxide::engine::vm::dispatch::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_numeric_instruction
8.07%  qjs      qjs                   [.] quickjs_oxide::engine::object::ordinary::<impl quickjs_oxide::engine::api::runtime::Runtime>::prepare_ordinary_read
7.88%  qjs      qjs                   [.] quickjs_oxide::engine::object::internal_methods::<impl quickjs_oxide::engine::api::runtime::Runtime>::internal_get_or_missing
6.43%  qjs      qjs                   [.] quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost::get_property_with_key

prop_read-s05_stack.report.txt

27.13%  qjs      qjs                   [.] quickjs_oxide::engine::vm::run::run
9.76%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::SlotStore::pop
7.09%  qjs      qjs                   [.] quickjs_oxide::engine::vm::stack::copy_value
6.48%  qjs      qjs                   [.] quickjs_oxide::engine::object::ordinary::<impl quickjs_oxide::engine::api::runtime::Runtime>::prepare_ordinary_read
5.14%  qjs      qjs                   [.] quickjs_oxide::engine::vm::property_driver::read
5.06%  qjs      qjs                   [.] quickjs_oxide::engine::vm::driver::run_frames_with_state

typed_array_read-s04_stack.report.txt

13.11%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
11.88%  qjs      qjs                   [.] quickjs_oxide::engine::object::internal_methods::<impl quickjs_oxide::engine::api::runtime::Runtime>::internal_get_or_missing
9.35%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
8.34%  qjs      qjs                   [.] quickjs_oxide::engine::builtins::buffer_access::<impl quickjs_oxide::engine::api::runtime::Runtime>::snapshot_buffer_access_raw
5.80%  qjs      qjs                   [.] quickjs_oxide::engine::heap::gc::<impl quickjs_oxide::engine::heap::Heap>::release_raw_no_drain
5.56%  qjs      qjs                   [.] quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost::get_property_with_key

typed_array_read-s05_legacy.report.txt

14.42%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
11.78%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
8.16%  qjs      qjs                   [.] quickjs_oxide::engine::vm::dispatch::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_numeric_instruction
6.65%  qjs      qjs                   [.] quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost::get_property_with_key
6.04%  qjs      qjs                   [.] <quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost as quickjs_oxide::engine::vm::protocol::VmHost>::get_property
6.04%  qjs      qjs                   [.] quickjs_oxide::engine::builtins::array_buffer::typed_array::<impl quickjs_oxide::engine::api::runtime::Runtime>::typed_array_read_index

typed_array_read-s05_stack.report.txt

12.64%  qjs      qjs                   [.] quickjs_oxide::engine::vm::frame_execution::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_inner
8.52%  qjs      qjs                   [.] quickjs_oxide::engine::vm::bindings::read_frame_binding
8.49%  qjs      qjs                   [.] quickjs_oxide::engine::vm::dispatch::<impl quickjs_oxide::engine::vm::activation::VmActivation>::execute_numeric_instruction
6.51%  qjs      qjs                   [.] <quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost as quickjs_oxide::engine::vm::protocol::VmHost>::get_property
6.19%  qjs      qjs                   [.] quickjs_oxide::engine::vm::host_bridge::RuntimeVmHost::get_property_with_key
6.16%  qjs      qjs                   [.] quickjs_oxide::engine::heap::gc::<impl quickjs_oxide::engine::heap::Heap>::release_raw_no_drain

5. 更新后的分析:已证实、未证实与修复责任

  1. 原语栈回归没有修复。 空循环/整数指令量相对 S04 都只变化约 -0.002%/-0.001%,当前相对旧 VM 仍多执行约 76%/67% 指令。源码未改、独立 CALL 保留、热点仍在,三者一致。
  2. 普通调用有可重复的局部改善,但不是构帧开销已解决。 指令量相对 S04 仅 -0.66%,cycles -5.57%,wall -5.21%;当前与旧 VM 仍有大差距。不能把约 5% 改善全归为少分配或某个未做隔离实验的布局变化。
  3. 属性读取新增回退已由指令量确认。 相对 S04 多执行 12.38% 机器指令,cycles +6.64%,wall +6.19%。property_driver::readfinish_readprepare_value_property_read 是当前代码路径:创建/保留键与 receiver、取得帧状态、进入共享读取准备,再消费槽/安排回复。上述函数在实际采样中出现。具体哪一处 clone、验证或调度贡献多少,仍需隔离 A/B;不能仅凭函数自身百分比计算总回退贡献。
  4. 数组/TypedArray 的变化必须连同旧路径覆盖一起解读。 TypedArray 读取指令相对 S04 -3.85%,cycles -6.91%;但当前新配置与当前旧 VM 指令量仅相差约 0.03%,且采样直接看到旧执行器。当前提交修改了新旧共用属性读取内核,不能把这项改善归为新核心已消除基础开销。
  5. Earley-Boyer 能力回归仍未解决。 失败稳定复现,根因未定位;本次成功的其他 workload 不能证明它的调用链已正确迁移。
  6. 问题仍应作为当前迁移实现的回归追踪。 后续 S08/S09 的计划不是延期的充分理由。当前应优先定位栈溢出,针对槽 helper/通用复制做保持语义的隔离实验,针对新增属性读取开销建立回归用例,并跟踪调用准备。修回旧水平与进一步优化分别记账;不能按 S05 阶段标签宣称这些问题已关闭。

**继续保留的证据边界:**没有确认 PC 更新的独立成本,没有测量全部分配/retain/release,没有证明任何单一改动能消除全部回退。本轮没有修改生产代码、提高预算、改断言或增加 skip。

6. 复现与证据位置

# 当前提交分别构建,关闭 profiling,目录独立
cargo build --locked --release -p quickjs-oxide-cli --no-default-features --jobs 2 --target-dir target/s05-benchmark/legacy
cargo build --locked --release -p quickjs-oxide-cli --no-default-features --features stack-vm --jobs 2 --target-dir target/s05-benchmark/stack
python3 scripts/benchmark/fixed.py --manifest docs/reports/data-structure-fixed-final.json --engine s04_stack=target/s04-benchmark/stack/release/qjs --engine s05_legacy=target/s05-benchmark/legacy/release/qjs --engine s05_stack=target/s05-benchmark/stack/release/qjs --repeat 5 --cpu 2 --timeout 60 --output target/s05-benchmark/fixed-58

构建时两套新二进制均设置 QUICKJS_OXIDE_BUILD_COMMIT=069249670bcb890994828d6da38bcfa92b6ebc0e。复跑须另选新输出目录并准备原 manifest 引用的外部工作量。二进制 SHA-256:

s04_stack 706cdbe649824225ca29b98945294f796d4d6ba65ffacdf970b8181e52af8d2d
s05_legacy 40c632ba39a8a0569ab39f6205f8a5009854613d743b5e4188d0282da33dff75
s05_stack 95057a05a91ffe4e9f92d6510ea0c7ef1d13d6907f7138d4e2fb814878849fb2

本评论内嵌全部 benchmark 和硬件计数中位数、热点及分析。原始数据保存在 PocketLab 本工作区 target/s05-benchmark/尚未作为 GitHub 附件上传或提交到仓库

  • fixed-58/{metadata.json,results.json,samples.jsonl,raw/}:870 个原始样本与输出/错误。
  • {legacy,stack}/release/qjs.build.json:构建命令、工具链、源码/二进制身份。
  • evidence/{metadata.json,counters.json,collect.py,collect.log}*.stat:54 份计数与校验;TypedArray 三份补充采样也记录于 collect.log。
  • evidence/*.data / *.report.txt:15 份 CPU 采样;*-assembly.txtsymbols.txt:当前 release 汇编。

最终校验:870 个样本完整,失败类型/数量已核对;54 次 perf stat 输出匹配;15 次采样输出匹配且 lost samples 为 0;三套二进制哈希与收据一致。

7. S01–S10 计划、双执行器与回归处理的澄清

“性能退化”和“执行路径回落”是两件事:前者指同一工作量变慢/资源成本增加,后者指新核心尚未支持的路径交给旧执行器。路径回落不一定更慢,也不能当作新核心已实现该能力。

阶段 实际交付
S01 整理编译器阶段、线性栈 IR、作用域与名字解析,建立诊断入口
S02 统一指令/栈/控制流契约、验证与代码发布,建立可执行函数和帧布局边界
S03 建立 owned FrameStore/SlotStore 与原语执行循环,明确值的 move/copy/clear
S04 普通调用/构造改显式帧,接通绑定、转换恢复、异常/finally、同步迭代清理和 host 重入骨架
S05 迁移属性/Proxy、Array、String/RegExp、buffer 与其他同步内置的内部 JS 回调
S06 迁移 generator、async/Promise、异步迭代的挂起与恢复
S07 接通模块、宿主、CLI/Web、二进制等全部既有入口,审核新核心覆盖
S08 有限指令融合、局部 pc/sp、精确观察点状态发布,并逐项 A/B
S09 调用存储、参数、帧布局、容量复用和栈顶缓存/指令表示等隔离实验
S10 完整功能/性能/覆盖验收后切换默认,删除旧执行器和迁移桥,再在删除后的代码上复验

当前确实有新旧两套执行核心共存,不是为旧版 JavaScript 保留向后兼容 VM。 Cargo 的 stack-vm 明确是非默认临时迁移配置;新路径遇到未迁移操作会交接给旧执行器。共用对象/内置/编译模块不等于始终只执行一个核心。最终目标是单一新核心;S07 应完成入口覆盖,S10 删除旧路径。对外既有 API/二进制语义兼容与内部旧 VM 存留是不同责任,前者不要求永久保留后者。

计划考虑了性能风险,但早期防线不足。 它安排了 S01 的诊断、S03/S04 的成本记录、S05 的 Earley-Boyer 覆盖筛查、S08/S09 的隔离 A/B 和无收益实验删除,以及 S10 的完整实测。它并未给每个 S03–S07 检查点建立明确的同源性能退化门槛,因此“门禁通过”和“性能退化仍存在”同时发生。它也没有授权对已知明显退化不作处理;优化阶段不是自动修复承诺。

优化与修复会重叠,应合并到同一问题账本。 例如槽操作重复检查和通用复制热点,既是当前回归,又属于 S08/S09 的优化范围;只需一个修复实现、一次独立 A/B 和对应验收,不应先做临时补丁再在 S08/S09 重写相同工作。性能回归、旧路径覆盖缺口、语言/资源错误分别登记,避免用“迁移完成”或“速度接近”混淆验收。

建议执行顺序:

  1. 现在建立回归检查点并定位失败。 固定本轮基线;分别记录 empty_loop/int_arith、func_call、prop_read 与 Earley-Boyer 的行为、路径覆盖和成本。先定位栈溢出;若由缺失的 S05 continuation 引起,就在对应迁移任务修,不添加另一个特殊 fallback 或调大预算。
  2. 现在修复不依赖后续语义迁移的基础成本。 对槽 helper/通用复制和新增属性读取路径逐因素 A/B,保持异常、所有权、GC、回调语义。已定位且可独立修的明显退化不因“S08 尚未开始”而推迟。
  3. 继续 S05–S07 时同步验收覆盖与性能。 每新增一类路径,证明该路径实际由新核心执行,再比较同源成本。对确实依赖完整挂起/调用表示的重构,写明依赖并归入 S08/S09,不为了提前达标制造重复实现。
  4. S08/S09 收口剩余问题并进一步提速。 提前完成的修复计入对应阶段,不重复做;区分恢复旧水平与新增收益。S10 在单核心覆盖、能力回归解决、明确性能门槛满足后切换并删除旧实现,删除后再测。

这比“所有问题一律等 S08/S09”或“为了现在修完而把整个后半段重做一遍”都更可审查。上述内容是基于本轮证据的计划调整建议;本次仅发布分析,没有修改实施计划文件或生产代码。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant