All Projects → w3reality → wasm-mt

w3reality / wasm-mt

Licence: other
A multithreading library for Rust and WebAssembly

Programming Languages

rust
11053 projects
javascript
184084 projects - #8 most used programming language
HTML
75241 projects
Makefile
30231 projects

Projects that are alternatives of or similar to wasm-mt

geopattern-rs
Beautiful generative geometric images from a string, based on @jasonlong's geo_pattern, with a WASM demo
Stars: ✭ 44 (-63.64%)
Mutual labels:  wasm
safenetwork-gitportal
p2p git portal - a decentralised alternative to github
Stars: ✭ 12 (-90.08%)
Mutual labels:  wasm
jasper
🧳 Single-binary packaging for Ruby applications that supports native and Wasm targets
Stars: ✭ 29 (-76.03%)
Mutual labels:  wasm
The-Java-Workshop
A New, Interactive Approach to Learning Java
Stars: ✭ 65 (-46.28%)
Mutual labels:  threading
spherro
Smooth particle hydrodynamics fluid simulator
Stars: ✭ 35 (-71.07%)
Mutual labels:  wasm
vrcpu
Code, documentation, schematics, notes for my Ben Eater inspired breadboard computer and emulator
Stars: ✭ 98 (-19.01%)
Mutual labels:  wasm
Xiecheng Comment
🌈Xiecheng_Comment多线程Threading爬取携程的丽江古城景点评论并生成词云
Stars: ✭ 23 (-80.99%)
Mutual labels:  threading
soabase-stages
A tiny library that makes staged/pipelined CompletableFutures much easier to create and manage
Stars: ✭ 23 (-80.99%)
Mutual labels:  threading
ugo-compiler-book
📚 µGo语言实现(从头开发一个迷你Go语言编译器)[Go版本+Rust版本]
Stars: ✭ 996 (+723.14%)
Mutual labels:  wasm
wasm-linker-js
A simple WebAssembly Linker in JavaScript
Stars: ✭ 14 (-88.43%)
Mutual labels:  wasm
Stitch
Simple threading library using annotations for Android
Stars: ✭ 28 (-76.86%)
Mutual labels:  threading
landlord
Magic: The Gathering mulligan and card draw simulator
Stars: ✭ 16 (-86.78%)
Mutual labels:  wasm
wasm-ops
Chart of WebAssembly Instructions
Stars: ✭ 46 (-61.98%)
Mutual labels:  wasm
blazor-adminlte
This project adapts ADMINLTE 3 so the components can be used from dotnet core Blazor / Server / Web Assembly
Stars: ✭ 182 (+50.41%)
Mutual labels:  wasm
wasmsign2
PoC implementation of the WebAssembly Modules Signatures proposal.
Stars: ✭ 18 (-85.12%)
Mutual labels:  wasm
wasm-toolchain
WebAssembly toolchain
Stars: ✭ 34 (-71.9%)
Mutual labels:  wasm
MudBlazor.Markdown
Markdown component based on the MudBlazor environment
Stars: ✭ 30 (-75.21%)
Mutual labels:  wasm
nanogui-GLES-wasm
nanogui port for GLES and WASM
Stars: ✭ 37 (-69.42%)
Mutual labels:  wasm
fullstack-rust
Reference implementation of a full-stack Rust application
Stars: ✭ 39 (-67.77%)
Mutual labels:  wasm
humanbenchmark
Memory tests solver with using OpenCV
Stars: ✭ 20 (-83.47%)
Mutual labels:  threading

wasm-mt

Docs | GitHub | Crate

crates MIT licensed CI

A multithreading library for Rust and WebAssembly.

wasm-mt helps you create and execute Web Worker based threads. You can program the threads simply using Rust closures and orchestrate them with async/await.

Examples

  • wasm-mt-pool - Thread pool library based on wasm-mt. [ crate | source ]

You can run all the following apps in browser!

  • exec - How to use wasm_mt. [ live | source ]
  • fib - Computing a Fibonacci sequence with nested threads. [ live | source ]
  • executors - Minimal serial/parallel executors using wasm_mt. [ live | source ]
  • parallel - Julia set benchmark of serial/parallel executors. [ live | source ]
  • arraybuffers - Demo of using WasmMt::new_with_arraybuffers(). [ live | source ]

Background and implementation

The preceding seminal work entitled "Multithreading Rust and Wasm" by @alexcrichton centers on Web Workers, shared memory, and the WebAssembly threads proposal. Shared memory is built on top of SharedArrayBuffer whose availability across major browsers has been somewhat limited. Also, the rust-wasm thread implementation work, along with the threads proposal, seems still in progress.

