什么是 webassembly

在 2019 年 12 月之前,如果你要编写一个web页面,那一定离不开 html、css、js 这三个好兄弟。在 2019 年 12 月之后 W3C 宣布 webassembly 加入了他们。为什么要在三兄弟后加入 webassembly ?它和之前的有什么区别么?以 js 为对比,我们具体看一下它们的区别。

wasm 与 js 的区别

js 是一种解释型语言,它代码运行之前不会进行编译工作,而是在执行的过程中实时编译。为了让边编译边执行能够顺利进行,我们拥有了 js 引擎。

wasm 则与之不同,它本身不是一种编程语言,而是一种字节码的标准,可以通过不同种类的高级编程语言,比如 Rust、Go、Python 等等,通过各自编译器将代码转换成 .wasm 文件,放入到浏览器预先做好的 wasm 虚拟机当中运行。

同时这种与 js 不同,可以预先运行的特色,也给 wasm 带来了一些优势:

  • 拥有一套完成的语义: wasm 这套体积小且加载快的二进制格式的完整语义,可以让硬件充分发挥能力以达到原生的执行效率。

  • 编译和优化时间所需时间较少: 相比 js 作为一个动态类型需要多次编译代码,wasm 让文件在推送到服务器前就进行了众多优化,能够有效减少编译和优化时间。

  • 执行速度更快: wasm 是二进制文件,它的指令更接近机器码,执行起来的速度相比 js 更快。

  • 垃圾回收效率更高: wasm 目前并不支持自动垃圾回收,垃圾回收都是手动控制的,比自动垃圾回收效率更高。

当然如果只是这么说,我们并不能很直观的感受出这些优势究竟有多大,刚好目前浏览器已经支持了以 wasm 规范的虚拟机。

接下来,我们通过一个 Chrome 与 Safari 的实例测试,来感受一下。

wasm与js执行速度比较

首先我们用原生的 js 写一段 fib 代码测试时间,代码内容如下:


<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head> <body>
<script>
function fibonacci(n) {
if (n == 0 || n == 1)
return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
function fibonacciTime() {
console.time("js")
fibonacci(40)
console.timeEnd("js")
}
fibonacciTime()
</script>
</body> </html>

用 live-server 测试时间,用时 1275 毫秒到 1329 毫秒。

然后我们用 Rust 转义成 wasm 再次测试。特别需要注意的是,测试用到的算法都是最普通的递归迭代,在实际使用中我们还可以使用动态规划来再次优化。

言归正传,然后我们用 rust-wasm 编译器将用 rust 写好的 fib 代码转换成 wasm 文件。

下载 wasm 编译器:

curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

配置 Cargo.toml:


[package]
name = "wasm"
version = "0.2.0"
authors = ["hzjsea"]
edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib]
crate-type = ["cdylib"]
path = "src/main.rs" [dependencies]
wasm-bindgen = "0.2.48"
chrono = "0.4.19"

main.rs:


use chrono::Utc;
use wasm_bindgen::prelude::*;
use std::time::Instant; #[wasm_bindgen]
pub fn fib(n: i32) -> i32 {
match n {
0 => 1,
1 => 1,
_ => fib(n - 1) + fib(n - 2),
}
} pub fn main(){
let result = fib(40);
println!("{:?}", result);
}

挂载wasm文件,即类似 vue,使用 index.html 把 wasm.js 文件挂载起来:


<script type="module">
main() async function main() {
const wasm = await import('/pkg/wasm.js')
await wasm.default('/pkg/wasm_bg.wasm')
console.time("rust")
console.log(wasm.fib(40))
console.timeEnd("rust")
} function fibonacci(n) {
if(n==0 || n == 1)
return n;
return fibonacci(n-1) + fibonacci(n-2);
}
function fibonacciTime(){
console.time("js")
fibonacci(40)
console.timeEnd("js")
}
fibonacciTime()
</script>

之后用编译器编译 Rust 代码生成 .wasm 文件:


wasm-pack build --target web --no-typescript --mode normal

然后我们可以明显看到,在相同的 live-server 测试下时间相差一倍左右。

因为此次编译指定不生成 wasm 的 ts 版本。所有只有上面的几个文件,其中:

  • package.json

{
"name": "wasm",
"collaborators": [
"hzjsea"
],
"version": "0.2.0",
"files": [
"wasm_bg.wasm",
"wasm.js"
],
"module": "wasm.js",
"sideEffects": false
}

指定打包的各类属性

  • wasm_bg.wasm

wasm.js转义后的二进制文件

  • wasm.js

由rust代码转移过来的wasm.js文件。

wasm 的组件库

