Concurrency and parallelism in Rust vs Javascript

Concurrency and parallelism are related but distinct concepts in programming. Concurrency refers to the ability of a program to have multiple threads of execution that run simultaneously, but not necessarily at the same time. This allows the program to handle multiple tasks or requests concurrently, without blocking or waiting for other tasks to complete.

Parallelism, on the other hand, refers to the ability of a program to execute multiple threads or tasks at the same time, using multiple CPU cores or other hardware resources. This can provide a performance boost by allowing the program to complete tasks faster, by dividing the work among multiple threads or cores.

Here is an example of concurrent and parallel code in Rust, compared to the same code in Javascript.

Rust:

use std::thread;

// This is a concurrent function that calculates the sum of a range of numbers.
// The function uses the rayon crate to parallelize the calculation across multiple threads.
fn sum_range(range: std::ops::Range<i32>) -> i32 {
  let sum: i32 = range
    .into_par_iter() // Convert the range into a parallel iterator.
    .sum(); // Calculate the sum in parallel using multiple threads.
  sum
}

fn main() {
  // Spawn two concurrent threads to calculate the sum of two different ranges of numbers.
  let thread1 = thread::spawn(|| sum_range(1..100));
  let thread2 = thread::spawn(|| sum_range(101..200));

  // Wait for the threads to complete and print the results.
  println!("Thread 1 sum: {}", thread1.join().unwrap());
  println!("Thread 2 sum: {}", thread2.join().unwrap());
}

JavaScript:

// This is a concurrent function that calculates the sum of a range of numbers.
// The function uses the async/await syntax to run the calculation asynchronously,
// allowing other tasks to run concurrently.
async function sumRange(range) {
  let sum = 0;
  for (let i = range.start; i < range.end; i++) {
    sum += i;
  }
  return sum;
}

async function main() {
  // Run two concurrent tasks to calculate the sum of two different ranges of numbers.
  const sum1 = sumRange({ start: 1, end: 100 });
  const sum2 = sumRange({ start: 101, end: 200 });

  // Wait for the tasks to complete and print the results.
  console.log(`Sum 1: ${await sum1}`);
  console.log(`Sum 2: ${await sum2}`);
}
main();

In the Rust code, the sum_range function uses the rayon crate to convert the input range into a parallel iterator, and to calculate the sum of the numbers in parallel using multiple threads. This allows the calculation to be done concurrently with other tasks, and to take advantage of multiple CPU cores or hardware threads to improve performance.

In the JavaScript code, the sumRange function uses the async/await syntax to run the calculation asynchronously, allowing other tasks to run concurrently. However, since JavaScript is a single-threaded language, the calculation is not actually executed in parallel. Instead, the JavaScript runtime uses a mechanism called "event loop" to switch between tasks and to allow them to run concurrently, without blocking or waiting for each other to complete.

Overall, both the Rust and JavaScript code use concurrency and asynchrony to allow multiple tasks to run concurrently, but only the Rust code uses parallelism to actually execute the tasks in parallel on multiple CPU cores or threads. This can provide a performance boost for certain types of workloads, but comes with additional complexity and challenges, such as managing shared resources and avoiding race conditions.

Did you find this article valuable?

Support KS | blog | Learn, Unlearn, Repeat by becoming a sponsor. Any amount is appreciated!