current position:Home>30 minute zero basic actual combat webassembly and rust

30 minute zero basic actual combat webassembly and rust

2022-01-29 15:24:04 Bug King

Preface

  • The goal is : Through actual combat , understand WebAssembly Development process , There is a simple comparison of performance
  • Example : Realization leetcode - Fibonacci sequence
  • Study preparation : need 0 Basics , be based on Mac Environmental Science , therefore bash Part of the command line Windows Students may need to replace
  • Study for a long time : about 30 minute
  • Packaging tools : webpack 5
  • Writing time :2021-10-13
  • Code @Github:dive-into-wasm

1. Environmental installation

install Rust And corresponding packages .

1.1 install Rust

$ curl -sSf https://static.rust-lang.org/rustup.sh | sh
 Copy code 

1.2 Change to domestic source

Change to domestic source , Otherwise the installation will be too slow .

New file :~/.cargo/config, Replace with the following ,replace-with It's your own business ping Various domestic sources in the document , See which source to use quickly :

[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"

#  Replace it with your preferred mirror source 
replace-with = 'sjtu'

#  Tsinghua University 
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"

#  University of science and technology of China 
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"

#  Shanghai Jiaotong University 
[source.sjtu]
registry = "https://mirrors.sjtug.sjtu.edu.cn/git/crates.io-index"

# rustcc Community 
[source.rustcc]
registry = "git://crates.rustcc.cn/crates.io-index"
 Copy code 

1.3 install cargo-generate The scaffold

$ cargo install cargo-generate
 Copy code 

1.4 install wasm-pack

wasm-pack hold Rust Compiled into WebAssembly .

$ cargo install wasm-pack
 Copy code 

2. To complete a Rust lib project

2.1 establish Rust project

$ cargo new rust --lib
 Copy code 

here rust Is the name of the project , You can change it to any name you want .

Be careful : It will automatically be named rust Folder , Do not create this folder manually .

2.2 To configure Cargo.toml

newly added [lib] , stay [dependencies] Add... Below wasm-bindgen rely on , The modified The complete content is similar to the following :

[package]
name = "rust"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen="0.2"
 Copy code 

2.3 lib.rs Code implementation

Code details are not discussed here , The contents of the document are as follows :

extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fib(i: u32) -> u32 {
    match i {
        0 => 0,
        1 => 1,
        _ => fib(i - 1) + fib(i - 2)
    }
}

#[wasm_bindgen]
pub fn fib_tail_call_optimized(i: u32, prev: u32, next: u32) -> u32 {
    match i {
        0 => next,
        1 => next,
        _ => fib_tail_call_optimized(i - 1, next, prev + next)
    }
}
 Copy code 

2.4 Compiled into WebAssembly Binary system

stay rust Project root , use wasm-pack Tool compilation :

$ wasm-pack build
 Copy code 

If successful, it will output something similar to the following :

...
[INFO]:    Your wasm pkg is ready to publish at .../dive-into-wasm/rust/pkg.
 Copy code 

At this time in pkg The directory will be generated as follows 5 File :rust.js,rust.d.ts, rust_bg.js,rust_bg.wasm,rust_bg.wasm.d.ts.rust_bg.wasm Binary files , That's what we'll use later .

3. Complete a front-end project

Complete a front-end project , And compile it into the browser to execute the generated WebAssembly .

3.1 Create front end projects

stay rust The parent directory of the directory executes ( namely web Contents and rust The directory is at the same level , Otherwise, the path in the sample code of this tutorial will be adjusted ):

$ mkdir web && cd web
$ npm init -y
 Copy code 

3.2 To configure webpack And development server

Installation dependency :

$ npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin
 Copy code 

Webpack 5 Not on by default WebAssembly Support , It needs to be configured manually , Simultaneous use html-webpack-plugin Automatically generate an entry HTML ,webpack.config.js The contents are as follows :

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    mode: 'development',
    plugins: [
        new HtmlWebpackPlugin({title: ' actual combat  WASM Rust'})
    ],
    //  Experimental characteristics 
    // BREAKING CHANGE: Since webpack 5 WebAssembly is not enabled by default and flagged as experimental feature.
    // You need to enable one of the WebAssembly experiments via 'experiments.asyncWebAssembly: true' (based on async modules) or 'experiments.syncWebAssembly: true' (like webpack 4, deprecated).
    experiments: {
        asyncWebAssembly: true
    }
}
 Copy code 

3.3 Write substitution and test code

Implementation calls WebAssembly And increase JS Realization , Conduct benchmark .

JS Realization 2 A way , One is a common implementation , One is the implementation of tail recursive optimization ,src/fib.js Code :

function fib(i) {
    if (i <= 1) return i

    return fib(i - 1) + fib(i - 2)
}


function fibTailCallOptimized(i, prev = 0, next = 1) {
    if (i <= 1) return next

    return fibTailCallOptimized(i - 1, next, prev + next)
}

export {
    fib,
    fibTailCallOptimized
}
 Copy code 

Call and execute benchmark ,src/index.js Code :

//  Direct reference  wasm  file 
import {fib as wasm_fib, fib_tail_call_optimized as wasm_fib_tail_call_optimized } from '../../rust/pkg/rust_bg.wasm'
import { fib, fibTailCallOptimized } from './fib.js'

function time(timerName, func) {
    console.time(timerName)
    console.log(`${timerName}: `, func())
    console.timeEnd(timerName)
}

// js  The implementation number cannot be too large , otherwise  CPU  completely fill , Can't run the results 
const num = 30
time('wasm_fib', () => wasm_fib(num))
time('wasm_fib_tail_call_optimized', () => wasm_fib_tail_call_optimized(num, 0, 1))
time('fib', () => fib(num))
time('fibTailCallOptimized', () => fibTailCallOptimized(num))
 Copy code 

Notice that the first line refers to rust_bg.wasm Binary code .

Be careful : Browser security policy prohibits the use of file:// Protocol loading wasm file , So what we use here webpack-dev-server.

3.4 Browser running and benchmark

webpack Package and run in the browser to test the effect .

$ npx webpack serve
 Copy code 

Open in browser , Usually http://localhost:8080/ . Console input is similar to the following ( Display of deleted results , You can check it yourself , First, ensure the consistency of operation results ):

wasm_fib: 0.193115234375 ms
wasm_fib_tail_call_optimized:   ms

fib: 0.93701171875 ms
fibTailCallOptimized: 0.16796875 ms
 Copy code 

You can see wasm The ratio of execution efficiency JS Not optimized high 5 About times ;

After tail call optimization is 2 About times .

Reference documents

  1. Cargo Chinese document
  2. Replace cargo Source —— Attached are the currently available domestic cargo Image source configuration

copyright notice
author[Bug King],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/01/202201291524020934.html

Random recommended