I released ComposableThreads (Rust edition) — a library for working with what are commonly called user-level threads in Rust.

https://github.com/endowataru/cmpth-rs

This was also my first time publishing a package to crates.io.

https://crates.io/crates/cmpth

ComposableThreads originally started as a C++ library I wrote during my PhD. I built it on the side while working on Distributed Shared Memory (DSM) for HPC — the main theme of my doctoral dissertation. When you try to build a DSM system, multithreading becomes deeply involved on both the application and system sides.

The lab I belonged to as a student, Taura Lab, had been developing MassiveThreads for many years. It’s a well-known and easy-to-use library in the community: it executes Cilk-style fork/join programs at high speed while providing a full set of features as a stackful user-level thread library. The obvious approach would have been to just use MassiveThreads, but when building something unusual like a DSM library, MassiveThreads alone wasn’t flexible enough to customize. So I decided to build a library that would match MassiveThreads in performance while also being highly customizable for prototyping various system libraries — and that became ComposableThreads. It started out as a side product of the DSM work, but it ended up becoming a paper and is probably the best thing I built during my PhD years.

Recently I found some free time, and coding with AI has become much easier, so I finally tackled something I had wanted to do for a while: porting ComposableThreads to Rust. The core ideas are the same as the C++ version: implementing stackful threads end-to-end, making one-shot continuations (suspended threads) first-class objects, allowing users to swap out components via generics, and matching MassiveThreads in performance. I also added Waker support since async/await is common in Rust. This does introduce some branching overhead, so I think that should be made swappable as well.

When putting together benchmarks, I looked for other Rust libraries doing similar things and was surprised to find not many. Tokio is the well-known thread library, but it seems primarily focused on fast I/O and doesn’t feel well-suited to HPC workloads. The best performer I found was rayon, though rayon is specialized for data parallelism — it doesn’t implement stackful threads and doesn’t have things like mutexes or yield.

The graph above shows execution times for ComposableThreads, MassiveThreads, and rayon measured on my MacBook Pro. For some reason MassiveThreads didn’t perform as well as I expected in my environment — I haven’t been able to investigate in detail, but since the machines in the lab during my time there were almost entirely x86-64, it may not be well-optimized for ARM64. rayon’s task creation was quite fast at around 10 ns per spawn/join pair. That said, keep in mind that rayon is implementing something fundamentally different. ComposableThreads looks slower compared to rayon, but at around 50 ns per spawn/join pair, I think the overhead for making it work as a proper user-level thread library is reasonably trimmed. That said, a lot of the code was written primarily by AI and I haven’t gotten to the point of studying the assembly, so there may be more room to tune toward the limits.

Going forward, I’d like to measure on a machine with a proper core count, clean up the interface to mature it as a library, and generally tinker with it whenever I find the time.