Revision control
Copy as Markdown
Other Tools
#![feature(test)]
extern crate test;
use crossbeam_channel::{bounded, unbounded};
use crossbeam_utils::thread::scope;
use test::Bencher;
const TOTAL_STEPS: usize = 40_000;
mod unbounded {
use super::*;
#[bench]
fn create(b: &mut Bencher) {
b.iter(unbounded::<i32>);
}
#[bench]
fn oneshot(b: &mut Bencher) {
b.iter(|| {
let (s, r) = unbounded::<i32>();
s.send(0).unwrap();
r.recv().unwrap();
});
}
#[bench]
fn inout(b: &mut Bencher) {
let (s, r) = unbounded::<i32>();
b.iter(|| {
s.send(0).unwrap();
r.recv().unwrap();
});
}
#[bench]
fn par_inout(b: &mut Bencher) {
let threads = num_cpus::get();
let steps = TOTAL_STEPS / threads;
let (s, r) = unbounded::<i32>();
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn spsc(b: &mut Bencher) {
let steps = TOTAL_STEPS;
let (s, r) = unbounded::<i32>();
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
b.iter(|| {
s1.send(()).unwrap();
for _ in 0..steps {
r.recv().unwrap();
}
r2.recv().unwrap();
});
drop(s1);
})
.unwrap();
}
#[bench]
fn spmc(b: &mut Bencher) {
let threads = num_cpus::get() - 1;
let steps = TOTAL_STEPS / threads;
let (s, r) = unbounded::<i32>();
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for _ in 0..steps {
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for i in 0..steps * threads {
s.send(i as i32).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn mpsc(b: &mut Bencher) {
let threads = num_cpus::get() - 1;
let steps = TOTAL_STEPS / threads;
let (s, r) = unbounded::<i32>();
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..steps * threads {
r.recv().unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn mpmc(b: &mut Bencher) {
let threads = num_cpus::get();
let steps = TOTAL_STEPS / threads;
let (s, r) = unbounded::<i32>();
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads / 2 {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
}
for _ in 0..threads / 2 {
scope.spawn(|_| {
while r1.recv().is_ok() {
for _ in 0..steps {
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
}
mod bounded_n {
use super::*;
#[bench]
fn spsc(b: &mut Bencher) {
let steps = TOTAL_STEPS;
let (s, r) = bounded::<i32>(steps);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
b.iter(|| {
s1.send(()).unwrap();
for _ in 0..steps {
r.recv().unwrap();
}
r2.recv().unwrap();
});
drop(s1);
})
.unwrap();
}
#[bench]
fn spmc(b: &mut Bencher) {
let threads = num_cpus::get() - 1;
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(steps * threads);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for _ in 0..steps {
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for i in 0..steps * threads {
s.send(i as i32).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn mpsc(b: &mut Bencher) {
let threads = num_cpus::get() - 1;
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(steps * threads);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..steps * threads {
r.recv().unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn par_inout(b: &mut Bencher) {
let threads = num_cpus::get();
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(threads);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn mpmc(b: &mut Bencher) {
let threads = num_cpus::get();
assert_eq!(threads % 2, 0);
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(steps * threads);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads / 2 {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
}
for _ in 0..threads / 2 {
scope.spawn(|_| {
while r1.recv().is_ok() {
for _ in 0..steps {
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
}
mod bounded_1 {
use super::*;
#[bench]
fn create(b: &mut Bencher) {
b.iter(|| bounded::<i32>(1));
}
#[bench]
fn oneshot(b: &mut Bencher) {
b.iter(|| {
let (s, r) = bounded::<i32>(1);
s.send(0).unwrap();
r.recv().unwrap();
});
}
#[bench]
fn spsc(b: &mut Bencher) {
let steps = TOTAL_STEPS;
let (s, r) = bounded::<i32>(1);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
b.iter(|| {
s1.send(()).unwrap();
for _ in 0..steps {
r.recv().unwrap();
}
r2.recv().unwrap();
});
drop(s1);
})
.unwrap();
}
#[bench]
fn spmc(b: &mut Bencher) {
let threads = num_cpus::get() - 1;
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(1);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for _ in 0..steps {
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for i in 0..steps * threads {
s.send(i as i32).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn mpsc(b: &mut Bencher) {
let threads = num_cpus::get() - 1;
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(1);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..steps * threads {
r.recv().unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn mpmc(b: &mut Bencher) {
let threads = num_cpus::get();
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(1);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads / 2 {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
}
for _ in 0..threads / 2 {
scope.spawn(|_| {
while r1.recv().is_ok() {
for _ in 0..steps {
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
}
mod bounded_0 {
use super::*;
#[bench]
fn create(b: &mut Bencher) {
b.iter(|| bounded::<i32>(0));
}
#[bench]
fn spsc(b: &mut Bencher) {
let steps = TOTAL_STEPS;
let (s, r) = bounded::<i32>(0);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
b.iter(|| {
s1.send(()).unwrap();
for _ in 0..steps {
r.recv().unwrap();
}
r2.recv().unwrap();
});
drop(s1);
})
.unwrap();
}
#[bench]
fn spmc(b: &mut Bencher) {
let threads = num_cpus::get() - 1;
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(0);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for _ in 0..steps {
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for i in 0..steps * threads {
s.send(i as i32).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn mpsc(b: &mut Bencher) {
let threads = num_cpus::get() - 1;
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(0);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..steps * threads {
r.recv().unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
#[bench]
fn mpmc(b: &mut Bencher) {
let threads = num_cpus::get();
let steps = TOTAL_STEPS / threads;
let (s, r) = bounded::<i32>(0);
let (s1, r1) = bounded(0);
let (s2, r2) = bounded(0);
scope(|scope| {
for _ in 0..threads / 2 {
scope.spawn(|_| {
while r1.recv().is_ok() {
for i in 0..steps {
s.send(i as i32).unwrap();
}
s2.send(()).unwrap();
}
});
}
for _ in 0..threads / 2 {
scope.spawn(|_| {
while r1.recv().is_ok() {
for _ in 0..steps {
r.recv().unwrap();
}
s2.send(()).unwrap();
}
});
}
b.iter(|| {
for _ in 0..threads {
s1.send(()).unwrap();
}
for _ in 0..threads {
r2.recv().unwrap();
}
});
drop(s1);
})
.unwrap();
}
}