{"id":17922630,"url":"https://github.com/rreverser/wasm-bindgen-rayon","last_synced_at":"2025-04-05T17:07:44.345Z","repository":{"id":212682681,"uuid":"732079849","full_name":"RReverser/wasm-bindgen-rayon","owner":"RReverser","description":"An adapter for enabling Rayon-based concurrency on the Web with WebAssembly.","archived":false,"fork":false,"pushed_at":"2024-03-31T16:10:02.000Z","size":1100,"stargazers_count":74,"open_issues_count":4,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-14T15:12:28.360Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://docs.rs/wasm-bindgen-rayon","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"GoogleChromeLabs/wasm-bindgen-rayon","license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RReverser.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"RReverser","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2023-12-15T15:37:58.000Z","updated_at":"2024-06-18T18:39:31.877Z","dependencies_parsed_at":"2024-06-18T18:39:03.577Z","dependency_job_id":"b16a9bf0-3b28-4ece-b123-1cd8da1ba0df","html_url":"https://github.com/RReverser/wasm-bindgen-rayon","commit_stats":null,"previous_names":["rreverser/wasm-bindgen-rayon"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RReverser%2Fwasm-bindgen-rayon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RReverser%2Fwasm-bindgen-rayon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RReverser%2Fwasm-bindgen-rayon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RReverser%2Fwasm-bindgen-rayon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RReverser","download_url":"https://codeload.github.com/RReverser/wasm-bindgen-rayon/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247369952,"owners_count":20927928,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-28T20:40:03.716Z","updated_at":"2025-04-05T17:07:44.311Z","avatar_url":"https://github.com/RReverser.png","language":"JavaScript","funding_links":["https://github.com/sponsors/RReverser"],"categories":[],"sub_categories":[],"readme":"`wasm-bindgen-rayon` is an adapter for enabling [Rayon](https://github.com/rayon-rs/rayon)-based concurrency on the Web with WebAssembly (via [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen), Web Workers and SharedArrayBuffer support).\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\u003c!-- param::isNotitle::true:: --\u003e\n\n- [Usage](#usage)\n  - [Setting up](#setting-up)\n  - [Using Rayon](#using-rayon)\n  - [Building Rust code](#building-rust-code)\n    - [Using config files](#using-config-files)\n    - [Using command-line params](#using-command-line-params)\n  - [Usage with various bundlers](#usage-with-various-bundlers)\n    - [Usage with Webpack](#usage-with-webpack)\n    - [Usage with Parcel](#usage-with-parcel)\n    - [Usage with Rollup / Vite](#usage-with-rollup--vite)\n    - [Usage without bundlers](#usage-without-bundlers)\n  - [Feature detection](#feature-detection)\n- [License](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n# Usage\n\nWebAssembly thread support is not yet a first-class citizen in Rust - it's still only available in nightly - so there are a few things to keep in mind when using this crate. Bear with me :)\n\nFor a quick demo, check out [this Mandelbrot fractal generator](https://rreverser.com/wasm-bindgen-rayon-demo/):\n\n\u003ctable width=\"100%\"\u003e\n  \u003ctr\u003e\n  \u003ctd width=\"50%\"\u003e\n\n![Drawn using a single thread: 273ms](https://github.com/RReverser/wasm-bindgen-rayon/assets/557590/665cb157-8734-460d-8a0a-a67370e00cb7)\n    \n  \u003c/td\u003e\n  \u003ctd width=\"50%\"\u003e\n\n![Drawn using all available threads via wasm-bindgen-rayon: 87ms](https://github.com/RReverser/wasm-bindgen-rayon/assets/557590/db32a88a-0e77-4974-94fc-1b993030ca92)\n    \n  \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Setting up\n\nIn order to use `SharedArrayBuffer` on the Web, you need to enable [cross-origin isolation policies](https://web.dev/coop-coep/). Check out the linked article for details.\n\nThen, add `wasm-bindgen`, `rayon`, and this crate as dependencies to your `Cargo.toml`:\n\n```toml\n[dependencies]\nwasm-bindgen = \"0.2\"\nrayon = \"1.8\"\nwasm-bindgen-rayon = \"1.2\"\n```\n\nThen, reexport the `init_thread_pool` function:\n\n```rust\npub use wasm_bindgen_rayon::init_thread_pool;\n\n// ...\n```\n\nThis will expose an async `initThreadPool` function in the final generated JavaScript for your library.\n\nYou'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:\n\n```js\nimport init, { initThreadPool /* ... */ } from './pkg/index.js';\n\n// Regular wasm-bindgen initialization.\nawait init();\n\n// Thread pool initialization with the given number of threads\n// (pass `navigator.hardwareConcurrency` if you want to use all cores).\nawait initThreadPool(navigator.hardwareConcurrency);\n\n// ...now you can invoke any exported functions as you normally would\n```\n\n## Using Rayon\n\nUse [Rayon](https://github.com/rayon-rs/rayon) iterators as you normally would, e.g.\n\n```rust\n#[wasm_bindgen]\npub fn sum(numbers: \u0026[i32]) -\u003e i32 {\n    numbers.par_iter().sum()\n}\n```\n\nwill accept an `Int32Array` from JavaScript side and calculate the sum of its values using all available threads.\n\n## Building Rust code\n\nFirst limitation to note is that you'll have to use `wasm-bindgen`/`wasm-pack`'s `web` target (`--target web`).\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ci\u003eWhy?\u003c/i\u003e\u003c/summary\u003e\n\nThis 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](https://rustwasm.github.io/wasm-bindgen/reference/js-snippets.html).\n\n\u003c/details\u003e\n\nThe other issue is that the Rust standard library for the WebAssembly target is built without threads support to ensure maximum portability.\n\nSince we want standard library to be thread-safe and [`std::sync`](https://doc.rust-lang.org/std/sync/) APIs 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.\n\nIn order to reduce risk of breakages, it's strongly recommended to use a fixed nightly version. This crate was tested with `nightly-2024-08-02`.\n\n### Using config files\n\nThe easiest way to configure those flags is:\n\n1. Put the following in a `rust-toolchain.toml` file in your project directory:\n\n  ```toml\n  [toolchain]\n  channel = \"nightly-2024-08-02\"\n  components = [\"rust-src\"]\n  targets = [\"wasm32-unknown-unknown\"]\n  ```\n  \n  This tells rustup to use a fixed nightly toolchain with the wasm-target for your project, and to install rust-src, which is required for `build-std`.\n2. Put the following in a `.cargo/config.toml` file in your project directory:\n\n   ```toml\n   [target.wasm32-unknown-unknown]\n   rustflags = [\"-C\", \"target-feature=+atomics,+bulk-memory\"]\n\n   [unstable]\n   build-std = [\"panic_abort\", \"std\"]\n   ```\n\n   This tells Cargo to rebuild the standard library with support for Wasm atomics.\n\nThen, run [`wasm-pack`](https://rustwasm.github.io/wasm-pack/book/) as you normally would with `--target web`:\n\n```sh\nwasm-pack build --target web [...normal wasm-pack params...]\n```\n\n### Using command-line params\n\nIf you prefer not to configure those parameters by default, you can pass them as part of the build command itself.\n\nIn that case, the whole command looks like this:\n\n```sh\nRUSTFLAGS='-C target-feature=+atomics,+bulk-memory' \\\n  rustup run nightly-2024-08-02 \\\n  wasm-pack build --target web [...] \\\n  -- -Z build-std=panic_abort,std\n```\n\nIt 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 :)\n\n## Usage with various bundlers\n\nWebAssembly threads use Web Workers under the hood for instantiating other threads with the same WebAssembly module \u0026 memory.\n\nwasm-bindgen-rayon provides the required JS code for those Workers internally, and [uses a syntax that is recognised across various bundlers](https://web.dev/bundling-non-js-resources/).\n\n### Usage with Webpack\n\nIf you're using Webpack v5 (version \u003e= 5.25.1), you don't need to do anything special, as it already supports [bundling Workers](https://webpack.js.org/guides/web-workers/) out of the box.\n\nNote that, unlike other bundlers, Webpack will warn about circular dependency because it uses content-based hashing. In our case, we do need to import the same module in both the main thread and the Worker, so this warning can be safely ignored. Hopefully, Webpack will implement support for circular ES modules (which are allowed by the spec) in the future.\n\n### Usage with Parcel\n\nParcel v2 also recognises the used syntax and works out of the box.\n\n### Usage with Rollup / Vite\n\nWe recommend using [Vite](https://vitejs.dev/) for Rollup users, as it has all the necessary plugins built-in.\n\nAlternatively, you should be able to configure Rollup yourself with plugins like [`@surma/rollup-plugin-off-main-thread`](https://github.com/surma/rollup-plugin-off-main-thread) and [`@web/rollup-plugin-import-meta-assets`](https://modern-web.dev/docs/building/rollup-plugin-import-meta-assets/) to bundle Worker and WebAssembly assets respectively.\n\n### Usage without bundlers\n\nThe default JS glue was designed in a way that works great with bundlers and code-splitting, but, sadly, not in browsers due to different treatment of import paths (see [`WICG/import-maps#244`](https://github.com/WICG/import-maps/issues/244)).\n\nIf you want to build this library for usage without bundlers, enable the `no-bundler` feature for `wasm-bindgen-rayon` in your `Cargo.toml`:\n\n```toml\nwasm-bindgen-rayon = { version = \"1.2\", features = [\"no-bundler\"] }\n```\n\n## Feature detection\n\nIf you're targeting [older browser versions that didn't support WebAssembly threads yet](https://webassembly.org/roadmap/), 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.\n\nYou can use [`wasm-feature-detect`](https://github.com/GoogleChromeLabs/wasm-feature-detect) library for this purpose. The code will look roughly like this:\n\n```js\nimport { threads } from 'wasm-feature-detect';\n\nlet wasmPkg;\n\nif (await threads()) {\n  wasmPkg = await import('./pkg-with-threads/index.js');\n  await wasmPkg.default();\n  await wasmPkg.initThreadPool(navigator.hardwareConcurrency);\n} else {\n  wasmPkg = await import('./pkg-without-threads/index.js');\n  await wasmPkg.default();\n}\n\nwasmPkg.nowCallAnyExportedFuncs();\n```\n\n# License\n\nThis crate is licensed under the Apache-2.0 license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frreverser%2Fwasm-bindgen-rayon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frreverser%2Fwasm-bindgen-rayon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frreverser%2Fwasm-bindgen-rayon/lists"}