I have a Rust async server based on the Tokio runtime. It has to process a mix of latency-sensitive I/O-bound requests, and heavy CPU-bound requests.
I don't want to let the CPU-bound tasks monopolize the Tokio runtime and starve the I/O bound tasks, so I'd like to offload the CPU-bound tasks to a dedicated, isolated threadpool (isolation is the key here, so spawn_blocking
/block_in_place
on one shared threadpool are insufficient). How can I create such a threadpool in Tokio?
A naive approach of starting two runtimes runs into an error:
thread 'tokio-runtime-worker' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like
block_on
) attempted to block the current thread while the thread is being used to drive asynchronous tasks.'
use tokio; // 0.2.20
fn main() {
let mut main_runtime = tokio::runtime::Runtime::new().unwrap();
let cpu_pool = tokio::runtime::Builder::new().threaded_scheduler().build().unwrap();
let cpu_pool = cpu_pool.handle().clone(); // this is the fix/workaround!
main_runtime.block_on(main_runtime.spawn(async move {
cpu_pool.spawn(async {}).await
}))
.unwrap().unwrap();
}
Can Tokio allow two separate runtimes? Is there a better way to create an isolated CPU pool in Tokio?
block_in_place
, but it doesn't give isolation guarantee I'm looking for. – Panter