All Projects → GoogleChromeLabs → wasm-bindgen-rayon

GoogleChromeLabs / wasm-bindgen-rayon

Licence: Apache-2.0 license
An adapter for enabling Rayon-based concurrency on the Web with WebAssembly.

Programming Languages

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

Projects that are alternatives of or similar to wasm-bindgen-rayon

noroutine
Goroutine analogue for Node.js, spreads I/O-bound routine calls to utilize thread pool (worker_threads) using balancer with event loop utilization. 🌱
Stars: ✭ 86 (-66.54%)
Mutual labels:  concurrency, parallel, multithreading, threads
Corium
Corium is a modern scripting language which combines simple, safe and efficient programming.
Stars: ✭ 18 (-93%)
Mutual labels:  concurrency, parallel, multithreading
MultiHttp
This is a high performance , very useful multi-curl tool written in php. 一个超级好用的并发CURL工具!!!(httpful,restful, concurrency)
Stars: ✭ 79 (-69.26%)
Mutual labels:  concurrency, parallel, multithreading
Hamsters.js
100% Vanilla Javascript Multithreading & Parallel Execution Library
Stars: ✭ 517 (+101.17%)
Mutual labels:  concurrency, parallel, multithreading
thread-pool
BS::thread_pool: a fast, lightweight, and easy-to-use C++17 thread pool library
Stars: ✭ 1,043 (+305.84%)
Mutual labels:  concurrency, parallel, multithreading
java-multithread
Códigos feitos para o curso de Multithreading com Java, no canal RinaldoDev do YouTube.
Stars: ✭ 24 (-90.66%)
Mutual labels:  concurrency, parallel, multithreading
Sobjectizer
An implementation of Actor, Publish-Subscribe, and CSP models in one rather small C++ framework. With performance, quality, and stability proved by years in the production.
Stars: ✭ 172 (-33.07%)
Mutual labels:  concurrency, multithreading
Java Concurrency Examples
Java Concurrency/Multithreading Tutorial with Examples for Dummies
Stars: ✭ 173 (-32.68%)
Mutual labels:  concurrency, multithreading
Util
A collection of useful utility functions
Stars: ✭ 201 (-21.79%)
Mutual labels:  concurrency, parallel
YACLib
Yet Another Concurrency Library
Stars: ✭ 193 (-24.9%)
Mutual labels:  concurrency, parallel
So 5 5
SObjectizer: it's all about in-process message dispatching!
Stars: ✭ 87 (-66.15%)
Mutual labels:  concurrency, multithreading
Yew
Yew is a modern Rust framework for creating multi-threaded front-end web apps with WebAssembly.
Stars: ✭ 18,243 (+6998.44%)
Mutual labels:  concurrency, multithreading
thread-pool
A modern thread pool implementation based on C++20
Stars: ✭ 104 (-59.53%)
Mutual labels:  concurrency, threads
Lightio
LightIO is a userland implemented green thread library for ruby
Stars: ✭ 165 (-35.8%)
Mutual labels:  concurrency, multithreading
Chymyst Core
Declarative concurrency in Scala - The implementation of the chemical machine
Stars: ✭ 142 (-44.75%)
Mutual labels:  concurrency, multithreading
Pht
A new threading extension for PHP
Stars: ✭ 175 (-31.91%)
Mutual labels:  concurrency, multithreading
Important Java Concepts
🚀 Complete Java - A to Z ║ 📚 Notes and Programs of all Important Concepts of Java - OOPS, Data Structures, Algorithms, Design Patterns & Development + Kotlin + Android 🔥
Stars: ✭ 135 (-47.47%)
Mutual labels:  concurrency, multithreading
pooljs
Browser computing unleashed!
Stars: ✭ 17 (-93.39%)
Mutual labels:  parallel, multithreading
Linux-Kernel-Driver-Programming
Implementation of PCI drivers, kprobe, sysfs, devfs, sensor driver, miscdevices, synchronization
Stars: ✭ 43 (-83.27%)
Mutual labels:  concurrency, parallel
Left Right
A lock-free, read-optimized, concurrency primitive.
Stars: ✭ 1,245 (+384.44%)
Mutual labels:  concurrency, multithreading

wasm-bindgen-rayon is an adapter for enabling Rayon-based concurrency on the Web with WebAssembly (via wasm-bindgen, Web Workers and SharedArrayBuffer support).

Usage

WebAssembly thread support is not yet a first-class citizen in Rust, so there are a few things to keep in mind when using this crate. Bear with me :)

For a quick demo, check out https://rreverser.com/wasm-bindgen-rayon-demo/.

Caveats

Before we get started, check out caveats listed in the wasm-bindgen threading docs. While this library specifically targets Rayon and automatically provides the necessary shims for you, some of the caveats still apply.

Most notably, even when you're using multithreading, the main thread still can't be blocked while waiting for the Rayon pool to get ready or for all the background operations to finish.

You must instantiate the main JS+Wasm in a dedicated Worker to avoid blocking the main thread - that is, don't mix UI and Rayon code together. Instead, use a library like Comlink or a custom glue code to expose required wasm-bindgen methods to the main thread, and do the UI work from there.

Setting up

