1 //! These are very minimal benchmarks ‒ reading and writing an integer shared in
2 //! different ways. You can compare the times and see the characteristics.
3 
4 use std::io::{self, Write};
5 use std::sync::{Arc, Mutex, RwLock};
6 use std::time::Instant;
7 
8 use arc_swap::ArcSwap;
9 use criterion::black_box;
10 use crossbeam_utils::thread;
11 
test_run<R, W>( name: &str, read_threads: usize, write_threads: usize, iterations: usize, r: R, w: W, ) where R: Fn() -> usize + Sync + Send, W: Fn(usize) + Sync + Send,12 fn test_run<R, W>(
13     name: &str,
14     read_threads: usize,
15     write_threads: usize,
16     iterations: usize,
17     r: R,
18     w: W,
19 ) where
20     R: Fn() -> usize + Sync + Send,
21     W: Fn(usize) + Sync + Send,
22 {
23     print!(
24         "{:20} ({} + {}) x {}: ",
25         name, read_threads, write_threads, iterations
26     );
27     io::stdout().flush().unwrap();
28     let before = Instant::now();
29     thread::scope(|scope| {
30         for _ in 0..read_threads {
31             scope.spawn(|_| {
32                 for _ in 0..iterations {
33                     black_box(r());
34                 }
35             });
36         }
37         for _ in 0..write_threads {
38             scope.spawn(|_| {
39                 for i in 0..iterations {
40                     black_box(w(i));
41                 }
42             });
43         }
44     })
45     .unwrap();
46     let duration = Instant::now() - before;
47     println!(
48         "{:03}.{:03}s",
49         duration.as_secs(),
50         duration.subsec_nanos() / 100_000
51     );
52 }
53 
test_round<R, W>(name: &str, iterations: usize, r: R, w: W) where R: Fn() -> usize + Sync + Send, W: Fn(usize) + Sync + Send,54 fn test_round<R, W>(name: &str, iterations: usize, r: R, w: W)
55 where
56     R: Fn() -> usize + Sync + Send,
57     W: Fn(usize) + Sync + Send,
58 {
59     test_run(name, 1, 0, iterations, &r, &w);
60     test_run(name, 2, 0, iterations, &r, &w);
61     test_run(name, 4, 0, iterations, &r, &w);
62     test_run(name, 8, 0, iterations, &r, &w);
63     test_run(name, 1, 1, iterations, &r, &w);
64     test_run(name, 4, 1, iterations, &r, &w);
65     test_run(name, 4, 2, iterations, &r, &w);
66     test_run(name, 4, 4, iterations, &r, &w);
67     test_run(name, 8, 1, iterations, &r, &w);
68     test_run(name, 8, 2, iterations, &r, &w);
69     test_run(name, 8, 4, iterations, &r, &w);
70     test_run(name, 0, 1, iterations, &r, &w);
71     test_run(name, 0, 4, iterations, &r, &w);
72 }
73 
main()74 fn main() {
75     let mutex = Mutex::new(42);
76     test_round(
77         "mutex",
78         100_000,
79         || *mutex.lock().unwrap(),
80         |i| *mutex.lock().unwrap() = i,
81     );
82     let mutex = Mutex::new(Arc::new(42));
83     test_round(
84         "mutex-arc",
85         100_000,
86         || **mutex.lock().unwrap(),
87         |i| *mutex.lock().unwrap() = Arc::new(i),
88     );
89     test_round(
90         "mutex-arc-clone",
91         100_000,
92         || *Arc::clone(&*mutex.lock().unwrap()),
93         |i| *mutex.lock().unwrap() = Arc::new(i),
94     );
95     let lock = RwLock::new(42);
96     test_round(
97         "rw",
98         100_000,
99         || *lock.read().unwrap(),
100         |i| *lock.write().unwrap() = i,
101     );
102     let lock = RwLock::new(Arc::new(42));
103     test_round(
104         "rw-arc",
105         100_000,
106         || **lock.read().unwrap(),
107         |i| *lock.write().unwrap() = Arc::new(i),
108     );
109     test_round(
110         "rw-arc-clone",
111         100_000,
112         || *Arc::clone(&*lock.read().unwrap()),
113         |i| *lock.write().unwrap() = Arc::new(i),
114     );
115     let arc = ArcSwap::from(Arc::new(42));
116     test_round(
117         "arc-load-store",
118         100_000,
119         || **arc.load(),
120         |i| arc.store(Arc::new(i)),
121     );
122     test_round(
123         "arc-rcu",
124         100_000,
125         || *arc.load_full(),
126         |i| {
127             arc.rcu(|_| Arc::new(i));
128         },
129     );
130 }
131