tokio-core: Possibly slow channel
Hi, I was playing around with tokio and implemented my goto benchmark for any kind of async distributed language: Pass a number around a ring of threads and see how how fast it is. In erlang with ring of 100 threads I get can pass the number around +/- 250K times a second. Below is an attempt to implement the same with Tokio channels but I thought the numbers are a bit low. Its possible I have not used you library properly or there is some hidden lock somewhere as my CPU hardly goes above 180% no matter how few/many threads I spawn. It takes about 14 seconds to send the number around a loop of 2 threads 1000000 times or around 77k sec.
Again I won’t be surprised if I have done something wrong. Here is the code snippet:
extern crate futures;
extern crate tokio_core;
use tokio_core::{Sender, Receiver};
use tokio_core::io::IoFuture;
use futures::stream::Stream;
use futures::{Future,finished};
use std::thread::spawn;
use std::io;
fn spawn_aux(trx: Sender<u32>, rx: IoFuture<Receiver<u32>>) {
spawn(move || {
let mut aux_loop = tokio_core::Loop::new().unwrap();
let future = rx.and_then(|s| {
s.for_each(|num| {
trx.send(num + 1)
})
});
aux_loop.run(future)
});
}
fn main() {
let mut main_loop = tokio_core::Loop::new().unwrap();
let (first_trx, mut last_rx) = main_loop.handle().channel::<u32>();
for _ in 1..2 {
let (next_trx, rx2) = main_loop.handle().channel::<u32>();
spawn_aux(next_trx, last_rx);
last_rx = rx2
}
first_trx.send(0).unwrap();
let future = last_rx.and_then(|s| {
s.take(1_000_000)
.fold(0, |_, num|{
let num = num + 1;
first_trx.send(num).unwrap();
finished::<u32, io::Error>(num)
})
});
let res = main_loop.run(future).unwrap();
println!("res {}", res);
}
available here: https://github.com/josephDunne/ring_test.git
I am really excited for this project going forward!
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 29 (8 by maintainers)
gettime()is called for timeout handling: https://github.com/tokio-rs/tokio-core/blob/master/src/reactor/mod.rs#L229I don’t necessarily trust it, but
perfreports that these instructions take60%of the_runfunction:It looks like a linked list, but because of inlining I’m not sure where the code comes from. Could it be the timer wheel? But there’s no timer wheel in the git version. Turns out your
Cargo.lockreferencestokio-core 0.1.0and the code doesn’t build any more due to API changes and I’m not sure how to port theReceiverpart.On the other hand,
tokio-coreis usingepoll. I would expect other implementations to avoid the system calls, but that’s probably not possible withtokio.perf recordoutput (above1%):