asm.js是一个中间语言,设计目的是使采用C编程语言编写的电脑软件可运行为网络应用程式,同时性能特征明显优于标准JavaScript

Quick Facts 设计者, 发行时间 ...
asm.js
设计者Mozilla
发行时间2013年3月21日,​11年前​(2013-03-21[1]
操作系统平台无关
网站asmjs.org
启发语言
JavaScript
Close

asm.js包括一个JavaScript的严格子集,其中的代码采用具有手动内存管理的静态类型语言(就像C语言)编写,代码使用一个原始码至原始码编译器(例如基于LLVMEmscripten)翻译。通过将语言特性限制在适合提前优化英语Ahead-of-time optimization和其他性能改进的范围内,性能得到了提高。

Mozilla Firefox是第一个实现针对asm.js优化的浏览器,从Firefox 22开始使用。[2]

设计

asm.js由JavaScript语言的一个严格子集组成。它可以显著提高采用具有手动内存管理(例如C)的静态类型语言编写的网络应用程式在使用原始码至原始码编译器转换为JavaScript后的性能。Asm.js的目标并不是提高手写JavaScript代码的性能,也不实现增强性能以外的其他目的。

通过将语言特性限制在适合提前优化和其他性能改进的范围内,其旨在具有比标准JavaScript更接近于本地(原生)代码的性能特征。[3]通过使用JavaScript的一个子集,asm.js很大程度上支持所有主要的网页浏览器[4],这不同于WebAssemblyGoogle Native Client等途径。

代码生成

asm.js通常不直接编写,而是作为一种通过编译器生成的中间语言,该编译器获取C++或其他语言的原始码,然后输出asm.js。

例如,提供下列C语言代码:

int f(int i) {
  return i + 1;
}

Emscripten将输出下列JavaScript代码:

function f(i) {
  i = i|0;
  return (i + 1)|0;
}

注意新增的|0和去除的类型说明符。在JavaScript中,按位运算符会将操作数转换为32位有符号整数并给出整数结果。这意味着使用0的按位OR为一个无作用的操作,只是将值转换为整数。通过对每个参数这样做,确保了从外部代码调用该函数时,该值被转换为正确的类型。这也用于返回值,在该情况下确保添加1到i的结果将是一个整数(否则可能变得太大),并标记函数的返回类型。这些转换为asm.js所必需,这样优化编译器才可以提前生成高效的本地代码。在此类优化编译器中,当asm.js代码调用其他asm.js代码时,转换不执行,因为必需的类型说明符意味着已保证值具有正确的类型。此外,不同于执行浮点加法和转换为整数,它可以简单地执行本机整数运算。这样一来,它可以得到显著的性能增益。 下面是另一个计算字符串长度的例子:

size_t strlen(char *ptr) {
  char *curr = ptr;
  while (*curr != 0) {
    curr++;
  }
  return (curr - ptr);
}

它对应以下asm.js代码:

function strlen(ptr) {
  ptr = ptr|0;
  var curr = 0;
  curr = ptr;
  while (MEM8[curr]|0 != 0) {
    curr = (curr + 1)|0;
  }
  return (curr - ptr)|0;
}

在生成的代码中,变量MEM8实际上是一个类型缓冲区的逐字节“视图”,它充当asm.js代码的堆(heap)。

性能

因为asm.js在浏览器中运行,所以性能很大程度上取决于浏览器和硬件。编译为asm.js的C程序的初步基准通常比使用Clang的本地编译慢一倍以上。[5]

这种超过普通JavaScript的性能增益主要是由于100%的类型一致性以及几乎没有垃圾回收(内存是手动管理的大型类型数组)。这个更简单的模型没有动态行为,没有内存分配或释放,只有一组简单、定义明确的整数和浮点操作,从而可实现更好的性能和优化潜力。[来源请求]

Mozilla在2013年12月的基准测试显示:“使用float32优化的Firefox可以运行所有基准,只比原生速度慢不到1.5倍。[6] Mozilla指出本地编译代码的性能不是单个度量,而是一个范围,使用不同的本地编译器(此例中为ClangGCC)将提供不同性能的代码。“事实上,在一些基准测试比如Box2D、FASTA和copy中,asm.js与Clang比较接近,或者比Clang到GCC还接近Clang。在一种情况下,asm.js甚至在Box2D上略微击败Clang。”

实现

Emscripten项目提供了可以编译C和C++(或其他任何可转换为LLVM IR的语言)代码为asm.js的工具。[7]

所有支持JavaScript较新版本的浏览器都应该能支持运行asm.js代码,因为它是该规范的子集。

部分浏览器的实现针对asm.js进行了特别优化:

  • Mozilla Firefox是第一个实现针对asm.js优化的网页浏览器,自Firefox 22开始使用。 OdinMonkey是Mozilla在Firefox中使用的asm.js提前编译器,它是IonMonkeySpiderMonkey的JIT编译器)的一个组件。
  • 微软在Microsoft Edge使用的JavaScript引擎Chakra中实现了asm.js支持,执行验证以产生高度优化的JIT代码。[8]
  • Google ChromeV8 JavaScript引擎在Chrome 28中对asm.js基准测试的性能是以前Chrome版本的两倍以上,[9]尽管Chrome的V8没有使用提前编译。

采用

目前几乎所有基于asm.js的应用程式都是使用Emscripten或Mandreel编译为asm.js的C/C++应用程式。

到目前为止,已有不少编程语言应用程式框架英语Application framework程序函数库游戏游戏引擎及其他软件已被移植[10]部分名单见下:

编程语言

应用程式框架

  • pepper.js:许多PNaCl应用的移植[15]
  • Qt:various Qt demos及KDE应用(如Kate)的移植[16]

程序和库

游戏引擎

游戏

仿真器

  • EM-DOSBox:一个DOSBox模拟器的移植[36]
  • Start9.io:面向多个游戏架构的网络仿真平台
  • JSMESS:一个MESS模拟器的移植,面向许多游戏机和电脑系统[37]

数学计算

参见

参考资料

外部链接

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.