Node.js中的WebAssembly入门
WebAssembly是一种令人兴奋的新语言,许多JavaScript引擎都支持它。WebAssembly有望使编译C和C ++等语言变得更容易在浏览器中运行。不过,我最兴奋的是能够编写优化的自定义算术和缓冲区操作,比如JavaScript中的快速十进制浮点运算,而无需等待TC39来解决。在本文中,我将向您展示如何获得几个在Node.js中运行的基本WebAssembly示例,并运行几个简单的基准测试来显示性能影响。
注意:本文中的代码仅在带有--expose-wasm
标志的节点7.2.1上进行了测试。该代码将不能在节点6.x或节点7.6.0工作,并将不会没有工作--expose-wasm
标志。
什么是WebAssembly无论如何?
该--expose-wasm
标志可让您访问Wasm
具有用于创建WebAssembly 模块的多个辅助函数的全局对象。就本文而言,WebAssembly模块仅是WebAssembly中编写的函数的集合。
$ ~/Workspace/node-v7.2.1-linux-x64/bin/node --expose-wasm > Wasm { verifyModule: [Function], verifyFunction: [Function], instantiateModule: [Function], experimentalVersion: 11 } >
要创建WebAssembly模块,您需要Wasm.instantiateModule()
使用表示模块的Uint8Array进行调用。下面是一个实例化一个空的WebAssembly模块的例子。
$ ~/Workspace/node-v7.2.1-linux-x64/bin/node --expose-wasm > Wasm.instantiateModule(new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x0b, 0x00, 0x00, 0x00])); {} >
因此,在基本级别上,创建WebAssembly模块包括将正确的十六进制数字放入instantiateModule()
函数中。这些十六进制数字意味着什么?这些十六进制数字是每个文件开头的序言.wasm
(.wasm
是WebAssembly文件的规范扩展)。每个WebAssembly文件都必须包含这些字节,因此这是最小可行的WebAssembly模块。
添加两个数字
谢天谢地,你不必自己写字节。有很多编译器用于编译C,C ++甚至Rust到WebAssembly。还有一种称为“WebAssembly AST” 的中间格式,简称“wast”。这是一个函数,返回它的2个参数的总和看起来像wast:
(module (func $addTwo (param i32 i32) (result i32) (i32.add (get_local 0) (get_local 1))) (export "addTwo" $addTwo))
你可以使用这个在线工具将代码编译成wasm
二进制代码,或者你可以直接从我编译.wasm
下载。
接下来,你如何.wasm
在Node.js中使用文件?为了使用它.wasm
,你需要加载文件并将节点的库返回的Node.js缓冲区fs
转换为ArrayBuffer。
const fs = require('fs'); const buf = fs.readFileSync('./addTwo.wasm'); const lib = Wasm.instantiateModule(new Uint8Array(buf)).exports; console.log(lib.addTwo(2, 2)); // Prints '4' console.log(lib.addTwo.toString()); // Prints 'function addTwo() { [native code] }'
addTwo
WebAssembly与普通的旧JavaScript实现相比有多快?这是一个简单的基准:
const fs = require('fs'); const buf = fs.readFileSync('./addTwo.wasm'); const lib = Wasm.instantiateModule(new Uint8Array(buf)).exports; const Benchmark = require('benchmark'); const suite = new Benchmark.Suite; suite. add('wasm', function() { lib.addTwo(2, 2); }). add('js', function() { addTwo(2, 2); }). on('cycle', function(event) { console.log(String(event.target)); }). on('complete', function() { console.log('Fastest is ' + this.filter('fastest').map('name')); }). run(); function addTwo(a, b) { return a + b; }
$ ~/Workspace/node-v7.2.1-linux-x64/bin/node --expose-wasm ./addTwo.js 4 wasm x 43,497,742 ops/sec ±0.77% (88 runs sampled) js x 66,021,200 ops/sec ±1.28% (83 runs sampled) Fastest is js
阶乘
在上面的例子中,WebAssembly与普通的老JS没有任何性能上的好处。让我们做一些更复杂的事情:递归地计算因式分解。这是一个.wast
公开一个fac()
递归计算阶乘函数的文件。
(module (func $fac (param i32) (result i32) (if (i32.lt_s (get_local 0) (i32.const 1)) (then (i32.const 1)) (else (i32.mul (get_local 0) (call $fac (i32.sub (get_local 0) (i32.const 1))))))) (export "fac" $fac))
你可以使用这个工具)编译.wasm
或只是在这里下载它。
下面是将计算100!
与WebAssembly和JavaScript 进行比较的另一个微不足道的基准:
const fs = require('fs'); const buf = fs.readFileSync('./factorial.wasm'); const lib = Wasm.instantiateModule(new Uint8Array(buf).buffer).exports; const Benchmark = require('benchmark'); const suite = new Benchmark.Suite; suite. add('wasm', function() { lib.fac(100); }). add('js', function() { fac(100); }). on('cycle', function(event) { console.log(String(event.target)); }). on('complete', function() { console.log('Fastest is ' + this.filter('fastest').map('name')); }). run(); function fac(n) { if (n <= 0) { return 1; } // `x | 0` rounds down, so `2.0001 | 0 === 2`. This helps deal with floating point precision issues like `0.1 + 0.2 !== 0.3` return (n * fac(n - 1)) | 0; }
$ ~/Workspace/node-v7.2.1-linux-x64/bin/node --expose-wasm ./factorial.js wasm x 2,484,967 ops/sec ±2.09% (87 runs sampled) js x 1,088,426 ops/sec ±2.63% (80 runs sampled) Fastest is wasm $
继续
在这些基本的例子中,WebAssembly在允许您真正优化JS代码方面显示出了承诺。我的基准测试非常简陋,WebAssembly仍然不稳定,并且采用不好,所以不要急于尝试编写下一个Web应用程序。然而,现在是玩WebAssembly的时候了,尤其是因为它可以在Node.js中使用。
原文地址http://thecodebarbarian.com/getting-started-with-webassembly-in-node.js.html
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android拼接合并图片生成长图
Android拼接合并图片生成长图 代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。 假设根目录的Pictures下已经有两张图片zhang.jpg和phil.jpg,最终把这两张图片合并成zhangphil.jpg的长图: package zhangphil.test; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.os.Bundle; import android.os.Environment; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; impor...
- 下一篇
Android图片添加文字水印并保存水印文字图片到指定文件
Android图片添加文字水印并保存水印文字图片到指定文件 package zhangphil.test; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Bundle; import android.os.Environment; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import java.io.BufferedOutputStream; import java.io.File; import java.io.Fi...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker安装Oracle12C,快速搭建Oracle学习环境