First of all, in order to use SharedArrayBuffer on the Web, you need to enable cross-origin isolation policies. Check out the linked article for details.

First of all, add this crate as a dependency to your Cargo.toml (in addition to wasm-bindgen and rayon themselves):

[dependencies]
wasm-bindgen = "0.2.74"
rayon = "1.5"
wasm-bindgen-rayon = "1.0"

Then, reexport the init_thread_pool function:

pub use wasm_bindgen_rayon::init_thread_pool;

// ...

This will expose an async initThreadPool function in the final generated JavaScript for your library.

You'll need to invoke it right after instantiating your module on the main thread in order to prepare the threadpool before calling into actual library functions:

import init, { initThreadPool /* ... */ } from './pkg/index.js';

// Regular wasm-bindgen initialization.
await init();

// Thread pool initialization with the given number of threads
// (pass `navigator.hardwareConcurrency` if you want to use all cores).
await initThreadPool(navigator.hardwareConcurrency);

// ...now you can invoke any exported functions as you normally would

Using Rayon

Use Rayon iterators as you normally would, e.g.

#[wasm_bindgen]
pub fn sum(numbers: &[i32]) -> i32 {
    numbers.par_iter().sum()
}

will accept an Int32Array from JavaScript side and calculate the sum of its values using all available threads.

Building Rust code

First limitation to note is that you'll have to use wasm-bindgen/wasm-pack's web target (--target web).

Why?

This is because the Wasm code needs to take its own object (the WebAssembly.Module) and share it with other threads when spawning them. This object is only accessible from the --target web and --target no-modules outputs, but we further restrict it to only --target web as we also use JS snippets feature.

The other issue is that the Rust standard library for the WebAssembly target is built without threads support to ensure maximum portability.

Since we do want standard APIs like Mutex, Arc and so on to work, you'll need to use the nightly compiler toolchain and pass some flags to rebuild the standard library in addition to your own code.

In order to reduce risk of breakages, it's strongly recommended to use a fixed nightly version. For example, the latest stable Rust at the moment of writing is version 1.60, which corresponds to nightly-2022-04-07, which was tested and works with this crate.

Using config files

The easiest way to configure those flags is:

  1. Put a string nightly-2022-04-07 in a rust-toolchain file in your project directory. This tells Rustup to use nightly toolchain by default for your project.

  2. Put the following in a .cargo/config file in your project directory:

    [target.wasm32-unknown-unknown]
    rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals"]
    
    [unstable]
    build-std = ["panic_abort", "std"]

    This tells Cargo to rebuild the standard library with support for Wasm atomics.

Then, run wasm-pack as you normally would with --target web:

$ wasm-pack build --target web [...normal wasm-pack params...]

Using command-line params

If you prefer not to configure those parameters by default, you can pass them as part of the build command itself.

In that case, the whole command looks like this:

RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals' \
	rustup run nightly-2022-04-07 \
	wasm-pack build --target web [...] \
	-- -Z build-std=panic_abort,std

It looks a bit scary, but it takes care of everything - choosing the nightly toolchain, enabling the required features as well as telling Cargo to rebuild the standard library. You only need to copy it once and hopefully forget about it :)

Feature detection

Not all browsers support WebAssembly threads yet, so you'll likely want to make two builds - one with threads support and one without - and use feature detection to choose the right one on the JavaScript side.

You can use wasm-feature-detect library for this purpose. The code will look roughly like this:

import { threads } from 'wasm-feature-detect';

let wasmPkg;

if (await threads()) {
  wasmPkg = await import('./pkg-with-threads/index.js');
  await wasmPkg.default();
  await wasmPkg.initThreadPool(navigator.hardwareConcurrency);
} else {
  wasmPkg = await import('./pkg-without-threads/index.js');
  await wasmPkg.default();
}

wasmPkg.nowCallAnyExportedFuncs();

Usage with various bundlers

WebAssembly threads use Web Workers under the hood for instantiating other threads with the same WebAssembly module & memory.

wasm-bindgen-rayon provides the required JS code for those Workers internally, and uses a syntax that is recognised across various bundlers.

Usage with Webpack

If you're using Webpack v5 (version >= 5.25.1), you don't need to do anything special, as it already supports bundling Workers out of the box.

Usage with Rollup

For Rollup, you'll need @surma/rollup-plugin-off-main-thread plugin (version >= 2.1.0) which brings the same functionality and was tested with this crate.

Usage with Parcel

The upcoming Parcel v2 also recognises the used syntax and supports WebAssembly and Worker bundling, so should work out of the box.

Usage without bundlers

The default JS glue was designed in a way that works great with bundlers and code-splitting, but, sadly, not yet in browsers due to different treatment of import paths (see WICG/import-maps#244 which might help unify those in the future).

If you want to build this library for usage without bundlers, enable the no-bundler feature for wasm-bindgen-rayon in your Cargo.toml:

wasm-bindgen-rayon = { version = "1.0", features = ["no-bundler"] }

Note that, in addition to the earlier mentioned restrictions, this will work out of the box only in browsers with support for Module Workers. To ensure that it works in all browsers, either bundle your code for production, or include module-workers-polyfill on the same page.

License

This crate is licensed under the Apache-2.0 license.

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].