This is a very clever architecture. We use a similar approach in Rspack by running CPU-bound tasks directly on Tokio. We don’t even need a separate I/O runtime, because the priority in compiler workloads is maximizing CPU utilization, not minimizing I/O latency.
One of the reasons we chose Tokio over Rayon is that Rspack exposes a large number of JavaScript hooks. These hooks are asynchronous and are frequently interleaved with CPU-bound work, so keeping everything on the same runtime greatly simplifies the execution model.
The discussion in is excellent. I’d also love to see Tokio provide more Rayon-like APIs (such as par_iter) to make scheduling CPU-bound workloads more ergonomic.