低级别的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采用的技巧也是每个网络开发者应该知道的。