Skip to content

Q052. When should you use DashMap versus RwLock<HashMap>?

Short Answer

Use DashMap for highly concurrent, mostly independent per-key operations where sharding reduces measured contention. Use RwLock<HashMap<K, V>> when you need a simple ownership model, atomic operations across multiple entries, consistent snapshots, or explicit control over the critical section. Start with the locked HashMap for clarity and move to DashMap when workload evidence justifies it.

Deep Dive

RwLock<HashMap> exposes one obvious synchronization boundary. A write guard can validate and update several keys atomically, and a read guard can observe one consistent map state. Its weakness is global contention: an unrelated write blocks all other access.

DashMap narrows locking to shards and provides convenient entry operations. Its weakness is that its guards are easy to retain accidentally and global invariants become harder. Methods such as iteration, capacity changes, and multi-key workflows can touch several shards and have less obvious latency.

Neither choice fixes a poor key distribution or a hot key. Alternatives include partitioning maps by domain owner, actor tasks, read-copy-update structures, immutable snapshots, or a purpose-built cache.

Internal Model

RwLock<HashMap> has one lock acquisition per protected operation or transaction. DashMap hashes before acquiring a selected shard lock and may acquire several shards for whole-map operations.

Benchmark the actual ratio of reads, writes, key skew, iteration, and critical-section duration. Uniform synthetic keys often overstate sharding benefits.

Example

rust
use std::collections::HashMap;
use std::sync::RwLock;

fn main() {
    let balances = RwLock::new(HashMap::from([("alice", 100_i64), ("bob", 0)]));

    let mut map = balances.write().unwrap();
    *map.get_mut("alice").unwrap() -= 25;
    *map.get_mut("bob").unwrap() += 25;

    assert_eq!(map.values().sum::<i64>(), 100);
}

Common Mistakes

  • Selecting DashMap before identifying actual lock contention.
  • Implementing a cross-key invariant as separate DashMap operations.
  • Benchmarking only uniformly distributed point reads.

Follow-ups

  • How would you benchmark these designs under hot-key traffic?
  • Can lock striping be implemented around a normal HashMap?
  • When would immutable snapshots outperform both options?

References

  • DashMap Documentation
  • Rust Standard Library
  • The Rust Performance Book