asm.js 是 JavaScript 的一个子集,非常容易优化。它通常是由编译器(例如 Emscripten)从 C 或 C++ 代码生成的。结果可以以非常高的速度运行,接近相同代码的原生编译速度。因此,Emscripten 和 asm.js 适用于 3D 游戏引擎等应用,这些引擎通常是大型且复杂的 C++ 代码库,需要快速运行。事实上,游戏行业中的顶尖公司已经采用了这种方法,例如 Unity 和 Epic,您可以在 Humble Mozilla Bundle 中看到它的实际应用,该捆绑包最近运行过。
随着 asm.js 代码变得越来越普遍,能够对其性能进行测量变得至关重要。当然,现有的基准测试有很多,包括 Octane(其中包含一个 asm.js 测试)和 JetStream(其中包含多个测试)。但是,即使是这些基准测试也没有包含 **非常大的** 代码样本,而大型代码库在特定方面具有挑战性。例如,仅加载包含此类脚本的页面可能需要相当长的时间,因为浏览器需要解析它,这会导致暂停,对用户来说很烦人。
来自 Unity 的最近基准测试 衡量了其游戏引擎的性能,该引擎(移植到 Web 后)是一个大型的 asm.js 代码库。鉴于 Unity 引擎在开发人员中非常受欢迎,因此对于浏览器中的游戏性能来说,这是一个非常好的基准测试,因为它尽可能接近真实环境,而且它还测试了大型 asm.js。但是,它确实专注于整体游戏性能,包括 WebGL 和 JavaScript 执行速度。对于游戏来说,这种整体结果通常是你关心的,但单独衡量 asm.js 也很有意思。
专门针对 asm.js 进行基准测试
Massive 是一个专门衡量 asm.js 性能的基准测试。它包含几个大型的真实世界代码库:Poppler、SQLite、Lua 和 Box2D;有关这些代码库的更多详细信息,请参阅 Massive 网站 上的常见问题解答。
Massive 报告一个总分,汇总其各个测量结果。这个分数可以帮助浏览器供应商跟踪其性能随时间的变化,并指出需要改进的领域。对于开发人员来说,它可以提供一个简单的方法来了解在特定设备和浏览器上 asm.js 执行的速度有多快。
重要的是,Massive **不仅** 测试吞吐量。如前所述,大型代码库会影响启动时间,还会影响响应能力和其他重要的用户体验方面。因此,Massive 除测试吞吐量外,还会测试浏览器加载大型代码库需要多长时间,以及在加载过程中响应能力如何。它还会测试性能的一致性。再次强调,有关这些方面更多详细信息,请参阅常见问题解答。
Massive 从第一天起就已在 github 上公开开发,我们也从许多相关方征求并收到了反馈。在过去几个月里,Massive 的开发一直在进行 beta 测试,我们收到了很多评论,目前没有重大的未解决问题,因此我们准备宣布第一个 **稳定** 版本,**Massive 1.0**。
Massive 测试了性能的多个方面,采用了新的方法,因此可能会出现某些方面没有以最佳方式进行测量的情况,当然,软件中总会有 bug。但是,通过公开开发 Massive,让每个人都有机会检查它并报告问题,以及通过进行长时间的 beta 测试,我们相信我们拥有获得可靠结果的最佳机会。当然,如果您确实发现任何问题,请 提交问题!当然,也欢迎您提供任何一般性的反馈。
Massive 性能随时间的变化
Massive 是全新的,但回顾一下它在旧浏览器上的性能(“追溯性地”)仍然很有意思,因为如果它衡量的是有用的东西,如果浏览器正在朝着正确的方向发展,那么我们应该会看到 Massive 随着时间的推移而改进,即使是在 Massive 存在之前很久就发布的浏览器版本上也是如此。下面的图表显示了 Firefox 从版本 14(于 2012 年 7 月 17 日发布,距今已超过 2 年)到版本 32(于 2014 年 9 月成为稳定版本)的性能变化。
数字越大越好,因此我们可以看到,Massive 分数确实遵循了预期的改进模式,Firefox 的 Massive 分数在 2 年前开始点基础上提高了约 **6 倍**。请注意,Massive 分数不是“线性的”,也就是说,6 倍的分数并不意味着性能提高了 6 倍,因为它使用的是几何平均值(类似于 Octane)计算的,但它平均的各个分数大多是线性的。因此,6 倍的改进确实代表了非常大且显著的加速。
仔细观察这些版本的 Firefox 随时间的变化,我们可以看到哪些功能在这些版本中发布,我们可以在这些版本中看到显著的改进。
Firefox 的 Massive 分数出现了三次大幅度跳跃,每个跳跃都进行了标注。
- Firefox 22 引入了 OdinMonkey,这是一个专门针对 asm.js 代码的优化模块。通过专门针对 asm.js 内容进行优化,它使 Firefox 的 Massive 分数几乎翻了一番。(当然,当时 Massive 还不存在;但我们在其他基准测试上测量了加速效果。)
- Firefox 26 从主线程中解析 异步脚本。这样可以避免浏览器或页面在脚本加载过程中变得无响应。对于 asm.js 内容来说,不仅解析,而且 编译 也在后台进行,使用户体验更加流畅。Firefox 26 中还包含针对 float32 操作的一般优化,这些优化出现在 Massive 中的一个测试中。
- Firefox 29 缓存 asm.js 代码:第二次访问同一个网站时,之前编译的 asm.js 代码将直接从磁盘 加载,完全避免任何编译暂停。此版本中的另一个加速是,之前的 float32 优化在 asm.js 代码中也得到了完全优化。
大型代码库以及为什么我们需要新的基准测试
这些功能中的每一个都预期会提高 asm.js 性能,因此看到这些功能带来大幅度加速是合理的。到目前为止,一切都看起来与我们的预期基本一致。但是,该图表上标注了第四个里程碑,它 **并没有** 带来任何加速。该功能是 IonMonkey,它在 Firefox 18 中发布。IonMonkey 是 Firefox 中一个新的优化编译器,它在大多数常见的浏览器基准测试中带来了非常显著的加速。那么,为什么它在 Massive 中没有显示出任何优势呢?
IonMonkey **确实** 对小型 asm.js 代码库有很大的帮助。但 IonMonkey 在其最初的 Firefox 18 版本中(见下面附注部分的更多详细信息)无法很好地处理非常大型的代码库——作为一个复杂的优化编译器,编译时间并不一定呈线性关系,这意味着大型脚本可能需要非常长的时间才能编译完成。因此,IonMonkey 包含一个脚本大小限制——超过一定大小,IonMonkey 根本不会启动。这就解释了为什么 Massive 在 Firefox 18 中没有改进,因为 IonMonkey 在那时发布了——Massive 包含非常大型的代码库,而 IonMonkey 当时无法在这些代码库上运行。
这表明,为什么像 Massive 这样的基准测试是必要的,因为其他基准测试 **确实** 在 IonMonkey 发布后显示出加速效果。换句话说,Massive 正在测量其他基准测试没有测量的东西。而这个东西——大型 asm.js 代码库——正在变得越来越重要。
(附注:IonMonkey 的脚本大小限制阻止了 IonMonkey 最初发布时大型代码库的优化,但该限制随着时间的推移而放宽,如今实际上已经不存在了。这得益于后台线程上的编译、可中断编译以及对编译速度的直接改进,所有这些都使得编译越来越大规模的函数成为可能。JavaScript 引擎的激动人心的通用改进一直在不断发生!)
关于 Robert Nyman [资深编辑]
Mozilla Hacks 的技术布道师和编辑。发表有关 HTML5、JavaScript 和开放 Web 的演讲和博客文章。Robert 是 HTML5 和开放 Web 的坚定支持者,自 1999 年以来一直从事 Web 前端开发工作,并在瑞典和纽约市工作。他也会定期在 http://robertnyman.com 上发布博客文章,他热爱旅行和结识新朋友。
更多由 Robert Nyman [资深编辑] 撰写的文章…
关于 Alon Zakai
Alon 是 Mozilla 的研究团队成员,主要从事 Emscripten 的工作,Emscripten 是一个将 C 和 C++ 编译成 JavaScript 的编译器。Alon 于 2010 年创立了 Emscripten 项目。
13 条评论