use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rayon::prelude::*;
fn par_channel(c: &mut Criterion) {
c.bench_function("par_channel/rayon", |b| {
b.iter(|| {
let channels: Vec<_> = (0..250_000)
.into_par_iter()
.map(|_| tokio::sync::oneshot::channel::<u64>())
.collect();
black_box(channels);
})
});
c.bench_function("par_channel/seq", |b| {
use tokio::sync::oneshot::{Receiver, Sender};
b.iter(|| {
let channels: Vec<(Sender<_>, Receiver<_>)> = (0..250_000)
.map(|_| tokio::sync::oneshot::channel::<u64>())
.collect();
black_box(channels);
})
});
}
fn par_spawn(c: &mut Criterion) {
c.bench_function("par_spawn/rayon", |b| {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
b.iter(|| {
let channels: Vec<_> = (0..250_000)
.into_par_iter()
.map(|_| rt.spawn(async move { black_box(5) }))
.collect();
black_box(channels);
})
});
c.bench_function("par_spawn/seq", |b| {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
b.iter(|| {
let channels: Vec<_> = (0..250_000)
.map(|_| rt.spawn(async move { black_box(5) }))
.collect();
black_box(channels);
})
});
}
criterion_group!(par, par_channel, par_spawn);
fn prim_arc(c: &mut Criterion) {
use std::sync::Arc;
struct Session(u64);
c.bench_function("prim_arc_direct", |b| {
fn f(_s: &Session) -> u64 {
3
}
let s = Session(5);
b.iter(|| {
black_box(f(&s));
})
});
c.bench_function("prim_arc_none", |b| {
fn f() -> u64 {
3
}
let _a = Arc::new(Session(5));
b.iter(|| {
black_box(f());
})
});
c.bench_function("prim_arc_clone", |b| {
fn f(_x: Arc<Session>) -> u64 {
3
}
let a = Arc::new(Session(5));
b.iter(|| {
black_box(f(a.clone()));
})
});
c.bench_function("prim_arc_ref", |b| {
fn f(_x: &Arc<Session>) -> u64 {
3
}
let a = Arc::new(Session(5));
b.iter(|| {
black_box(f(&a));
})
});
c.bench_function("prim_arc_ref_clone", |b| {
fn f(x: &Arc<Session>) -> u64 {
let _x = x.clone();
3
}
let a = Arc::new(Session(5));
b.iter(|| {
black_box(f(&a));
})
});
}
fn prim_closure(c: &mut Criterion) {
use std::sync::Arc;
c.bench_function("prim_closure_symbol", |b| {
fn f() -> u64 {
3
}
b.iter(|| {
black_box(f());
})
});
c.bench_function("prim_closure_fn", |b| {
let f = || 3;
b.iter(|| {
black_box(f());
})
});
c.bench_function("prim_closure_ArcFnUntyped", |b| {
let x = 3;
let f: Arc<_> = Arc::new(move || x);
b.iter(|| {
black_box(f());
})
});
c.bench_function("prim_closure_BoxFnUntyped", |b| {
let x = 3;
let f: Box<_> = Box::new(move || x);
b.iter(|| {
black_box(f());
})
});
c.bench_function("prim_closure_ArcFnTyped", |b| {
let x = 3;
let f: Arc<dyn Fn() -> u64> = Arc::new(move || x);
b.iter(|| {
black_box(f());
})
});
c.bench_function("prim_closure_BoxFnTyped", |b| {
let x = 3;
let f: Box<dyn Fn() -> u64> = Box::new(move || x);
b.iter(|| {
black_box(f());
})
});
pub enum Kernel {
Function(fn() -> u64),
ArcClosure(Arc<dyn Fn() -> u64>),
BoxClosure(Box<dyn Fn() -> u64>),
}
impl Kernel {
fn apply(&self) -> u64 {
match self {
Kernel::Function(f) => f(),
Kernel::ArcClosure(f) => f(),
Kernel::BoxClosure(f) => f(),
}
}
}
c.bench_function("prim_closure_enum_symbol", |b| {
fn f() -> u64 {
3
}
let k = Kernel::Function(f);
b.iter(|| {
black_box(k.apply());
})
});
c.bench_function("prim_closure_enum_fn", |b| {
let f = || 3;
let k = Kernel::Function(f);
b.iter(|| {
black_box(k.apply());
})
});
c.bench_function("prim_closure_enum_ArcFnUntyped", |b| {
let x = 3;
let f: Arc<_> = Arc::new(move || x);
let k = Kernel::ArcClosure(f);
b.iter(|| {
black_box(k.apply());
})
});
c.bench_function("prim_closure_enum_BoxFnUntyped", |b| {
let x = 3;
let f: Box<_> = Box::new(move || x);
let k = Kernel::BoxClosure(f);
b.iter(|| {
black_box(k.apply());
})
});
c.bench_function("prim_closure_enum_ArcFnTyped", |b| {
let x = 3;
let f: Arc<dyn Fn() -> u64> = Arc::new(move || x);
let k = Kernel::ArcClosure(f);
b.iter(|| {
black_box(k.apply());
})
});
c.bench_function("prim_closure_enum_BoxFnTyped", |b| {
let x = 3;
let f: Box<dyn Fn() -> u64> = Box::new(move || x);
let k = Kernel::BoxClosure(f);
b.iter(|| {
black_box(k.apply());
})
});
}
fn prim_capture(c: &mut Criterion) {
trait Compile<F: Fn(u64) -> u64> {
fn compile(&self) -> F;
}
c.bench_function("prim_capture_symbol_outer", |b| {
struct K;
impl Compile<fn(u64) -> u64> for K {
fn compile(&self) -> fn(u64) -> u64 {
|x| x + 3
}
}
let k = K;
let f = k.compile();
b.iter(|| {
black_box(f(5));
})
});
c.bench_function("prim_capture_symbol_inner", |b| {
struct K;
impl Compile<fn(u64) -> u64> for K {
fn compile(&self) -> fn(u64) -> u64 {
|x| x + 3
}
}
let k = K;
b.iter(|| {
let f = k.compile();
black_box(f(5));
})
});
c.bench_function("prim_capture_Box_outer", |b| {
struct K;
impl Compile<Box<dyn Fn(u64) -> u64>> for K {
fn compile(&self) -> Box<dyn Fn(u64) -> u64> {
Box::new(|x| x + 3)
}
}
let k = K;
let f = k.compile();
b.iter(|| {
black_box(f(5));
})
});
c.bench_function("prim_capture_Box_inner", |b| {
struct K;
impl Compile<Box<dyn Fn(u64) -> u64>> for K {
fn compile(&self) -> Box<dyn Fn(u64) -> u64> {
Box::new(|x| x + 3)
}
}
let k = K;
b.iter(|| {
let f = k.compile();
black_box(f(5));
})
});
c.bench_function("prim_capture_Box_move_empty_outer", |b| {
struct K;
impl Compile<Box<dyn Fn(u64) -> u64>> for K {
fn compile(&self) -> Box<dyn Fn(u64) -> u64> {
Box::new(move |x| x + 3)
}
}
let k = K;
let f = k.compile();
b.iter(|| {
black_box(f(5));
})
});
c.bench_function("prim_capture_Box_move_empty_inner", |b| {
struct K;
impl Compile<Box<dyn Fn(u64) -> u64>> for K {
fn compile(&self) -> Box<dyn Fn(u64) -> u64> {
Box::new(move |x| x + 3)
}
}
let k = K;
b.iter(|| {
let f = k.compile();
black_box(f(5));
})
});
c.bench_function("prim_capture_Box_move_nonempty_outer", |b| {
struct K;
impl Compile<Box<dyn Fn(u64) -> u64>> for K {
fn compile(&self) -> Box<dyn Fn(u64) -> u64> {
let c = 3;
Box::new(move |x| x + c)
}
}
let k = K;
let f = k.compile();
b.iter(|| {
black_box(f(5));
})
});
c.bench_function("prim_capture_Box_move_nonempty_inner", |b| {
struct K;
impl Compile<Box<dyn Fn(u64) -> u64>> for K {
fn compile(&self) -> Box<dyn Fn(u64) -> u64> {
let c = 3;
Box::new(move |x| x + c)
}
}
let k = K;
b.iter(|| {
let f = k.compile();
black_box(f(5));
})
});
}
criterion_group!(prim, prim_arc, prim_closure, prim_capture);
criterion_main!(par, prim);