summaryrefslogtreecommitdiff
path: root/vendor/atomic-waker/benches/waker.rs
blob: 199d82dea00277f6ca7e0e942aebfdaf173bb708 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use atomic_waker::AtomicWaker;
use criterion::{black_box, criterion_group, criterion_main, BenchmarkGroup, Criterion};

use std::sync::Arc;
use std::task::{Wake, Waker};

enum Contention {
    Low,
    High,
}

impl Contention {
    fn bench<M>(
        self,
        group: &mut BenchmarkGroup<'_, M>,
        f: impl Fn(&AtomicWaker) + Send + Sync + Clone,
    ) where
        M: criterion::measurement::Measurement,
    {
        let waker = AtomicWaker::new();

        match self {
            Self::Low => {
                // Run the benchmark with low contention.
                group.bench_function("low contention", move |b| {
                    b.iter(|| {
                        for _ in 0..500 {
                            f(&waker);
                        }
                    })
                });
            }

            Self::High => {
                // Run the benchmark with high contention.
                group.bench_function("high contention", move |b| {
                    b.iter(|| {
                        use rayon::prelude::*;
                        (0..100_000).into_par_iter().for_each(|_| f(&waker));
                    })
                });
            }
        }
    }
}

fn run_lo_hi(c: &mut Criterion, name: &str, f: impl Fn(&AtomicWaker) + Send + Sync + Clone) {
    let mut group = c.benchmark_group(name);

    Contention::Low.bench(&mut group, f.clone());
    Contention::High.bench(&mut group, f);

    group.finish();
}

fn store_and_wake(c: &mut Criterion) {
    run_lo_hi(c, "store and wake", |waker| {
        let noop_waker = noop_waker();
        waker.register(&noop_waker);
        waker.wake();
    });

    run_lo_hi(c, "store and take", |waker| {
        let noop_waker = noop_waker();
        waker.register(&noop_waker);
        black_box(waker.take());
    });
}

fn wake_without_store(c: &mut Criterion) {
    run_lo_hi(c, "wake without store", |waker| {
        waker.wake();
    });

    run_lo_hi(c, "take without store", |waker| {
        black_box(waker.take());
    });
}

criterion_group!(benches, store_and_wake, wake_without_store);

criterion_main!(benches);

fn noop_waker() -> Waker {
    struct Noop;

    impl Wake for Noop {
        fn wake(self: Arc<Self>) {
            // Do nothing
        }

        fn wake_by_ref(self: &Arc<Self>) {
            // Do nothing
        }
    }

    Waker::from(Arc::new(Noop))
}