Search code examples
rustparallel-processingmutex

How do I disable the eventual fairness of the Rust parking_lot crate's Mutex?


I have a prior assurance that a rayon par_iter's threads will only lock a Mutex once each for a batch of work, and since I have no thread starving concerns, have no need to incur the (apparently 0.5ms) overhead of parking_lot's eventual fairness guarantee. Parking_lot still offers other benefits I would like to take advantage of. Is it possible to configure the parking_lot Mutex to disable the fairness guarantees?

Here's some simplified init and generic work:

let mut map: Vec<Vec<Mutex<HashSet<u64>>>> = Vec::with_capacity(WIDTH);
for i in 0..WIDTH {
  map.push(Vec::with_capacity(HEIGHT));
  for _ in 0..HEIGHT {
    map[i].push(Mutex::new(HashSet::new()));
  }
}

let mut diff: Vec<(usize, usize, u64)> = /* some code to fill this with numbers */
diff.par_iter().for_each(|(x, y, id)| {
  map[x][y].lock().insert(id);
});

At the scale I'm at this is a lot faster than the serial approach, but it's on the hot path and even half-millisecond time gains are important for my usecase.

Things I've tried: I asked my old pal ChatGPT, and it told me to try

parking_lot::lock_api::Mutex<HashSet<u64, parking_lot::RawMutex>>

However this resulted in strange errors. Looking at the docs, there is apparently some use for the lock_api, but I'm not really groking the example, nor whether or not it could help me achieve my end.


Solution

  • parking_lot doesn't have 0.5ms overhead. What parking_lot has is a guarantee that if a thread keeps locking and unlocking the same Mutex, then it will use a fair version of the unlock function on average once every 0.5ms (and every time the thread keeps the Mutex locked for more than 1ms). This fair unlock function incurs slightly more overhead than an unfair unlock but it will still be in the order of a few microseconds at most.

    Anyway, if each thread locks and releases the Mutex only once for a short time, then it will never need to use the fair unlock so it will never incur the extra overhead.