On the contrary, Web Worker based multithreading in JavaScript has been well supported for a long time. After experimenting, we have come up to a Rust ergonomic multithreading solution that does not require SharedArrayBuffer. It just works across all major browsers today and we named it wasm-mt.

Internally, we use the postMessage() Web Worker API (through bindings provided by wasm-bindgen) to initialize spawned threads. And, importantly, we keep using postMessage() for dynamically sending Rust closures (serialized by serde_traitobject) to the spawned threads. By doing so, the parent thread can await the results of the closures executed in the spawned thread. We have found that this approach is highly flexible for extension, too. For example, it is straightforward to augment WasmMt::Thread to support more customized inter-thread communication patterns.

Note, however, that wasm-mt has some remarkable limitations compared to the ongoing shared memory based multithreading work led by wasm-bindgen. wasm-mt is not efficient in that it does not include support of the standard thread primitive operations:

  • shared memory based message passing and mutexes,
  • atomic instructions and efficient memory handling per the threads proposal.

Thanks

Getting started

Requirements:

Cargo.toml:

wasm-mt = "0.1"
serde = { version = "1.0", features = ["derive"] }
serde_closure = "0.2"

Creating a thread

First, create a [WasmMt] thread builder with [new][WasmMt::new] and initialize it:

use wasm_mt::prelude::*;

let pkg_js = "./pkg/exec.js"; // path to `wasm-bindgen`'s JS binding
let mt = WasmMt::new(pkg_js).and_init().await.unwrap();

Then, create a [wasm_mt::Thread][Thread] with the [thread][WasmMt::thread] function and initialize it:

let th = mt.thread().and_init().await.unwrap();

Executing a thread

Using the [exec!] macro, you can execute a closure in the thread and await the result:

// fn add(a: i32, b: i32) -> i32 { a + b }

let a = 1;
let b = 2;
let ans = exec!(th, move || {
    let c = add(a, b);

    Ok(JsValue::from(c))
}).await?;
assert_eq!(ans, JsValue::from(3));

You can also execute an async closure with exec!:

// use wasm_mt::utils::sleep;
// async fn sub(a: i32, b: i32) -> i32 {
//    sleep(1000).await;
//    a - b
// }

let a = 1;
let b = 2;
let ans = exec!(th, async move || {
    let c = sub(a, b).await;

    Ok(JsValue::from(c))
}).await?;
assert_eq!(ans, JsValue::from(-1));

Executing JavaScript in a thread

Using the [exec_js!] macro, you can execute JavaScript within a thread:

let ans = exec_js!(th, "
    const add = (a, b) => a + b;
    return add(1, 2);
").await?;
assert_eq!(ans, JsValue::from(3));

Similarly, use [exec_js_async!] for running asynchronous JavaScript:

let ans = exec_js_async!(th, "
    const sub = (a, b) => new Promise(resolve => {
        setTimeout(() => resolve(a - b), 1000);
    });
    return await sub(1, 2);
").await?;
assert_eq!(ans, JsValue::from(-1));

Making executors

By using [wasm_mt:Thread][Thread], you can easily create custom executors. One such example is the wasm-mt-pool crate. It provides a thread pool that is based on the work stealing scheduling strategy.

Here, for simplicity, we show the implementation of much more straightforward executors: a serial executor and a parallel executor.

First, prepare a Vec<wasm_mt::Thread> containing initialized threads:

let mut v: Vec<wasm_mt::Thread> = vec![];
for i in 0..4 {
    let th = mt.thread().and_init().await?;
    v.push(th);
}

Then, here's the executors in action. Note, in the latter case, we are using wasm_bindgen_futures::spawn_local to dispatch the threads in parallel.

console_ln!("🚀 serial executor:");
for th in &v {
    console_ln!("starting a thread");
    let ans = exec!(th, move || Ok(JsValue::from(42))).await?;
    console_ln!("ans: {:?}", ans);
}

console_ln!("🚀 parallel executor:");
for th in v {
    spawn_local(async move {
        console_ln!("starting a thread");
        let ans = exec!(th, move || Ok(JsValue::from(42))).await.unwrap();
        console_ln!("ans: {:?}", ans);
    });
}

Observe the starting/ending timing of each thread in the developer console:

🚀 serial executor:
starting a thread
ans: JsValue(42)
starting a thread
ans: JsValue(42)
starting a thread
ans: JsValue(42)
starting a thread
ans: JsValue(42)
🚀 parallel executor:
(4) starting a thread
(4) ans: JsValue(42)
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].