#![feature(test)] #[macro_use] extern crate chan; extern crate rand; extern crate test; use std::sync::Arc; use std::sync::mpsc; use std::thread; use rand::Rng; use test::Bencher; fn get_data() -> Vec { rand::thread_rng().gen_iter().take(1000).collect() } fn get_data_sum>(xs: I) -> u64 { xs.into_iter().fold(0, |sum, x| sum + (x as u64)) } macro_rules! bench_chan_spsc { ($name:ident, $cons:expr) => { #[bench] fn $name(b: &mut Bencher) { let data = Arc::new(get_data()); let sum = get_data_sum(data.iter().cloned()); b.bytes = data.len() as u64; b.iter(|| { let data = data.clone(); let (s, r) = $cons; thread::spawn(move || { for &datum in &*data { let _ = s.send(datum); } }); assert_eq!(sum, get_data_sum(r.iter())); }); } } } bench_chan_spsc!(spsc_chan_sync_unbuffered, chan::sync(0)); bench_chan_spsc!(spsc_chan_sync_buffered, chan::sync(1)); bench_chan_spsc!(spsc_chan_sync_buffered_all, chan::sync(1000)); bench_chan_spsc!(spsc_chan_async, chan::async()); bench_chan_spsc!(std_spsc_chan_sync_unbuffered, mpsc::sync_channel(0)); bench_chan_spsc!(std_spsc_chan_sync_buffered, mpsc::sync_channel(1)); bench_chan_spsc!(std_spsc_chan_sync_buffered_all, mpsc::sync_channel(1000)); bench_chan_spsc!(std_spsc_chan_async, mpsc::channel()); macro_rules! bench_chan_mpsc { ($name:ident, $cons:expr) => { #[bench] fn $name(b: &mut Bencher) { let data = Arc::new(get_data()); let sum = get_data_sum(data.iter().cloned()); b.bytes = data.len() as u64; b.iter(|| { let (s, r) = $cons; for i in 0..4 { let data = data.clone(); let s = s.clone(); let start = i * (data.len() / 4); let end = start + (data.len() / 4); thread::spawn(move || { for &datum in &(&*data)[start..end] { let _ = s.send(datum); } }); } drop(s); assert_eq!(sum, get_data_sum(r.iter())); }); } } } bench_chan_mpsc!(mpsc_chan_sync_unbuffered, chan::sync(0)); bench_chan_mpsc!(mpsc_chan_sync_buffered, chan::sync(1)); bench_chan_mpsc!(mpsc_chan_sync_buffered_all, chan::sync(1000)); bench_chan_mpsc!(mpsc_chan_async, chan::async()); bench_chan_mpsc!(std_mpsc_chan_sync_unbuffered, mpsc::sync_channel(0)); bench_chan_mpsc!(std_mpsc_chan_sync_buffered, mpsc::sync_channel(1)); bench_chan_mpsc!(std_mpsc_chan_sync_buffered_all, mpsc::sync_channel(1000)); bench_chan_mpsc!(std_mpsc_chan_async, mpsc::channel()); macro_rules! bench_select_no_init { ($name:ident, $cons:expr) => { #[bench] fn $name(b: &mut Bencher) { let data = Arc::new(get_data()); let sum = get_data_sum(data.iter().cloned()); b.bytes = data.len() as u64; b.iter(|| { let mut rs = vec![]; for i in 0..4 { let (s, r) = $cons; rs.push(r); let data = data.clone(); let start = i * (data.len() / 4); let end = start + (data.len() / 4); thread::spawn(move || { for &datum in &(&*data)[start..end] { let _ = s.send(datum); } }); } let mut recv = vec![]; let (r0, r1, r2, r3) = (&rs[0], &rs[1], &rs[2], &rs[3]); let mut done = &mut [false, false, false, false]; loop { chan_select! { r0.recv() -> d => { if let Some(d) = d { recv.push(d); } else { done[0] = true; } }, r1.recv() -> d => { if let Some(d) = d { recv.push(d); } else { done[1] = true; } }, r2.recv() -> d => { if let Some(d) = d { recv.push(d); } else { done[2] = true; } }, r3.recv() -> d => { if let Some(d) = d { recv.push(d); } else { done[3] = true; } }, } if done.iter().all(|&b| b) { break; } } assert_eq!(sum, get_data_sum(recv.into_iter())); }); } } } bench_select_no_init!(select_no_init_chan_sync_unbuffered, chan::sync(0)); bench_select_no_init!(select_no_init_chan_sync_buffered, chan::sync(1)); bench_select_no_init!(select_no_init_chan_sync_buffered_all, chan::sync(1000)); bench_select_no_init!(select_no_init_chan_async, chan::async()); macro_rules! bench_select_with_init { ($name:ident, $cons:expr) => { #[bench] fn $name(b: &mut Bencher) { let data = Arc::new(get_data()); let sum = get_data_sum(data.iter().cloned()); b.bytes = data.len() as u64; b.iter(|| { let mut rs = vec![]; for i in 0..4 { let (s, r) = $cons; rs.push(r); let data = data.clone(); let start = i * (data.len() / 4); let end = start + (data.len() / 4); thread::spawn(move || { for &datum in &(&*data)[start..end] { let _ = s.send(datum); } }); } let mut recv = vec![]; let (r0, r1, r2, r3) = (&rs[0], &rs[1], &rs[2], &rs[3]); let mut done = &mut [false, false, false, false]; let mut sel = chan::Select::new(); loop { chan_select! {sel, r0.recv() -> d => { if let Some(d) = d { recv.push(d); } else { done[0] = true; } }, r1.recv() -> d => { if let Some(d) = d { recv.push(d); } else { done[1] = true; } }, r2.recv() -> d => { if let Some(d) = d { recv.push(d); } else { done[2] = true; } }, r3.recv() -> d => { if let Some(d) = d { recv.push(d); } else { done[3] = true; } }, } if done.iter().all(|&b| b) { break; } } assert_eq!(sum, get_data_sum(recv.into_iter())); }); } } } bench_select_with_init!(select_with_init_chan_sync_unbuffered, chan::sync(0)); bench_select_with_init!(select_with_init_chan_sync_buffered, chan::sync(1)); bench_select_with_init!(select_with_init_chan_sync_buffered_all, chan::sync(1000)); bench_select_with_init!(select_with_init_chan_async, chan::async());