executor/distaff/benches/overhead.rs

120 lines
3.1 KiB
Rust

use distaff::{Scope, ThreadPool};
use divan::Bencher;
struct Node {
val: u64,
left: Option<Box<Node>>,
right: Option<Box<Node>>,
}
impl Node {
pub fn tree(layers: usize) -> Self {
Self {
val: 1,
left: (layers != 1).then(|| Box::new(Self::tree(layers - 1))),
right: (layers != 1).then(|| Box::new(Self::tree(layers - 1))),
}
}
}
const LAYERS: &[usize] = &[10, 24];
fn nodes() -> impl Iterator<Item = (usize, usize)> {
LAYERS.iter().map(|&l| (l, (1 << l) - 1))
}
#[divan::bench(args = nodes())]
fn no_overhead(bencher: Bencher, nodes: (usize, usize)) {
fn join_no_overhead<A, B, RA, RB>(scope: Scope<'_, '_>, a: A, b: B) -> (RA, RB)
where
A: FnOnce(Scope<'_, '_>) -> RA + Send,
B: FnOnce(Scope<'_, '_>) -> RB + Send,
RA: Send,
RB: Send,
{
(a(scope), b(scope))
}
#[inline]
fn sum(node: &Node, scope: Scope<'_, '_>) -> u64 {
let (left, right) = join_no_overhead(
scope,
|s| node.left.as_deref().map(|n| sum(n, s)).unwrap_or_default(),
|s| node.right.as_deref().map(|n| sum(n, s)).unwrap_or_default(),
);
node.val + left + right
}
let tree = Node::tree(nodes.0);
let pool = ThreadPool::global();
bencher.bench_local(move || {
pool.scope(|scope| {
assert_eq!(sum(&tree, scope), nodes.1 as u64);
});
});
}
#[divan::bench(args = nodes())]
fn distaff_overhead(bencher: Bencher, nodes: (usize, usize)) {
fn sum<'scope, 'env>(node: &Node, scope: Scope<'scope, 'env>) -> u64 {
let (left, right) = scope.join(
|s| node.left.as_deref().map(|n| sum(n, s)).unwrap_or_default(),
|s| node.right.as_deref().map(|n| sum(n, s)).unwrap_or_default(),
);
node.val + left + right
}
let tree = Node::tree(nodes.0);
let pool = ThreadPool::global();
bencher.bench_local(move || {
pool.scope(|scope| {
assert_eq!(sum(&tree, scope), nodes.1 as u64);
});
});
}
#[divan::bench(args = nodes())]
fn rayon_overhead(bencher: Bencher, nodes: (usize, usize)) {
fn sum(node: &Node) -> u64 {
let (left, right) = rayon::join(
|| node.left.as_deref().map(sum).unwrap_or_default(),
|| node.right.as_deref().map(sum).unwrap_or_default(),
);
node.val + left + right
}
let tree = Node::tree(nodes.0);
bencher.bench_local(move || {
assert_eq!(sum(&tree), nodes.1 as u64);
});
}
#[divan::bench(args = nodes())]
fn chili_overhead(bencher: Bencher, nodes: (usize, usize)) {
use chili::Scope;
fn sum(node: &Node, scope: &mut Scope<'_>) -> u64 {
let (left, right) = scope.join(
|s| node.left.as_deref().map(|n| sum(n, s)).unwrap_or_default(),
|s| node.right.as_deref().map(|n| sum(n, s)).unwrap_or_default(),
);
node.val + left + right
}
let tree = Node::tree(nodes.0);
let mut scope = Scope::global();
bencher.bench_local(move || {
assert_eq!(sum(&tree, &mut scope), nodes.1 as u64);
});
}
fn main() {
divan::main();
}