Library / SDK
rayon-rs/rayon avatar
rayon-rs/rayon

Rayon for Rust: Converting Sequential Iterators into Parallel Ones

Rayon: A data parallelism library for Rust

13,349 stars612 forksRustApache-2.0

At a glance

What is it?
Rayon is a data-parallelism library for Rust that turns foo.iter() into foo.par_iter() and guarantees data-race freedom. It is a strong fit for CPU-bound collection work and the wrong tool for I/O-bound workloads or WebAssembly builds that need real threads.
Who is it for?
Adopt Rayon if you have CPU-bound work over collections or recursive divide-and-conquer code and can compile with rustc 1.85.0 or newer. Do not adopt it for I/O-bound concurrency, for pipelines that need ordered side effects, or for a WebAssembly target where you are not prepared to add wasm-bindgen-rayon and its build configuration, because the default WebAssembly path falls back to single-core sequential iteration.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 32 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Rayon solves, and who it is actually for

Rayon targets a narrow, common problem: a computation that is already written as a sequential iterator, or as a recursive divide-and-conquer function, and that you want to spread across CPU cores without rewriting it around threads, channels and manual work queues. The README frames the pitch in one line: changing foo.iter() into foo.par_iter() is usually the whole edit. The audience is Rust developers with CPU-bound work over slices, vectors and other collections, plus anyone writing recursive algorithms that split naturally into independent subproblems.

It is not a general concurrency toolkit. The crate description in Cargo.toml calls it "Simple work-stealing parallelism for Rust", and that word simple is load-bearing. Rayon does not schedule I/O, does not give you async tasks, and does not manage long-lived background workers you push messages to. If your bottleneck is waiting on a socket or a disk, the parallel iterator machinery adds overhead without removing the wait.

Work stealing, join, and scope: the mechanism behind par_iter

The workspace splits into two crates. The rayon crate at the repository root exposes the public API: parallel iterators, the join and scope functions, and the ThreadPool type. The rayon-core crate is the engine, and Cargo.toml marks it as a public dependency, so its version is part of Rayon's own compatibility surface. The workspace dependencies list crossbeam-deque and crossbeam-utils, which is where the deque used for stealing work comes from.

The data flow is straightforward. A parallel iterator is split into tasks, those tasks are placed on per-thread deques, and idle threads steal from busy ones. The README states that parallel iterators "take care of deciding how to divide your data into tasks; it will dynamically adapt for maximum performance". That adaptivity is the point: you do not pick a chunk size or a thread count for the common case.

When the iterator API does not fit, join lets you fork two closures and wait for both, and scope lets you spawn tasks that borrow from the surrounding stack. Custom thread pools exist for the case where the global pool is the wrong place to run something. The safety claim is the structural one: the README says Rayon's APIs guarantee data-race freedom, so if the code compiles it typically behaves as the sequential version did. That guarantee is about data races, not about ordering. The README is explicit that side effects such as sending on a Rust channel or writing to disk may occur in a different order.

Installing Rayon and running a first parallel iterator

The README gives the dependency line directly. Add it to Cargo.toml; the version shown in the README is 1.12, and the published crate version in the repository manifest is 1.12.0.

toml
[dependencies]
rayon = "1.12"

The parallel iterator traits are not in the prelude of the standard library, so each module that uses them needs the Rayon prelude in scope.

rust
use rayon::prelude::*;

With those two pieces in place, the README's own example compiles as written. The only change from a sequential version is the method name on the iterator.

rust
use rayon::prelude::*;
fn sum_of_squares(input: &[i32]) -> i32 {
    input.par_iter() // <-- just change that!
         .map(|&i| i * i)
         .sum()
}

The result is the same sum you would get sequentially. What changes is that the map and the reduction are split across the worker threads of the global pool. The README notes that Rayon currently requires rustc 1.85.0 or greater, and the workspace manifest sets rust-version to 1.85 with edition 2024, so an older toolchain will fail before your code ever runs.

If you want to see the effect rather than take it on faith, the repository ships a demo crate. The README gives these commands, and notes that pressing s runs the simulation sequentially while p runs it in parallel.

text
> cd rayon-demo
> cargo run --release -- nbody visualize

Running the demo with --help lists the other available demos.

The WebAssembly fallback is a silent performance cliff

The README is unusually direct about this one. When you build to WebAssembly, Rayon treats the target as a platform without multithreading support and falls back to sequential iteration. Code compiles and runs unchanged. It also uses a single CPU core, and the README says plainly that it "will run slower".

That is a real trap for anyone porting a browser-side workload that was fast on native. Nothing in the build output announces the downgrade. You get correct results and no parallelism. Real threading on the Web requires an adapter plus project configuration, and the README points to the wasm-bindgen-rayon documentation rather than describing the setup itself.

The Cargo.toml feature list adds a related detail: the web_spin_lock feature switches to a spin-lock implementation on the browser's main thread to avoid the forbidden atomics.wait, and the manifest comments say it is only useful on the wasm32-unknown-unknown target. It pulls in the optional wasm_sync dependency. That feature addresses a specific constraint of the browser main thread; it does not turn the default WebAssembly build into a threaded one.

