Chinese/Telephonic whispers


Some years ago, I got interested in this problem, introduced in Go by Rob Pike (google "chinese whispers golang" to get the go version, as I can not include more that 2 links). The version quoted there still compiles and work with current go (but slower, see below).

Some Rust versions and discussions emerged :
ThornyDev: Telephonic Whispers in Rust
Chinese Whispers in Rust Based on example by Rob Pike in · GitHub

I played a bit with that (back in 2014), trying different things notably for the threads (there were several threads variants in Rust at that time IIRC).

I would like to make that work again with a recent Rust, but as I have not been able to follow evolutions for a long time, I am a bit stuck. I would be very glad to get a working version, that could be considered "state of the art with Rust 1.30" in terms of threading use, and able to work efficiently with 100000 or 200000 whispers (the go version is running in around 0.9s for 100000 on my laptop, quite longer than 0.3s given in the blog article). I remember that in my old tests, going further than 20000 or 30000 was quite hard and implied doing things like tuning stack_size.

Many thanks for any help, it will be much appreciated!



1 Like

Let me also quote these two threads which were adding lots of interesting details about the internals of Rust ; getting some updates about these in the context of 2018 (I know Rust has changed a lot in 4 years) would also interest me a lot.



Here's my take on the example: GitHub - parasyte/whispers-futures: Telephonic Whispers in Rust with Futures 0.3. See: I'm using futures-preview 0.3. "Benchmarks" are included in the README.


Here is my take at it. Unlike @parasyte's great example, I wasn't looking for performance (e.g., using a single-threaded executor), but to be as close to Go's code as possible (async/await is quite nice for that).

Rust code with async/await and M:N task scheduling (ThreadPool)

Full Rust code
//! Cargo.toml:
//! [dependencies]
//! futures = { package = "futures-preview", version = "0.3.0-alpha.16" }

// Tested with rustc 1.37.0-nightly


use ::std::*;
use ::futures::{

async fn whisper (current: Sender<u32>, next: Receiver<u32>)
    current.send(next.await.unwrap() + 1).unwrap();

fn main ()
    const N: usize = 100_000;
    let mut rt = ThreadPool::new().unwrap();
    let (current, first) = oneshot::channel();
    let last = (0 .. N).fold(current, |prev, _| {
        let (next, current) = oneshot::channel();
        rt.spawn(whisper(prev, current)).unwrap();
    rt.spawn(async { last.send(1).unwrap() }).unwrap();
1 Like