低级别的JavaScript - asm.js的魅力

201 阅读3分钟

低级别的JavaScript - asm.js的魅力

asm.js,或称Assembly JavaScript,是普通JavaScript的一个子集,它是为了利用JavaScript的某些方面和低级技术来榨取网络上的每一盎司的速度。

asm.js是如何工作的?

asm.js是普通JavaScript的一个严格的子集,具有一些有趣的方面。与大多数JavaScript方言不同,asm.js是一个编译目标,而不是要手工编码的东西。相反,程序员编写C或C++,然后将半编译的源代码翻译成asm.js。

asm.js利用了JavaScript的许多低级方面来发挥速度的优势。在这篇文章中,我们将探讨asm.js采用的两个技巧,看看网络的一些真正力量。

类型

在C或C++代码被编译成asm.js JavaScript之前,它看起来是这样的。

int add(int a, int b){
	return a + b;
}

经过LLVM的优化,并通过Emscripten(一种将C/C++转化为asm.js的工具),上述代码就变成了。

function add(a, b){
	return a | 0 + b | 0
}

类型注释

如果你看一下编译后的asm.js代码,你应该会经常看到bitwise OR 0。比如说。

var x = 3 | 0

这个位法OR对我们的值做了一些有趣的事情。在这种情况下,它充当了从浮点number 到intnumber 的隐式转换。在你的控制台中试试这个。

var x = 3.5 | 0
console.log(x) // 3

从强类型化到弱类型化

如果你曾经学习过JavaScript的入门课程,你会知道所有的数字都是number 。在你的浏览器的控制台中试试这些。

//would be an int in C/C++
console.log(typeof(3)) //prints number
//would be a float in C/C++
console.log(typeof(3.14)) //prints number

JavaScript中的number 类型是一个8字节的IEEE-754浮点数。这是否意味着我们使用ints的C/C++代码会被翻译成8字节的float?并非如此。JavaScript实际上可以处理不同大小和类型的数字。

//here is what the number type normally is
console.log(Float64Array.BYTES_PER_ELEMENT)
//prints 8
//a traditional C/C++ int
console.log(Int8Array.BYTES_PER_ELEMENT)
//prints 1

在浏览器的控制台中运行这两个数字,第一个数字是8字节,第二个数字是1字节。有了这些知识,我们可以看到asm.js是如何将C/C++中的强类型变量转化为弱类型的JavaScript的。

闪电回合

asm.js在引擎盖下做的事情比我们在这里要讲的多得多,但它们仍然值得注意。下面是asm.js的一些更有趣的方面,在尝试优化JavaScript的时候要考虑到。

  • asm.js放弃了像JavaScript Objects这样的高级抽象概念
  • asm.js不产生垃圾,因此不需要花时间去收集垃圾。
  • asm.js利用工作线程的优势,开辟了更快的异步代码。
  • asm.js允许使用一些C/C++库,如OpenCV和Qhull。

结论

如果你想看看asm.js的运行情况,我推荐Mozilla的bananabread演示。这个游戏引擎最初是用C++编写的,然后被编译成JavaScript,在网络上运行。

asm.js是释放网络力量的一个重要工具。它的用途是无穷无尽的,从媒体处理到游戏,到人工智能,到响应式网络应用。即使你不在你的项目中使用它,asm采用的技巧也是每个网络开发者应该知道的。