Introducing the "Sync" shard

With the MT refactor, it became more and more clear that we need more primitives to write safer, and faster, concurrent and parallel programs in Crystal, beyond the Channel, Mutex and the recent WaitGroup from stdlib

A couple weeks ago I started experimenting with synchronization primitives for Crystal, and I just pushed a new shard: sync.

The shard is meant to design, evolve, test and refine the API, until we believe that they’re sound, and maybe consider to push them to stdlib. The shard allows to use the primitives today in your apps, so we can get feedback from real apps.

The shard provides these basic types:

  • Sync::Semaphore
  • Sync::Mutex (see below for why)
  • Sync::RWLock
  • Sync::ConditionVariable

It also features wrapping types, to wrap a global variable with a mutex or rwlock:

  • Sync::Exclusive(T)
  • Sync::Shared(T).

Finally, it features one high level data structure:

  • Sync::Map(K, V) —inspired by the dashmap Rust crate

Last but not least: they’re not just safe, they’re fast!

I ported the nsync algorithms for mutexes, rwlocks and condition variables (see The Fastest Mutexes) and that led to writing a very efficient alternative to Mutex from stdlib (see the charts in README).

Sync::Map(K, V) requires quite some memory, but its performance skyrockets compared to a Hash protected by a single Sync::RWLock.

19 Likes

Neat. Are there any reasons not to push the mutex to stdlib to replace the current one? I imagine it would be pretty nice inside channels, for example.

Aside on channels: I don’t know if anyone else has noticed it, but if we managed to replace the size-limited buffer of channels with a lockfree variant with the same size restriction and reasonably similar api, then the lock could be split into two, one for protecting the reader underflow backlog and one for protecting the writer overflow backlog. In very many cases it would totally eliminate contention except for the lock-free part.

1 Like

As for everything in the shard, the mutex is meant to move to stdlib. I’m also planning to make a thread version to replace the slow pthread mutexes (and condvar). I’d still like to get some real feedback on whether the port is sound :sweat_smile:

Though I’m not sure whether we want a Mutex + RWLock or just a single Lock type that does both?

1 Like