python wasm_认识 WebAssembly

自从Brendan Eich用十天时间创造了JavaScript,人们对它的吐槽就从未间断过。众所周知JavaScript是一门动态语言。运行于JavaScript引擎中,我们熟悉的有Mozilla的SpiderMonkey,Safari的JavaScriptCore,Edge的Chakra还有大名鼎鼎的V8。V8引擎将JavaScript的运行效率提升到一个新的level。所以后来的Nodejs也采用V8作为引擎,实现了用js进行后端开发的愿景。

然而JavaScript发展到今天,其语言基因中存在的缺陷并不能得到根本性的改变。比如常见的加法操作

function add(a, b) {

return a + b;

}

这段代码在浏览器中的运行过程比你想象的复杂。

add在被调用前,js引擎并不能提前预判传入参数的类型,需要在运行时对参数进行如下一连串的类型判断和转换操作。

对js加法运算的详细操作(keng)有兴趣的可以看这篇文章。

V8再快也难以逾越语言本身的瓶颈。这种问题是动态语言的弊端,对于此类问题,业界已经出现了非常多的解决方案。

而本文要讲的正是目前最为前沿的一种 ------ WebAssembly。

WebAssembly这个概念其实2015年就提出来了,而就在不久之前,四大浏览器厂商,Chrome, Firefox, Edge, Safari 在新版的浏览器中才全部默认支持Webassembly(Chrome, Firefox早于后两者),这种技术很快将在前端高性能开发领域中大放异彩。

WebAssembly是什么?

下面是来自官方的定义:

WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web.

关键词:”format",WebAssembly 是一种编码格式,适合编译到web上运行。

事实上,WebAssembly可以看做是对JavaScript的加强,弥补JavaScript在执行效率上的缺陷。

它是一个新的语言,它定义了一种AST,并可以用字节码的格式表示。

它是对浏览器的加强,浏览器能够直接理解WebAssembly并将其转化为机器码。

它是一种目标语言,任何其他语言都可以编译成WebAssembly在浏览器上运行。

想象一下,在计算机视觉,游戏动画,视频编解码,数据加密等需要需要高计算量的领域,如果想在浏览器上实现,并跨浏览器支持,唯一能做的就是用JavaScript来运行,这是一件吃力不讨好的事情。而WebAssembly可以将现有的用C,C++编写的库直接编译成WebAssembly运行到浏览器上, 并且可以作为库被JavaScript引用。那就意味着我们可以将很多后端的工作转移到前端,减轻服务器的压力。这是WebAssembly最为吸引人的特性。并且WebAssembly是运行于沙箱中,保证了其安全性。

为什么要有WebAssembly?

如果只是想让C,C++,Java等原生语言编写的模块运行在浏览器上。我们只需要一个转换器,将源语言转换为目标语言JavaScript,而这种技术其实很早就有了。

例如将Java转换成JavaScript的Google Web Toolkit (GWT)

将python转换成JavaScript的pyjamas 等等。

但是这并没有解决JavaScript执行慢的问题,这跟直接用JavaScript来重写代码库是一样的作用。这就是为什么Electron能直接运行Node.js但对比传统桌面应用依然弱鸡的原因。

要理解JavaScript为什么运行慢,就要理解它在引擎中的处理过程。

传统JavaScript在V8引擎中的编译过程是这样的:首先JavaScript会被编译成AST,然后引擎再将AST, 转化为机器语言交给底层执行。

V8的pipeline结构会进一步先将AST转化为一种中间代码,再对中间代码再次生成优化后的机器码,从而实现更快的执行速度。

对于WebAssembly来说,前面的parser, optimize 全部省了,直接编译到机器码。

浏览器通过增加一种语言格式的编译支持,来实现执行效率的突破。

WebAssembly除了运行快之外,其特殊的二进制表示法也大大减小了代码包的大小。同时提升了浏览器的加载速度。

如何使用WebAssembly?

现在你已经能在这些浏览器中使用WebAssembly了。

WebAssembly这么快,但并不意味着JavaScript这门语言要从此绝迹了。

如前面所说,WebAssembly和JavaScript之间是可以相互调用的。

假设我们用C写了这段代码

include

int add(int a, int b) {

return a + b;

}

首先将其转化为wasm文件, 这里运用一个线上的工具 WasmFiddle

将转化的add.wasm下载下来。

由于目前还没支持 的引入方式。所以不能直接在html引入,我们可以通过JS fetch来请求文件。

先封装一个fetch方法:

function fetchAndInstantiateWasm (url, imports) {

return fetch(url)

.then(res => {

if (res.ok)

return res.arrayBuffer();

throw new Error(`Unable to fetch Web Assembly file ${url}.`);

})

.then(bytes => WebAssembly.compile(bytes))

.then(module => WebAssembly.instantiate(module, imports || {}))

.then(instance => instance.exports);

}

用定义好的fetchAndInstantiateWasm方法请求add.wasm文件,并在回调中调用C中定义的add方法,成功输出结果15。

fetchAndInstantiateWasm('add.wasm', {})

.then(m => {

console.log(m.add(5, 10)); // 15

});

