Live data from Hacker News

Read Locks Are Not Your Friends

eventual-consistency.vercel.app

21–24 of 24 posts

Re: Read Locks Are Not Your Friends

#21
post #8

This is drawing broad conclusions from a specific RW mutex implementation. Other implementations adopt techniques to make the readers scale linearly in the read-mostly case by using per-core state (the drawback is that write locks need to scan it). One example is folly::SharedMutex, which is very battle-tested: https://uvdn7.github.io/shared-mutex/ There are more sophisticated techniques such as RCU or hazard pointer…

Wow, folly::SharedMutex is quite an example of design tradeoffs. I wonder what application the authors wanted it for where using a global array was better than a per-mutex array.

Re: Read Locks Are Not Your Friends

#22
Lock contention is a real issue for any multi-threaded system, and while a RW mutex is useful when you have a longer executing critical section, for something very short lived there is still a cache coordination cost. In many of the HashiCorp applications, we work around this by using an immutable radix tree design instead [1].

Instead of a RW mutex, you have a single writer lock. Any writer acquires the lock, makes changes, and generates a new root pointer to the tree (any update operation generates a new root, because the tree is immutable). Then we do an atomic swap from the old root to the new root. Any readers do an atomic read of the current point in time root, and perform their read operations lock free. This is safe because the tree is immutable, so readers don't need to be concerned with another thread modifying the tree concurrently, any modifications will create a new tree. This is a pattern we've standardized with a library we call MemDB [2].

This has the advantage of making reads multi-core scalable with much lower lock contention. Given we typically use Raft for distributed consensus, you only have a single writer anyways (e.g. the FSM commit thread is the only writer).

We apply this pattern to Vault, Consul, and Nomad all of which are able to scale to many dozens of cores, with largely a linear speedup in read performance.

[1] https://github.com/hashicorp/go-immutable-radix [2] https://github.com/hashicorp/go-memdb

Re: Read Locks Are Not Your Friends

#24
post #22

Lock contention is a real issue for any multi-threaded system, and while a RW mutex is useful when you have a longer executing critical section, for something very short lived there is still a cache coordination cost. In many of the HashiCorp applications, we work around this by using an immutable radix tree design instead [1]. Instead of a RW mutex, you have a single writer lock. Any writer acquires the lock, makes…

You need a way to cleanup after that though. Either GC or, for non-GC languages, some deferred reclamation method like hazard pointers or RCU.
Post reply on HN