use dial9::{DiskBuffer, RecorderTokioExt, TokioAttachOptions, recorder};
use std::time::Duration;
fn main() -> std::io::Result<()> {
let trace_dir = "/tmp/multi_runtime";
let _ = std::fs::create_dir_all(trace_dir);
let writer = DiskBuffer::builder()
.base_path(trace_dir)
.max_file_size(1024 * 1024)
.max_total_size(5 * 1024 * 1024)
.build()?;
let recorder = recorder(writer).build();
let (recorder, main_rt) = recorder.attach_tokio_runtime_with(
TokioAttachOptions::builder().runtime_name("main").build(),
|t| {
t.worker_threads(2);
},
)?;
let (recorder, io_rt) = recorder.attach_tokio_runtime_with(
TokioAttachOptions::builder().runtime_name("io").build(),
|t| {
t.worker_threads(2);
},
)?;
println!("Running workload on two named runtimes...");
let io_handle = io_rt.handle().clone();
main_rt.block_on(async move {
let mut requests = Vec::new();
for i in 0..20 {
let io = io_handle.clone();
requests.push(dial9::spawn(async move {
tokio::task::yield_now().await;
tokio::time::sleep(Duration::from_millis(5)).await;
println!(" [main] request {i} handled");
dial9::spawn_in(&io, async move {
tokio::time::sleep(Duration::from_millis(10)).await;
println!(" [io] request {i} flushed");
})
.await
.unwrap();
}));
}
for request in requests {
request.await.unwrap();
}
});
println!("All tasks completed.");
drop(io_rt);
drop(main_rt);
recorder.graceful_shutdown(Duration::from_secs(5));
println!("\nTrace files in {trace_dir}/:");
for entry in std::fs::read_dir(trace_dir)? {
let entry = entry?;
let meta = entry.metadata()?;
println!(
" {} ({} bytes)",
entry.file_name().to_string_lossy(),
meta.len()
);
}
println!("\nThe trace viewer will show workers grouped by runtime name (main / io).");
Ok(())
}