Web程序性能优化——asm.js和WebAssembly

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:首先解决的是

asm.js

asm.jsJavaScript 语言中一个可以高度优化的子集。通过避免 JavaScript 引擎某些难以优化的机制和模式(主要是垃圾回收和类型判断),达到 JavaScript 引擎运行优化的目的。换言之,正常的 JavaScript 代码会类型自动装换和垃圾自动回收的,而编写 asm.js 风格的代码则表示 程序员 需要管理内存和确定数据类型。

asm.js 不提供任何额外的语法,只要编写 asm.js 的代码,在支持 asm.js 优化的 JavaScript 引擎中能被自动识别,从而让引擎实现自己的优化,而在不支持 asm.js 的引擎中也能正常运行。

手写asm.js例子

首先解决的是 JavaScript 中变量类型的问题

var a = 10;
var b = a;
var a = 10;
var b = a | 0;

上面两段代码的不同之处在于,第一段代码b的值类型在运行的时候才能被确定,而第二段代码中b总是会被当作32位整型处理。同样的还有对运算的限制,如 (a + b) | 0 把两个变量的加运算限制为更高效的整型加运算。在支持 asm.jsJavaScript 引擎中,运行上面的代码会进行底层优化。

第二个要解决的问题是内存分配,众所周知, JavaScript 不提供垃圾回收相关的API,在 JavaScript 中讲垃圾回收大多数开发者会想到将不用的变量设为 null ,比如:

// 创建一个长度为10000的数组
var a = new Array(10000).fill('hello');

a = null;

但对于垃圾回收 a = null 只是告诉浏览器长度为10000的数组已经没有被任何变量引用,可以回收其占用的内存了,至于什么时候回收,浏览器有自己的想法。

asm.js 中所说的内存分配和这个机制不同, asm.js 的内存分配由程序员自己控制。使用 ArrayBuffer 创建一个数据缓冲区,可以在这个缓冲区存储和取值,而不需要再付出内存分配和垃圾回收的代价。 ArrayBuffer 是不能直接操作的,而是通过类型数组对象和 DataView (视图)对象,具体用法请参考 MDN | ArrayBuffer ,下面是一个例子

// 创建一个64k的数据缓冲区
var heap = new ArrayBuffer(0x10000);

// 使用64位浮点值数组引用这个缓冲区
var arr = new Float64Array( heap )

下面是一个更复杂的例子,使用 asm.js 风格的代码编写一个函数计算两数之间的相邻数的乘积,存储起来并计算总和

function ASM (heap) {

  var arr = new Int32Array(heap);

  function foo(x, y) {
    x = x | 0;
    y = y | 0;

    var i = 0;
    var p = 0;
    var sum = 0;
    for (i = x | 0; (i | 0) < (y | 0); p = (p + 8) | 0, i = (i + 1) | 0) {
      sum = (sum + i * (i + 1)) | 0;

      arr[p >> 3] = (i * (i + 1)) | 0;
    }

    return +sum;
  }

  return foo;
}

var heap = new ArrayBuffer(0x1000);

var foo = ASM(heap)

foo(0, 1024) // 357913600

通常用“模块”机制将asm.js代码封装起来,如上面的代码,内存区变量为私有变量,不可在外部更改。

上面代码中,使用 ArrayBuffer 分配内存,使用 Int32Array 规定数据类型,在使用数据时,每个数据也都使用特殊的符号标识数据类型,在支持 asm.js 的引擎中,这些都是触发优化的信号,而在不支持 asm.js 的引擎,这些符号也是正常的运算符而已,不影响计算结果。

Emscripten

在实际运用中,不大可能手写 asm.js 规范的代码,写起来异常麻烦并且容易出错,所以通常 asm.js 代码通常是其他语言的编译目标代码,比如使用 EmscriptenC / C++ 代码编译成 asm.js

安装 Emscripten

