几天前,Google 发布了一个新的 JavaScript 基准测试,名为 Octane。新的基准测试总是受欢迎的,因为它们推动浏览器在新的领域达到新的性能水平。我特别高兴地看到包含了 pdf.js,它与大多数基准测试不同,是真实世界的代码,以及 GB 模拟器,这是一种非常有趣的性能密集型代码。但是,每个基准测试套件都有其局限性,值得牢记这一点,特别是在公告中和在 项目页面 中将新基准测试命名为“现代 Web 的 JavaScript 基准测试套件”时,这是一个很高的目标,仅靠一个基准测试难以实现。
现在,每个基准测试都必须从所有可能的代码中选择一些代码来运行,而选择具有代表性的代码非常困难。因此,基准测试永远不可能 100% 代表现有且重要的代码,这总是可以理解的。但是,即使考虑到这一点,我对 Octane 中选择的一些代码仍然存在一些担忧:两个新的基准测试中有更好的版本,并且在这些更好版本上的性能与出现在 Octane 中的版本有很大不同。
基准测试黑盒
Octane 中的一个新的基准测试是“Mandreel”,它是 Mandreel(一种 C++ 到 JS 编译器)编译的 Bullet 物理引擎。Bullet 绝对是包含在基准测试中的有趣代码。但是,选择 Mandreel 的移植版本是有问题的。一个问题是 Mandreel 是一种闭源编译器,一个黑盒,因此很难从中了解哪种代码效率更高以及应该优化什么。我们只有一个生成的代码转储,作为商业产品,任何人都需要花费金钱才能重现这些结果,并对正在运行的原始 C++ 进行修改或使用不同的代码库。我们也没有为这个特定的基准测试编译的源代码:Bullet 本身是开源的,但我们不知道这里编译的具体版本,也没有使用 Bullet 的基准测试驱动程序代码,这两者都是使用其他编译器重现这些结果所必需的。
另一种选择可能是使用由 Emscripten 编译的 Bullet,Emscripten 是一种类似地将 C++ 编译为 JS 的开源编译器(免责声明:我是 Emscripten 开发人员)。除了开源之外,Emscripten 还具有 Bullet 的移植版本(可以在 此处 查看演示),它可以以自然的方式与常规 JS 交互,使其可用于普通的 Web 游戏,而不仅仅是编译后的游戏,这与 Mandreel 的移植版本不同。这是优先选择 Emscripten 移植版本的另一个原因。
Mandreel 是否代表了 Web?
Google 将 Mandreel 包含在 Octane 中的动机是 Mandreel“用于无数基于 Web 的游戏中”。似乎 Mandreel 主要用于 Chrome 网上应用商店 (CWS),在普通 Web 中的应用较少。上面引用的描述在技术上是准确的:CWS 中的 Mandreel 游戏确实是“基于 Web 的”(用 JS+HTML+WebGL 编写),即使它们实际上并不“在 Web 上”,我所说的“在 Web 上”是指 CWS 的围墙花园之外,以及所有浏览器都可以访问的普通 Web。Google 关心在 CWS 中运行的代码的性能是完全合理的,因为 Google 运营并从中获利。但这确实对 Octane 基准测试的标题“现代 Web 的 JavaScript 基准测试套件”提出了质疑。
生成代码的性能差异很大
话虽如此,仍然可以公平地说,编译生成的代码在 Web 上的重要性日益增加,因此必须选择某个基准测试来表示它。问题是所选的特定基准测试在多大程度上代表了编译代码的整体情况。一方面,Mandreel 和 Emscripten 的编译输出非常相似:两者都使用大型类型化数组、相同的 Relooper 算法 等,因此我们可以预期性能会相似。但是,情况似乎并不总是如此。当我们将由 Mandreel 编译的 Bullet 与由 Emscripten 编译的 Bullet 进行比较时——我之前做过一个基准测试,可以在 此处 查看——在我的 MacBook pro 上,Chrome 比 Firefox 在 Emscripten 版本上的速度 慢 1.5 倍 ,但在 Google 选择包含在 Octane 中的 Mandreel 版本上的速度 快 1.5 倍。(我测试的是 Chrome Dev,它是 Linux 上可用的最新版本,以及 Firefox Aurora,它与此最接近。如果您自己运行测试,请注意,在 Emscripten 版本中,数字越小越好,而在 Octane 版本中则相反。)
(顺便说一句,Chrome 不仅难以快速运行 Emscripten 版本,而且该基准测试还暴露出 Chrome 中的一个错误,即当重新加载基准测试时,选项卡会始终崩溃——可能是 此公开问题 的副本。这种严重的、在 Mandreel 编译版本中不会发生的问题,可能表明由于开发人员关注度的不同,这两个版本进行了不同的优化。)
Mandreel 基准测试的另一个问题是名称。称其为 Mandreel 暗示它代表所有 Mandreel 生成的代码,但即使使用单个编译器,性能也可能存在巨大差异,具体取决于编译的 C/C++ 代码。例如,Chrome 在某些 Emscripten 编译的基准测试中的速度可能比 Firefox 慢 10-15 倍(示例 1、示例 2),而在其他基准测试中的速度却很快(示例)。因此,将基准测试命名为“Mandreel-Bullet”会更好,以表明它只是一个 Mandreel 编译的代码库,不能代表所有编译代码。
Box2DWeb 不是 Box2D 最好的移植版本
“Box2DWeb” 是 Octane 中的另一个新的基准测试,其中运行了 Box2D 到 JavaScript 的特定移植版本,即 Box2DWeb。但是,如 此处所示(另请参见 此处),Box2DWeb 明显慢于 Box2D 到 Web 的其他移植版本,特别是 Mandreel 和 Emscripten 从 Box2D 编写的原始 C++ 中移植的版本。现在,您可以证明排除 Mandreel 版本是合理的,因为它不能作为普通 JS 的库使用(就像之前的 Bullet 一样),但 Emscripten 编译版本没有此限制,可以在 此处找到。(可以在 此处和 此处 查看演示。)
优先选择 Emscripten 版本的另一个原因是它使用 Box2D 2.2,而 Box2DWeb 使用旧版本的 Box2D 2.1。直接编译 C++ 代码可以让 Emscripten 移植版本更容易与最新的上游功能和改进保持同步。
Google 可能调查了网站并发现速度较慢的 Box2DWeb 更受欢迎,尽管我不知道情况是否如此,但如果是这样,这将在一定程度上证明优先选择速度较慢的版本是合理的。但是,即使如此,我仍然认为最好使用 Emscripten 版本,因为如前所述,它速度更快且更新。另一个需要考虑的因素是,Octane 中包含的版本将获得关注并可能增加采用率,这使得选择最适合 Web 的版本变得更加重要。
我在 此处 发布了 Emscripten 编译的 Box2D 的基准测试,在我的机器上,Chrome 在该基准测试中的速度 慢于 Firefox 3 倍,但在 Google 选择包含在 Octane 中的版本上的速度 快 1.6 倍。这与我们之前在 Mandreel/Bullet 基准测试中看到的情况类似,并且引发了关于单个基准测试在多大程度上能够具有代表性的相同问题。
总结
如开头所述,所有基准测试都不完美。Octane 中的特定代码样本是 Chrome 运行良好的代码,但这并不意味着代码是出于这个原因而选择的:相反的因果关系更有可能,即 Google 选择专注于优化这些代码,并随着时间的推移使 Chrome 在这些代码上的运行速度加快。事情就是这样运作的——你选择要优化的事情,然后对其进行优化。
但是,在 Octane 中的 5 个新的基准测试中有 2 个,我们有充分的理由优先选择这两个基准测试的替代版本,如前所述。现在,当 Google 开始优化 Octane 时,更好的选择可能尚未出现——我不知道 Google 何时开始这项工作——但现在存在更好的替代方案这一事实使得 Octane 的很大一部分在今天显得不太相关。当然,如果更好版本的性能与 Octane 版本的性能没有太大差异,那么这无关紧要,但正如我们所看到的,当比较浏览器在这些版本上的性能时,确实存在显着差异:一个浏览器在一个版本的相同基准测试中可能明显更好,但在另一个版本中却明显更慢。
所有这一切表明,现代 Web 不能有一个单一的基准测试。代码种类实在太多了,即使我们专注于其中一种,该特定任务的不同基准测试的行为也可能大不相同。
话虽如此,我们也不应该过于怀疑:基准测试是有用的。我们需要基准测试来推动我们前进,而 Octane 是一款有趣的新基准测试,即使存在上述问题,它也包含良好的想法,值得关注。但我们应该始终意识到任何单个基准测试的局限性,尤其是在单个基准测试声称代表整个现代 Web 时。
11 条评论