本文介绍了为什么asm.js会降低性能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是看一下它的性能,我手工编写了一个很短的asm.js模块,该模块使用32位整数数学和类型化数组(Int32Array)模拟2D波动方程.我有三个版本,所有版本都尽可能相似:

Just to see how it performs, I wrote a very short asm.js module by hand, which simulates the 2D wave equation using 32-bit integer math and typed arrays (Int32Array). I have three versions of it, all as similar as possible:

  1. 普通的(即清晰易懂的C语言样式)JavaScript
  2. 与1相同,根据Firefox和其他工具,添加了asm.js批注,以便它通过验证器
  3. 与2相同,除了没有"use asm";顶部的指令

我在 http://jsfiddle.net/jtiscione/xj0x0qk3/上留下了一个演示,您可以在该模块之间切换看看使用每一个的效果.这三个都可以工作,但是速度不同.这是热点(带有asm.js注释):

I left a demo at http://jsfiddle.net/jtiscione/xj0x0qk3/ which lets you switch between modules to see the effects of using each one. All three work, but at different speeds. This is the hotspot (with asm.js annotations):

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)>>2]"等)

The "ordinary JavaScript" version is structured as above, but without the bitwise operators that asm.js requires (e.g. "x|0", "~~x", "arr[(x<<2)>>2]", etc.)

这些是使用Firefox(开发人员版v.41)和Chrome(版本44)的机器上所有三个模块的结果,以毫秒为单位:

These are the results for all three modules on my machine, using Firefox (Developer Edition v. 41) and Chrome (version 44), in milliseconds per iteration:

  • FIREFOX(版本41):20 ms,35 ms,60 ms.
  • CHROME(版本44):25 ms,150 ms,75 ms.

因此,普通的JavaScript在两种浏览器中都可以胜出.所需的asm.js批注的存在都会使性能降低3倍.此外,还存在"use asm";指令具有明显的效果-它对Firefox有所帮助,并使Chrome屈服!

So ordinary JavaScript wins in both browsers. The presence of asm.js-required annotations deteriorates performance by a factor of 3 in both. Furthermore, the presence of the "use asm"; directive has an obvious effect- it helps Firefox a bit, and brings Chrome to its knees!

仅添加按位运算符会带来三倍的性能下降,这似乎很奇怪,这是告诉浏览器使用asm.js无法克服的.另外,为什么告诉浏览器使用asm.js在Firefox中仅起到一点帮助,而在Chrome中完全适得其反呢?

It seems strange that merely adding bitwise operators should introduce a threefold performance degradation that can't be overcome by telling the browser to use asm.js. Also, why does telling the browser to use asm.js only help marginally in Firefox, and completely backfire in Chrome?

推荐答案

实际上,尚未创建asm.js来手动编写代码,而仅仅是出于从其他语言进行编译的结果.据我所知,没有任何工具可以验证asm.js代码.您是否尝试过用C语言编写代码并使用Emscripten生成asm.js代码?我强烈怀疑结果会完全不同,并且针对asm.js进行了优化.

Actually asm.js has not been created to write code by hand but only as result of a compilation from other languages. As far as I know there are no tools that validate the asm.js code.Have you tried to write the code in C lang and use Emscripten to generate the asm.js code? I strongly suspect that the result would be quite different and optimized for asm.js.

我认为混合类型化和非类型化var只会增加复杂性而没有任何好处.相反,"asm.js"代码更复杂:我尝试解析 jointjs.com上的asm.js和普通函数./demos/javascript-ast ,结果为:

I think that mixing typed and untyped vars you only add complexity without any benefits. On the contrary the "asm.js" code is more complex: I tried to parse the asm.js and the plain functions on jointjs.com/demos/javascript-ast and the results are:

  • 普通js函数具有137个节点和746个令牌
  • asm.js函数具有235个节点和1252个令牌

我想说的是,如果您在每个循环中有更多指令要执行,那么它很容易变慢.

I would say that if you have more instructions to execute in each loop it easily will be slower.

这篇关于为什么asm.js会降低性能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 06:47