iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🌊

Benchmarking Web Worker + WebAssembly: The Rust Journey (11)

に公開

Bundler, Maybe Next Time

Related Articles:

Previous articles in the 'Rust Journey' series

------------------- ↓ Preface starts here ↓-------------------

In the previous article,
I got WebAssembly + multi-threading running,
so now I want to know its true capabilities.

While I can't imagine a specific real-world scenario,
I'll try running a 4-billion-iteration loop on the WebAssembly side.
This is the same test I performed with JS previously.

Since the setup is the same as before,
I will only include the implementation details.

ヾ(・ω<)ノ" 三三三● ⅱⅲ Roll, roll♪

------------------- ↓ Main content starts here ↓-------------------

Main Thread Implementation

Add {type:"module"} to the options when creating the Worker instance.

./dist/js/index.mjs
(async () => {
const maxWorkers = navigator.hardwareConcurrency || 4;
const workers = []
const path = new URL('/js/worker.mjs', import.meta.url)  

for (let i = 0; i < maxWorkers; i++) {
  workers[i] = new Worker(path, {type:"module"})
  workers[i].addEventListener('message', (event) => {
      console.log("Data from worker"+i+" received: ", event.data);
  }, false);
}
})()

Adjusted to load various modules using import.

./dist/js/worker.mjs
import wasm_bindgen, {loop_wasm} from "/pkg/wasm-worker.js"
(async () => {
  const path = new URL("/pkg/wasm-worker_bg.wasm", import.meta.url)  
  await wasm_bindgen(path)

  console.time("sleep")
  loop_wasm()
  console.timeEnd("sleep")
})()

Implementation Details

Here is what the WebAssembly side implementation looks like.
Since I couldn't get a clear picture of the state when measuring from the JS side,
I embedded the measurement code directly inside WebAssembly.

./src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    pub fn log(message: String);
    #[wasm_bindgen(js_namespace = console)]
    pub fn time(index: &str);
    #[wasm_bindgen(js_namespace = console)]
    pub fn timeEnd(index: &str);
}

#[wasm_bindgen]
pub fn loop_wasm() {
    let max: u32 = 40_0000_0000;

    time("wasm");
    for i in 0..max {}
    timeEnd("wasm");
}

Building the project:

wasm-pack build --release --target web --out-dir ./dist/pkg --out-name wasm-worker

Results

(^_^;) That's overwhelming.

In JS, a 4-billion-iteration loop took about 3 seconds,
but in WASM, it was in the 1/100ms order.
There was no point in even comparing them.

I need to come up with an implementation that leverages this,
but it seems quite difficult.

completed

Discussion