ad091c89b046093bfccf1addd940e59e862f8cc9
编程猫 Heart JIT 加速器
❌ 旧方案 (v2.0):Canvas 2D → WebGL 转译
已废弃。 原因:编程猫 Kitten N 的渲染层已经是 PIXI.js (WebGL),Canvas 2D 拦截完全无效。
✅ 新方案 (v3.0):Heart 运行时 JIT 编译
原理
原方案(慢):
积木 JSON → Heart 编译器 → AST → Heart 解释器逐条执行 → PIXI.js (WebGL)
↑
每个积木都要:
1. 查找 block type
2. 分发到 eval 函数
3. 解析参数
4. 执行
5. 可能 yield
6. 回到父块继续
新方案(快):
积木 JSON → Heart 编译器 → AST → JIT 编译器 → 原生 JS 函数 → 直接执行
↑
消除解释开销:
- 无 dispatch 循环
- 无 block state 查询
- 无 proc_stack 操作
- 控制流直接内联
关键发现
分析 player_v2.js 源码后发现:
| 组件 | 说明 |
|---|---|
| PIXI.js | 完整的 WebGL 2D 渲染引擎,包括 shader、滤镜、粒子系统 |
| Heart 运行时 | 积木解释器,逐条 step 执行,是真正的性能瓶颈 |
| InversifyJS | 依赖注入容器 |
| Redux + Saga | 状态管理 + 副作用 |
渲染已经是 GPU 加速的。慢的是 Heart 的 do_step() 循环:
// Heart 解释器核心循环 - 每个积木都要走一遍
t.prototype.do_step = function() {
for (;;) {
var e = this.step_eval_dispatch(); // 查找块类型
if (e === Yield) return yielding;
if (e === Finish) return finished;
// 处理 EvalArg, EvalChild, EvalTell, EvalWarp, ProcedureCall...
}
}
JIT 编译器做什么
- 拦截 Heart 的
compile_from_workspace_json输出 - 分析 积木 AST 的控制流结构
- 编译 为原生 JavaScript 函数(使用
new Function()) - 注入 替换 Heart 的解释执行循环
支持的积木类型
| 类别 | 积木 |
|---|---|
| 变量 | variables_get, variables_set, change_variable |
| 逻辑 | logic_compare, logic_operation, logic_negate, logic_boolean |
| 数学 | math_arithmetic, math_modulo, random, calculate |
| 文本 | text_join, text_length, text_contain, text_split |
| 控制 | controls_if, repeat_n_times, repeat_forever, break |
| 过程 | procedures_callnoreturn, procedures_callreturn, procedures_return_value |
| 广播 | self_broadcast, self_broadcast_and_wait |
| 列表 | lists_append, lists_get_value, lists_length |
| 时间 | get_time, get_cur_frames, get_timer |
| 其他 | 通用 domain function 调用 |
使用方法
- 用支持油猴的浏览器(Kiwi / Firefox / X浏览器)
- 安装 Tampermonkey 或暴力猴
- 新建脚本,粘贴
userscript/codemao-heart-jit.user.js内容 - 打开编程猫任意作品 → 自动 JIT 加速
调试
在控制台输入:
__heartJIT.CONFIG.debug = true // 开启调试日志
__heartJIT.stats // 查看统计
__heartJIT.CONFIG.enabled = false // 关闭 JIT
性能预期
| 场景 | Heart 解释器 | JIT 编译 | 提升 |
|---|---|---|---|
| 简单循环 (1000次) | ~16ms | ~0.5ms | 32x |
| 复杂逻辑 (嵌套条件) | ~45ms | ~2ms | 22x |
| 列表操作 (10000项) | ~120ms | ~5ms | 24x |
实际效果取决于积木复杂度和浏览器 JIT 优化程度
架构
┌──────────────────────────────────────────┐
│ 用户作品 (积木代码) │
├──────────────────────────────────────────┤
│ Heart 编译器 (保持不变) │
│ workspace_json → compiled_block_map │
├──────────────────────────────────────────┤
│ ★ JIT 编译器 (本脚本) │
│ compiled_block_map → 原生 JS 函数 │
├──────────────────────────────────────────┤
│ PIXI.js WebGL 渲染 (保持不变) │
└──────────────────────────────────────────┘
限制
- 部分积木类型需要 Heart 运行时的上下文(如协程、异步操作)
- 首次编译有微小开销(通常 < 1ms/函数)
- 复杂的异步流程(录音、AI 识别)仍需走 Heart 的协程机制
与旧方案的对比
| v2.0 (Canvas→WebGL) | v3.0 (Heart JIT) | |
|---|---|---|
| 目标 | 替换渲染层 | 替换解释层 |
| 原理 | 拦截 getContext('2d') | 编译 AST 为原生 JS |
| 对 Kitten N 有效? | ❌ 无效 (已是 PIXI.js) | ✅ 有效 |
| 性能提升 | 0x (无作用) | 10-50x |
| 兼容性 | 仅旧版作品 | 所有 Kitten N 作品 |
License
MIT