同样通过js import,也能够在C中调用js的方法。

fetchAndInstantiateWasm('program.wasm', {

env: {

consoleLog: num => console.log(num)

}

})

.then(m => {

console.log(m.add(5, 10)); // 15

});

上面在js代码中定义了consoleLog, 并传入了wasm文件,在C中就可以调用consoleLog方法往控制台输出信息,你也可以执行一些你想要的其他操作。

#include

void consoleLog(int num);

int add(int num1, int num2) {

int result = num1 + num2;

consoleLog(result);

return result;

}

可直接下载demo代码执行查看效果 demo。

运行python -m SimpleHTTPServer后访问localhost:8000, 查看log中输出信息。

前面说WebAssembly是一门新的语言,但上面引入的wasm只是一种字节码,是作为其他语言编译的目标语言,完全没有可读性。其实WebAssembly是有自己的语法的,文件格式为wast。下面是add方法编译成的WebAssembly版本。

(module

(type $FUNCSIG$vi (func (param i32)))

(import "env" "consoleLog" (func $consoleLog (param i32)))

(table 0 anyfunc)

(memory $0 1)

(export "memory" (memory $0))

(export "add" (func $add))

(func $add (param $0 i32) (param $1 i32) (result i32)

(call $consoleLog

(tee_local $1

(i32.add

(get_local $1)

(get_local $0)

)

)

)

(get_local $1)

)

)

wast是可编辑的,它同样可以直接转化为wasm, 用于浏览器引入。

上面只是一个最简单的例子,实际上利用WebAssembly实现的应用已经可以相当酷炫。

还有一个运用webassembly实现的浏览器视频编辑器

和其他类似技术的区别?

asm.js

可能对前端比较关注的同学有听说过asm.js。它是Mozilla开发的一个JavaScript的子集。就是在JavaScript的基础上,加入了静态类型的支持。

asm.js是Mozilla开发的,所以只支持自家浏览器Firefox。当然代码也可以兼容运行于其他浏览器,但是就没有了优化效果。

asm.js 提供一种语法来表示变量类型

var first = 5;

var second = first;

对于上面这段JavaScript代码,在asm.js里是这样写的

var first = 5;

var second = first | 0;

在first后面加上|0,我们就将first标记为32位整数,而被赋值的second也为被定义为32位整数。

在Mozilla引擎编译代码的时候,遇到这些标志就会提前知道变量的类型,提前优化代码。而这些标记也不影响其他引擎的运算结果。

然而说到底它还是JavaScript,只不过我们提前为优化做了准备。代码还是要经过JavaScript Code ->AST->Optimize的过程。

另外asm.js也是支持将C,C++转化为asm.js的,有兴趣的可以参考这里

TypeScript

大家应该也知道微软的TypeScript,TypeScript做的工作其实跟asm.js有点类似,只不过TypeScript是更加High-Level的。他是JavaScript的一个超集,就是在JavaScript的基础上支持了类型和类等语法。并且能直接编译为JavaScript。TypeScript在于能在开发阶段就进行类型检查,保证代码开发效率和安全性。但是从浏览器运行效率上来看并没有优化效果,因为浏览器并不原生支持。

相同功能的还有facabook的Flow,也是在开发阶段加入类型的支持。

结语

目前WebAssembly由W3C WebAssembly Community Group负责开发与标准定制,而该组织的成员正是来自Google, Microsoft, Mozilla等浏览器开发人员。几个大厂同时投入到WebAssembly的开发中,相信不久WebAssembly就会成为一种浏览器网站&应用的通用优化技术。

参考资料

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
selfie_segmentation_solution_simd_wasm_bin.js 是一个自拍分割解决方案的 JavaScript 文件。该文件利用 SIMD (单指令多数据) 和 WebAssembly 技术实现了自拍分割功能,并以二进制格式保存。 自拍分割是一种利用计算机视觉技术将自拍照片中的人物主体与背景进行分离的方法。这种技术可以应用于很多场景,比如制作虚化背景效果、替换背景、添加特效等等。 SIMD 是一种并行计算技术,它使用单个指令同时对多个数据进行操作,可以提高计算效率。由于自拍分割需要对图像中的每个像素进行计算,利用 SIMD 可以加快分割速度,使得实时应用变得可能。 WebAssembly (简称wasm) 则是一种基于低级汇编语言的二进制格式,它可以在现代浏览器中运行,提供了更高性能的计算能力。通过将自拍分割算法编译为 wasm 格式,可以在浏览器中快速加载和执行算法,而无需依赖于服务器端的计算资源。 selfie_segmentation_solution_simd_wasm_bin.js 文件包含了已经编译为 wasm 格式的自拍分割算法的二进制数据,可以通过浏览器的 WebAssembly 接口加载并使用。使用这个文件,开发者可以轻松地将自拍分割功能集成到自己的网页应用中,实现各种有趣的效果。 总结来说,selfie_segmentation_solution_simd_wasm_bin.js 是一个实现自拍分割功能的 JavaScript 文件,利用了 SIMD 和 WebAssembly 技术提高了计算效率和性能,可以在浏览器中快速加载和执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值