Where parallel iterators change behaviour, not just speed

The compile-time guarantee covers data races. It does not cover ordering, and the README says so. Any iterator body that writes to a log, appends to a shared file, or sends on a channel may execute those side effects in a different order than the sequential version. Code that happens to produce the right answer sequentially because the writes arrive in a convenient order can produce a different interleaving under par_iter.

The README also notes that parallel iterators sometimes offer alternative versions of sequential iterator methods with higher performance. That is a hint that the API is not a pure drop-in at the trait level: the set of available methods is not identical, and reaching for the faster variant is a deliberate choice.

There is a second boundary worth naming. Rayon's model is fork-join over in-memory data. It has no answer for backpressure, retries, or work that blocks for a long time. A pool thread parked on a slow network call is a thread not stealing tasks, and the global pool has a fixed size. The README does not document a timeout, a cancellation mechanism, or a way to drain a pool on shutdown, so anyone who needs those has to build them outside Rayon.

Rayon versus hand-rolled threads and channels

The realistic alternative in Rust is not another crate so much as the manual approach: spawn std::thread workers, hand out chunks of a vector, and collect results over std::sync::mpsc. That approach gives you explicit control over thread count, chunk boundaries and shutdown. It also means you write the partitioning logic yourself, and a static chunking scheme does badly when the per-item cost varies, because one worker finishes early while another is still grinding.

The difference is where the scheduling intelligence lives. Rayon's per-thread deques with stealing adapt as the work runs, which is exactly the case static chunking handles poorly. The cost is that you give up direct control: the number of tasks, their assignment and the timing of side effects are the library's business, not yours. For a fixed, uniform workload where you already know the right chunk size, manual threads are not obviously worse. For irregular workloads, recursive splits, or code you want to convert with a one-line edit, Rayon is doing work you would otherwise have to write and debug.

Maintenance, upgrades and the dual licence

The repository is not archived, and the last push was on 2026-08-28, which is recent. The workspace manifest pins rust-version to 1.85 and edition to 2024, and the README states the same minimum. That is the main upgrade constraint: raising the toolchain floor is a breaking change for downstream users, and the manifest comment about keeping some dependencies below their latest versions "in order to support older rustc" shows the project actively trades dependency freshness for a lower floor.

Rayon's own version sits at 1.12.0 while rayon-core is at 1.13.0, and because rayon-core is a public dependency, its releases are part of the compatibility story. Pinning rayon in Cargo.toml without pinning rayon-core is normal, but a lockfile diff that bumps rayon-core alone is worth reading.

On licensing: the workspace sets license to "MIT OR Apache-2.0", and the README says Rayon is distributed under both the MIT licence and the Apache License 2.0, with LICENSE-MIT and LICENSE-APACHE at the repository root. The README also states that opening a pull request is assumed to signal agreement with those licensing terms. The dual grant is the same arrangement most of the Rust ecosystem uses, and it is generally the permissive direction, but whether it fits a given product is a question for your own legal review, not something this article can settle.

Editorial conclusion

Adopt Rayon if you have CPU-bound work over collections or recursive divide-and-conquer code and can compile with rustc 1.85.0 or newer. Do not adopt it for I/O-bound concurrency, for pipelines that need ordered side effects, or for a WebAssembly target where you are not prepared to add wasm-bindgen-rayon and its build configuration, because the default WebAssembly path falls back to single-core sequential iteration. Before committing, verify the rustc version in your CI image and run the rayon-demo nbody visualization to see the sequential and parallel paths side by side.

Frequently asked questions

How do I use Rayon in a Rust project?

Add rayon = "1.12" to the [dependencies] section of Cargo.toml, then bring the traits into scope with use rayon::prelude::*; in each module that needs them. After that, changing a call such as foo.iter() to foo.par_iter() is usually the only edit required.

How do I install Rayon?

There is no separate installer. Rayon is published on crates.io, and the README's recommended way to use it is adding a dependency line to Cargo.toml and letting Cargo fetch it. The crate requires rustc 1.85.0 or greater.

Does Rayon work when compiled to WebAssembly?

By default Rayon treats WebAssembly as a platform without multithreading support and falls back to sequential iteration, so existing code compiles and runs but uses only one CPU core. Real threading on the Web needs an adapter and extra project configuration, which the README delegates to the wasm-bindgen-rayon documentation.

Does Rayon guarantee the same results as sequential code?

Rayon's APIs guarantee data-race freedom, and the README says that if your code compiles it typically does the same thing it did before. Parallel iterators are generally guaranteed to produce the same results as their sequential counterparts, with the caveat that side effects such as writing to disk or sending on a channel may occur in a different order.

What is the minimum Rust version Rayon needs?

The README states that Rayon currently requires rustc 1.85.0 or greater, and the workspace manifest sets rust-version to 1.85 with edition 2024. A build on an older toolchain fails before your code runs.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. rayon-rs/rayon on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rayon-rs-rayon.svg)](https://hysenlabs.com/projects/rayon-rs-rayon)