• https://www.jianshu.com/writer#/notebooks/164311/notes/88906048/preview


    什么是 webassembly

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

    wasm 与 js 的区别

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

    wasm 则与之不同,它本身不是一种编程语言,而是一种字节码的标准,可以通过不同种类的高级编程语言,比如 Rust、Go、Python 等等,通过各自编译器将代码转换成 .wasm 文件,放入到浏览器预先做好的 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 场景的项目会在未来的一段时间内不断的出现,大家可以多多了解一下。

  • 相关阅读:
    Java 泛型约束
    Java 单例模式
    Java中的Atomic包使用指南
    基数排序
    归并排序
    插入排序
    选择排序
    交换排序
    Java多线程 LockSupport
    Java并发控制:ReentrantLock Condition使用详解
  • 原文地址:https://www.cnblogs.com/upyun/p/14870075.html
Copyright © 2020-2023  润新知