$ git clone https://github.com/juj/emsdk.git
$ cd emsdk
$ ./emsdk install latest
$ ./emsdk activate latest
$ source ./emsdk_env.sh

Emscripten的编译用法非常简单

  1. 编写一个C++程序hello.cc。
#include <iostream>

int main () {
  std::cout << "Hello World" << std::endl;
}
  1. 使用以下命令将 C++ 源码编译成 asm.js
emcc hello.cc

输出文件 a.out.js 就是 asm.js 规范的 JavaScript 代码,默认执行 main 函数。

WebAssembly

WebAssembly 字节码是一种抹平了不同 CPU 架构的机器码, WebAssembly 字节码不能直接在任何一种 CPU 架构上运行,但由于非常接近机器码,可以非常快的被翻译为对应架构的机器码,因此 WebAssembly 运行速度和机器码接近,这听上去非常像 Java 字节码。

WebAssembly 出现之前,浏览器只能运行 .js 后缀的编程代码文件, JavaScript 是web应用开发的唯一语言,但是在支持 WebAssembly 的浏览器上,现在能运行 .wasm 后缀的代码文件了。

WebAssembly 几乎不可能是手工编写的,一般由其他语言编译而成,目前能编译成 WebAssembly 的高级语言有:

  • AssemblyScript : 语法和 TypeScript 一致,对前端来说学习成本低,为前端编写 WebAssembly 最佳选择;
  • c\c++ : 官方推荐的方式;
  • Rust : 语法复杂、学习成本高,对前端来说可能会不适应;
  • Kotlin : 语法和 JavaJS 相似,语言学习成本低;
  • Golang : 语法简单学习成本低。

Hello world

使用 AssemblyScript 编译成 WebAssembly ,首先安装

yarn global add AssemblyScript/assemblyscript

编写源代码 demo.ts

export function foo (x: i32):i32 {
  return x * x;
}

使用 asc demo.ts -o demo.wasm 编译代码,使用js代码 fetch 方法加载 wasm 模块

fetch('./demo.wasm')
  .then(res => {return res.arrayBuffer()})
  .then(WebAssembly.instantiate) // 编译成当前CPU架构的机器码并实例化
  .then(module => { // module为WebAssembly模块
    console.log(module.instance.exports.foo(100))
  })

总结

asm.jsWebAssembly 都是底层优化web程序性能的技术,他们通常都是由其他语言编译而成。 asm.js 是JavaScript的一个子集,所以在不支持 asm.js 优化的浏览器上也能正常运行,它的文件类型是文本; WebAssembly 则是更新的技术,提供了新的API,在不支持的浏览器上无法运行,它的文件类型是二进制字节码。这两种技术虽然都是极高提升web程序性能的技术,但一般开发中不会使用到,只有在密集型计算、图形处理等计算场景才能发挥出它们的巨大优势。

作者简介:叶茂,芦苇科技web前端开发工程师,代表作品:口红挑战网红小游戏、芦苇科技官网。擅长网站建设、公众号开发、微信小程序开发、小游戏、公众号开发,专注于前端框架、服务端渲染、SEO技术、交互设计、图像绘制、数据分析等研究。

欢迎和我们一起并肩作战: web@talkmoney.cn

访问 www.talkmoney.cn 了解更多


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

安全之美

安全之美

Andy Oram、John Viega / 徐 波、沈晓斌 / 机械工业出版社华章公司 / 2011-4-28 / 65.00元

“这本深思熟虑的论文集(《安全之美》)帮助读者摆脱安全领域闪烁着欺骗光芒的心理恐惧,转而欣赏安全的微妙美感。本书描述了安全的阴和阳,以及引人注目的破坏性和闪亮光辉的建设者之间剑拔弩张的气氛。” ——Gary McGraw,Cigital公司CTO,《Software Security》及其他9本书的作者 大多数人不会太关注安全问题,直到他们的个人或商业系统受到攻击。这种发人深省的现象证......一起来看看 《安全之美》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试