Parallelism means executing multiple tasks simultaneously. It is different from concurrency: tasks can make progress concurrently on one thread without running at the same instant. In Rust, the practical choice is whether independent work benefits enough from multiple threads to justify their overhead. section 8.0 section 11.4
For compute-intensive work over many items, start with Rayon’s parallel iterators. Replace an ordinary iterator with `par_iter()` where the operation permits it, then benchmark both versions. Rayon also provides helpers for lightweight threaded tasks; parallel iterators are the starting point for data processing. section 11.4
let start = Instant::now();
let sum = data
.iter()
.map(|n| n.wrapping_mul(*n))
.reduce(|a: i64, b: i64| a.wrapping_add(b)); #1
let finish = Instant::now() - start;
println!(
"Summing squares without rayon took {}s",
finish.as_secs_f64()
);
let start = Instant::now();
let sum = data
.par_iter()
.map(|n| n.wrapping_mul(*n))
.reduce(|| 0, |a: i64, b: i64| a.wrapping_add(b)); #2
let finish = Instant::now() - start;
println!("Summing squares with rayon took {}s", finish.as_secs_f64());
Compare the ordinary `iter().map().reduce()` pipeline with its `par_iter()` counterpart. In this small summing-squares test, Rayon took about 23 times longer: dividing work and coordinating threads outweighed the computation. section 11.4
let re = Regex::new(r"catdog").unwrap(); #1
let start = Instant::now();
let matches: Vec<_> = data.iter().filter(|s| re.is_match(s)).collect();
let finish = Instant::now() - start;
println!("Regex took {}s", finish.as_secs_f64());
let start = Instant::now();
let matches: Vec<_> =
data.par_iter().filter(|s| re.is_match(s)).collect();
let finish = Instant::now() - start;
println!("Regex with rayon took {}s", finish.as_secs_f64());
The same iterator swap helps when each item takes more work. Filtering large strings with a regular expression took about 0.0436 seconds sequentially versus 0.00617 seconds with Rayon in this test. section 11.4
Async does not make work parallel by itself. `tokio::join!` runs futures concurrently, but the blocking-sleep demonstration shows its branches executing sequentially on one thread. Spawning with `tokio::task::spawn()` makes a task eligible to run on a worker thread; Tokio chooses the thread, so a runtime with one worker cannot run those tasks in parallel. `tokio::task::spawn_blocking()` runs a blocking task on a separate thread. section 8.5
Choose and check the execution strategy:
- Use concurrent async tasks for work that spends time waiting on I/O; use nonblocking operations so waiting does not stall the thread. section 8.0 section 8.5
- Use threaded parallelism when there is enough independent computation to offset scheduling and synchronization costs. Expect diminishing returns as thread counts rise. section 11.4
- Measure the actual workload rather than assuming `par_iter()` or a multithreaded async runtime will be faster. section 11.4 section 8.2





































