【发布时间】:2015-08-01 23:09:15
【问题描述】:
为了看看它的性能,我手工编写了一个非常短的 asm.js 模块,它使用 32 位整数数学和类型化数组 (Int32Array) 模拟 2D 波动方程。我有它的三个版本,都尽可能相似:
- 普通(即易读,尽管是 C 风格)JavaScript
- 与 1 相同,添加了 asm.js 注释,以便根据 Firefox 和其他工具通过验证器
- 与 2 相同,但没有“使用 asm”;顶部的指令
我在http://jsfiddle.net/jtiscione/xj0x0qk3/ 留下了一个演示,它可以让您在模块之间切换以查看使用每个模块的效果。这三个都可以工作,但速度不同。这是热点(带有 asm.js 注释):
for (i = 0; ~~i < ~~h; i = (1 + i)|0) {
for (j = 0; ~~j < ~~w; j = (1 + j)|0) {
if (~~i == 0) {
index = (1 + index) | 0;
continue;
}
if (~~(i + 1) == ~~h) {
index = (1 + index) | 0;
continue;
}
if (~~j == 0) {
index = (1 + index) | 0;
continue;
}
if (~~(j + 1) == ~~w) {
index = (1 + index) | 0;
continue;
}
uCen = signedHeap [((u0_offset + index) << 2) >> 2] | 0;
uNorth = signedHeap[((u0_offset + index - w) << 2) >> 2] | 0;
uSouth = signedHeap[((u0_offset + index + w) << 2) >> 2] | 0;
uWest = signedHeap [((u0_offset + index - 1) << 2) >> 2] | 0;
uEast = signedHeap [((u0_offset + index + 1) << 2) >> 2] | 0;
uxx = (((uWest + uEast) >> 1) - uCen) | 0;
uyy = (((uNorth + uSouth) >> 1) - uCen) | 0;
vel = signedHeap[((vel_offset + index) << 2) >> 2] | 0;
vel = vel + (uxx >> 1) | 0;
vel = applyCap(vel) | 0;
vel = vel + (uyy >> 1) | 0;
vel = applyCap(vel) | 0;
force = signedHeap[((force_offset + index) << 2) >> 2] | 0;
signedHeap[((u1_offset + index) << 2) >> 2] = applyCap(((applyCap((uCen + vel) | 0) | 0) + force) | 0) | 0;
force = force - (force >> forceDampingBitShift) | 0;
signedHeap[((force_offset + index) << 2) >> 2] = force;
vel = vel - (vel >> velocityDampingBitShift) | 0;
signedHeap[((vel_offset + index) << 2) >> 2] = vel;
index = (index + 1)|0;
}
}
“普通 JavaScript”版本的结构如上,但没有 asm.js 所需的位运算符(例如“x|0”、“~~x”、“arr[(x>2 ]”等)
这些是我机器上所有三个模块的结果,使用 Firefox(开发者版 v. 41)和 Chrome(版本 44),每次迭代以毫秒为单位:
- FIREFOX(版本 41):20 毫秒、35 毫秒、60 毫秒。
- CHROME(版本 44):25 毫秒、150 毫秒、75 毫秒。
所以普通的 JavaScript 在两种浏览器中都胜出。 asm.js 所需注释的存在使两者的性能下降了 3 倍。此外,“使用 asm”的存在;指令有一个明显的效果——它对 Firefox 有点帮助,让 Chrome 屈服!
仅添加按位运算符会引入三倍的性能下降,这似乎很奇怪,而这无法通过告诉浏览器使用 asm.js 来克服。另外,为什么告诉浏览器使用 asm.js 对 Firefox 的帮助很小,而在 Chrome 中却完全适得其反?
【问题讨论】:
-
首先,我在 Chrome 44 和 FF 39(Win XP,32 位)中运行了 "Massive" benchmark,这是我对 Chrome 和 Firefox 的结果(复制并转储到“在基准页面上输入从另一个运行复制的数据”字段 - 是的,它适用于实际的 HTML)。除了一点(“poppler-cold-preparation”),Chrome 到处都慢,在最极端的情况下比 FF 慢 24.6 倍。看起来 Chrome 目前只是无法合理处理 asm.js。
-
只是一个想法,您是否对后续/重复调用进行了“基准测试”,因为 asm 在编译/选择阶段会使用更多时间(我想)?
-
@birdspider 你的意思是多次运行基准测试?不,我只是拿走了那里的东西......当前界面似乎需要重新加载页面才能再次运行基准测试,很可能需要再次编译/优化代码。但是整个基准测试对我来说大约需要 15 分钟才能完成,所以我认为编译时间并不是一个很大的因素。如果 Chrome 真的需要这么长时间来编译,我会感到困惑的是,代码甚至可以运行根本。
-
我认为它根本没有实现 (dev.modern.ie/platform/status/asmjs) asm.js;谷歌浏览 chrome 论坛,它处于某种测试阶段,名称为
turbofan- 也是 (phoronix.com/…) -
@birdspider 那么为什么在添加/删除
'use asm'时会有很大的不同呢?它只是没有加起来......
标签: javascript performance bitwise-operators asm.js