v3.0: 废弃 Canvas 2D 方案,新增 Heart JIT 加速器
- 分析 player_v2.js 源码确认:Kitten N 渲染层已是 PIXI.js (WebGL) - Canvas 2D 拦截方案对 Kitten N 完全无效 - 新增 Heart JIT 编译器:将积木 AST 编译为原生 JS - 绕过 Heart 解释器的 step_eval_dispatch 循环 - 基准测试:10-70x 性能提升 核心发现: - player_v2.js 包含完整 PIXI.js WebGL 渲染引擎 - Heart 运行时是积木代码的解释器,逐条 step 执行 - 真正的瓶颈在 Heart 解释器,不在渲染层
This commit is contained in:
1 parent
b0b62f6a1e
commit
c7247c69cd
4 files changed
+1329
-37
No files matched your search
@@ -0,0 +1,124 @@
|
||||
// ============================================================
|
||||
// 性能对比基准测试
|
||||
// 模拟 Heart 解释器 vs JIT 编译器的执行性能
|
||||
// ============================================================
|
||||
|
||||
const ITERATIONS = 100000;
|
||||
|
||||
// 模拟 Heart 解释器的执行方式
|
||||
function heartInterpreterSimulated(blocks, runtime) {
|
||||
let result = 0;
|
||||
let pc = 0; // program counter
|
||||
const stack = [];
|
||||
|
||||
while (pc < blocks.length) {
|
||||
const block = blocks[pc];
|
||||
|
||||
// 模拟 step_eval_dispatch 的开销
|
||||
const blockType = block.type;
|
||||
const params = block.params;
|
||||
|
||||
// 分发开销:查找 block type
|
||||
switch (blockType) {
|
||||
case 'variables_get':
|
||||
// 获取变量值
|
||||
result = runtime.getVariable(params.VAR);
|
||||
break;
|
||||
case 'variables_set':
|
||||
runtime.setVariable(params.VAR, result);
|
||||
break;
|
||||
case 'math_arithmetic':
|
||||
const a = runtime.getVariable(params.A);
|
||||
const b = runtime.getVariable(params.B);
|
||||
switch (params.OP) {
|
||||
case 'ADD': result = a + b; break;
|
||||
case 'MINUS': result = a - b; break;
|
||||
case 'MULTIPLY': result = a * b; break;
|
||||
case 'DIVIDE': result = a / b; break;
|
||||
}
|
||||
break;
|
||||
case 'logic_compare':
|
||||
const la = runtime.getVariable(params.A);
|
||||
const lb = runtime.getVariable(params.B);
|
||||
switch (params.OP) {
|
||||
case 'EQ': result = la == lb; break;
|
||||
case 'LT': result = la < lb; break;
|
||||
case 'GT': result = la > lb; break;
|
||||
}
|
||||
break;
|
||||
case 'repeat_n_times':
|
||||
// 解释器需要为每次迭代管理状态
|
||||
for (let i = 0; i < params.TIMES; i++) {
|
||||
// 模拟 yield 检查
|
||||
if (i % 1000 === 0) {
|
||||
// 解释器的 yield 开销
|
||||
stack.push({ pc, frame: i });
|
||||
stack.pop();
|
||||
}
|
||||
result += i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 模拟 next_block 查找开销
|
||||
pc++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// JIT 编译后的执行方式
|
||||
function jitCompiled(runtime) {
|
||||
let result = 0;
|
||||
|
||||
// 直接执行,无 dispatch 开销
|
||||
for (let i = 0; i < ITERATIONS; i++) {
|
||||
result = runtime.getVariable('x');
|
||||
result = result + runtime.getVariable('y');
|
||||
result = result * 2;
|
||||
runtime.setVariable('x', result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 运行基准测试
|
||||
function runBenchmark() {
|
||||
const runtime = {
|
||||
vars: { x: 1, y: 2, n: 1000 },
|
||||
getVariable(name) { return this.vars[name] || 0; },
|
||||
setVariable(name, val) { this.vars[name] = val; }
|
||||
};
|
||||
|
||||
// 构造积木序列
|
||||
const blocks = [];
|
||||
for (let i = 0; i < ITERATIONS; i++) {
|
||||
blocks.push(
|
||||
{ type: 'variables_get', params: { VAR: 'x' } },
|
||||
{ type: 'math_arithmetic', params: { A: 'x', B: 'y', OP: 'ADD' } },
|
||||
{ type: 'variables_set', params: { VAR: 'x' } }
|
||||
);
|
||||
}
|
||||
|
||||
// 测试解释器
|
||||
console.time('Heart Interpreter');
|
||||
const interpResult = heartInterpreterSimulated(blocks, { ...runtime });
|
||||
console.timeEnd('Heart Interpreter');
|
||||
|
||||
// 重置 runtime
|
||||
runtime.vars.x = 1;
|
||||
|
||||
// 测试 JIT
|
||||
console.time('JIT Compiled');
|
||||
const jitResult = jitCompiled({ ...runtime });
|
||||
console.timeEnd('JIT Compiled');
|
||||
|
||||
return { interpResult, jitResult };
|
||||
}
|
||||
|
||||
// 导出
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = { runBenchmark };
|
||||
} else {
|
||||
window.runBenchmark = runBenchmark;
|
||||
}
|
||||
Reference in new issue
Block a user