看完了实例测试,我们不能略过测试中提到的 Rust。Rust 中有个类似于 react 的框架,叫做Yew。关于 Yew 官方[https://github.com/yewstack/yew]描述如下:

Yew is a modern Rust framework for creating multi-threaded front-end web apps with WebAssembly.

  • Features a macro for declaring interactive HTML with Rust expressions. Developers who have experience using JSX in React should feel quite at home when using Yew.

  • Achieves high performance by minimizing DOM API calls for each page render and by making it easy to offload processing to background web workers.

  • Supports JavaScript interoperability, allowing developers to leverage NPM packages and integrate with existing JavaScript applications.

计时器

大致看完了 Rust,如果你还想看更多的 WebAssembly 流程,官方提供的一个计时器的练手项目可以满足你的需求

项目地址 https://yew.rs/docs/zh-CN/getting-started/build-a-sample-app

主要可以看下 lib.rs 这个文件

总结与思考

虽然 webassembly 作为一种新的 web 技术常常被提起,但是因为其工具链的调试困难,包体积过大等等问题还在解决的过程中,同时也表明了 wasm 并不可能在短时间内直接代替 js,他们之间更多的是一种互补合作的关系。但不可否认的是,适合 webassembly 场景的项目会在未来的一段时间内不断的出现,大家可以多多了解一下。

https://www.jianshu.com/writer#/notebooks/164311/notes/88906048/preview的更多相关文章

  1. 接口测试之——Charles抓包及常见问题解决(转载自https://www.jianshu.com/p/831c0114179f)

    简介 Charles其实是一款代理服务器,通过成为电脑或者浏览器的代理,然后截取请求和请求结果达到分析抓包的目的.该软件是用Java写的,能够在Windows,Mac,Linux上使用,安装Charl ...

  2. [转]https://www.jianshu.com/p/06443248f4d8

    eos是什么? 原文 https://www.jianshu.com/p/06443248f4d8 简介 用一句话来定义eos,即:区块链操作系统,支持在它之上构建dapp,支持智能合约.帐户.身份验 ...

  3. Zabbix调优不完全指南(https://www.jianshu.com/p/2d911d55448f)

    从学习搭建zabbix到完成各类监控.调优.二次开发已经过去了两年,期间通过QQ学习群.zabbix官方社区.各个技术博客整理学习了不少关于各种报错的处理方法,现在将常见的一些报错处理方法整理出来分享 ...

  4. jar与war包区别,转自https://www.jianshu.com/p/3b5c45e8e5bd

    https://www.jianshu.com/p/3b5c45e8e5bd

  5. fastdfs(https://www.jianshu.com/p/1c71ae024e5e)

    参考 官方网站:https://github.com/happyfish100/ 配置文档:https://github.com/happyfish100/fastdfs/wiki/ 参考资料:htt ...

  6. https://www.jianshu.com/p/1038c6170775

    import os # 方法一: os.walk实现 def items_dir(rootname): l = [] for main_dir, dirs, file_name_list in os. ...

  7. Redis 单线程却能支撑高并发 - 简书 https://www.jianshu.com/p/2d293482f272

    小结: 1.在 I/O 多路复用模型中,最重要的函数调用就是 select,该方法的能够同时监控多个文件描述符的可读可写情况:2.Redis 服务采用 Reactor 的方式来实现文件事件处理器(每一 ...

  8. 当我写下Map<String,Object> map = new HashMap<>() https://www.jianshu.com/p/6b2e350e99be

    当我写下Map<String,Object> map = new HashMap<>();我到底在写什么? 我什么时候会写HashMap? 一个函数同时需要返回 多种 状态的情 ...

  9. Asp.Net Core 第01局:项目创建和部署 转载https://www.jianshu.com/p/9c9750e23b3e

    总目录 一.前言 本文通过从项目创建到部署,简单介绍Asp.Net Core. 二.环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 三.开局 第一手:创建项目   ...

随机推荐

  1. Linux中数据库的安装和配置(MySQL与Maria DB)

    目录 MySQL和Maria DB的介绍 MySQL和Maria DB的安装 yum源安装MySQL(Centos6.5+Mysql5.1) 源码包安装MySQL yum源安装Maria DB 源码包 ...

  2. 这次我好像才真的明白了CSS Rem字体计算的原理

    背景 如何按照设计稿中标注的尺寸,直接写页面的样式,不再需要px2rem这样的工具或者人工转换 ? 只要你明白了rem的计算原理,这个问题的答案超级简单. 根字体大小计算核心原理 设备的根字体大小 * ...

  3. Spring中@Import注解的使用

    Spring中@Import注解的使用 @Import注解算是SpringBoot自动配置原理中一个很重要的注解 认识@Import注解 先看一下源码 @Target(ElementType.TYPE ...

  4. JavaScrip条件表达式优化

    目录 1,前言 2,多条件if语句优化 3,参数默认值 4,Switch语句优化 1,前言 今早看了一篇文章<JavaScrip实现:如何写出漂亮的条件表达式>,原创于:华为云开发者社区, ...

  5. 【Azure 环境】在Azure虚拟机(经典) 的资源中,使用SDK导出VM列表的办法

    Azure,  在2008年10月的Microsoft专业开发人员大会(PDC)上宣布,当时使用内部项目代号"Project Red Dog",并于2010年2月正式发布为Wind ...

  6. Flink去重统计-基于自定义布隆过滤器

    一.背景说明 在Flink中对流数据进行去重计算是常有操作,如流量域对独立访客之类的统计,去重思路一般有三个: 基于Hashset来实现去重 数据存在内存,容量小,服务重启会丢失. 使用状态编程Val ...

  7. “可变的”tuple

    来看一个"可变的"tuple: >>> t = ('a', 'b', ['A', 'B']) >>> t[2][0] = 'X' >> ...

  8. yiled

    def fib(max): n,a,b = 0,0,1 while n < max: print("hallo") yield b #把函数执行过程冻结在这一步,并且把b的值 ...

  9. [刷题] 350 Intersection of Two Arrays

    要求 给定两个数组nums,求两个数组交集 输出结果与元素在两个数组中出现的次数一致 不考虑输出结果的顺序 举例 nums1=[1,2,2,1] nums2=[2,2] 结果:[2,2] 思路 使用m ...

  10. 搭建LNMP环境部署Wordpress博客

    !!!首先要做的就是关闭系统的防火墙以及selinux: #systemctl stop firewalld #systemctl disable firewalld #sed -ri 's/^(SE ...