文章摘要
该文章探讨了在iOS上实现CPU密集型模拟器(如Dolphin)的替代方案:利用WebKit对WebAssembly的JIT编译能力,通过生成Wasm字节码而非直接生成原生机器码,从而绕过iOS的JIT限制,使模拟器能在浏览器环境中高效运行。
文章总结
文章核心内容重述
背景与动机
本文探讨了如何在iOS上实现CPU密集型模拟器(如Dolphin)的JIT编译。由于iOS禁止JIT编译,但Web浏览器是例外——JavaScriptCore和WebAssembly都支持JIT。作者提出一个思路:不直接生成原生机器码,而是生成WebAssembly字节码,由浏览器将其编译为机器码。
作者在本科毕业项目中实现了一个Game Boy模拟器WATaBoy,分别使用解释器和JIT-to-Wasm两种方式,作为概念验证和性能对比基准。
实现方法
Wasm代码生成与链接
作者使用Rust的wasm-encoder crate在运行时生成Wasm字节码。由于Wasm采用哈佛架构,无法直接执行生成的字节码,需要通过JavaScript作为"嵌入器"来完成编译、实例化和链接。
具体流程:
1. 编译与实例化:使用同步编译接口处理字节码
2. 链接:将生成模块的函数添加到主模块的间接函数表中
3. 调度:通过call_indirect指令调用表中第n个函数
关键技术细节
- 使用Rust的
#[link(wasm_import_module = "env")]导入JavaScript函数 - 通过内联WebAssembly实现
call_indirect指令 - 使用
--export-table和--growable-table链接器标志导出和扩展函数表
性能测试结果
在MacBook Air (M2)上测试了三款游戏:宝可梦蓝、塞尔达传说、Tobu Tobu Girl。
关键发现: - JIT-to-Wasm比原生解释器快约1.2倍 - JIT-to-Wasm比Wasm解释器快约1.5倍 - Safari浏览器性能最佳,Chrome和Firefox次之
局限性与未来工作
WATaBoy方面: - 缺少音频和GBC支持 - PPU模拟仍占大部分运行时间,因部分中断未实现预测 - 可进一步优化JIT编译器(如重编译分支指令)
JIT-to-Wasm通用问题: - 代码生成工具不够成熟,缺乏类似DynASM或Cranelift的易用工具 - 无法实现某些底层优化(如Dolphin的硬件快速内存映射)
结论
虽然这不能证明GameCube模拟器仅靠JIT-to-Wasm就能全速运行,但基本块JIT已能超越解释器,说明这条路径值得探索。随着代码生成工具的成熟,Wasm可能成为跨平台模拟器(尤其是iOS平台)的通用目标。
评论总结
根据评论内容,主要观点和论据如下:
项目评价:多数评论认可该项目作为本科生作品的出色性(评论3:“This is an incredible project for an undergraduate”),并肯定其实现了GameBoy JIT运行时的创新性(评论4:“What's cool here is to have a GameBoy JIT runtime at all”)。
性能对比:评论指出WASM上的JIT比原生解释器更快,因为WASM开销约20%,而解释器开销约1000%(评论4:“WASM overhead is about 20%, interpreter overhead is about 1000%”)。但评论2质疑在老旧硬件上实际速度会慢20倍(评论2:“on real old hardware it would be 20x slower in real life”)。
浏览器差异:评论3注意到Firefox比Chrome/Safari慢25%(评论3:“Firefox is 25% slower than Chrome/Safari, I wonder why”)。
未覆盖内容:评论1希望看到iOS上原生解释器与WASM-JIT的对比(评论1:“Would've been fun to see the comparison between native interpreter & JIT-on-WASM on iOS as well”)。
平衡总结:评论整体肯定项目创新性,但指出性能受硬件和浏览器影响,且缺乏iOS平台对比数据。