Skip to main content

concurrent_counters/
concurrent_counters.rs

1use micromeasure::{
2    ConcurrentBenchContext, ConcurrentBenchControl, ConcurrentWorker, ConcurrentWorkerResult,
3    benchmark_main, black_box,
4};
5use std::sync::RwLock;
6use std::time::Duration;
7
8#[derive(Default)]
9struct CounterLatch {
10    value: RwLock<u64>,
11}
12
13impl ConcurrentBenchContext for CounterLatch {
14    fn prepare(_num_threads: usize) -> Self {
15        Self::default()
16    }
17}
18
19fn optimistic_reader(
20    ctx: &CounterLatch,
21    control: &ConcurrentBenchControl,
22) -> ConcurrentWorkerResult {
23    let mut operations = 0_u64;
24    let mut read_misses = 0_u64;
25
26    while !control.should_stop() {
27        if let Ok(guard) = ctx.value.try_read() {
28            black_box(*guard ^ control.thread_index() as u64 ^ control.role_thread_index() as u64);
29            operations = operations.wrapping_add(1);
30        } else {
31            read_misses = read_misses.wrapping_add(1);
32        }
33    }
34
35    ConcurrentWorkerResult::operations(operations).with_counter("read_misses", read_misses)
36}
37
38fn exclusive_writer(
39    ctx: &CounterLatch,
40    control: &ConcurrentBenchControl,
41) -> ConcurrentWorkerResult {
42    let mut operations = 0_u64;
43
44    while !control.should_stop() {
45        let mut guard = ctx.value.write().expect("rwlock poisoned");
46        *guard = guard.wrapping_add(control.thread_index() as u64 + 1);
47        black_box(*guard);
48        operations = operations.wrapping_add(1);
49    }
50
51    ConcurrentWorkerResult::operations(operations)
52}
53
54benchmark_main!(|runner| {
55    let workers = [
56        ConcurrentWorker {
57            name: "optimistic_reader",
58            threads: 3,
59            run: optimistic_reader,
60        },
61        ConcurrentWorker {
62            name: "exclusive_writer",
63            threads: 1,
64            run: exclusive_writer,
65        },
66    ];
67
68    runner.concurrent_group::<CounterLatch>("Contention", |g| {
69        g.bench(
70            "rwlock_readers_vs_writer_with_counters",
71            Duration::from_millis(50),
72            &workers,
73        );
74    });
75});