1 #[macro_use]
2 extern crate criterion;
3
4 use criterion::{Criterion, Bencher, black_box};
5 use std::{
6 ops::DerefMut,
7 sync::Arc,
8 };
9
10 trait Mutex<T>: Send + Sync + 'static {
11 type Guard<'a>: DerefMut<Target = T> where Self: 'a;
new(x: T) -> Self12 fn new(x: T) -> Self;
lock(&self) -> Self::Guard<'_>13 fn lock(&self) -> Self::Guard<'_>;
14 }
15
16 impl<T: Send + 'static> Mutex<T> for spin::mutex::SpinMutex<T> {
17 type Guard<'a> = spin::mutex::SpinMutexGuard<'a, T> where Self: 'a;
new(x: T) -> Self18 fn new(x: T) -> Self { spin::mutex::SpinMutex::new(x) }
lock(&self) -> Self::Guard<'_>19 fn lock(&self) -> Self::Guard<'_> { self.lock() }
20 }
21
22 impl<T: Send + 'static> Mutex<T> for spin::mutex::TicketMutex<T> {
23 type Guard<'a> = spin::mutex::TicketMutexGuard<'a, T> where Self: 'a;
new(x: T) -> Self24 fn new(x: T) -> Self { spin::mutex::TicketMutex::new(x) }
lock(&self) -> Self::Guard<'_>25 fn lock(&self) -> Self::Guard<'_> { self.lock() }
26 }
27
28 impl<T: Send + 'static> Mutex<T> for std::sync::Mutex<T> {
29 type Guard<'a> = std::sync::MutexGuard<'a, T> where Self: 'a;
new(x: T) -> Self30 fn new(x: T) -> Self { std::sync::Mutex::new(x) }
lock(&self) -> Self::Guard<'_>31 fn lock(&self) -> Self::Guard<'_> { self.lock().unwrap() }
32 }
33
gen_create<M: Mutex<u32>>(b: &mut Bencher)34 fn gen_create<M: Mutex<u32>>(b: &mut Bencher) {
35 b.iter(|| {
36 let n = black_box(42);
37 M::new(n)
38 });
39 }
40
gen_lock_unlock<M: Mutex<u32>>(b: &mut Bencher)41 fn gen_lock_unlock<M: Mutex<u32>>(b: &mut Bencher) {
42 let m = M::new(0);
43 b.iter(|| {
44 let mut m = m.lock();
45 *m = m.wrapping_add(1);
46 drop(m);
47 });
48 }
49
gen_lock_unlock_read_contention<M: Mutex<u32>>(b: &mut Bencher)50 fn gen_lock_unlock_read_contention<M: Mutex<u32>>(b: &mut Bencher) {
51 let m = Arc::new(M::new(0));
52 let thread = std::thread::spawn({
53 let m = m.clone();
54 move || {
55 while Arc::strong_count(&m) > 1 {
56 for _ in 0..1000 {
57 black_box(*m.lock());
58 }
59 }
60 }
61 });
62 b.iter(|| {
63 let mut m = m.lock();
64 *m = m.wrapping_add(1);
65 drop(m);
66 });
67 drop(m);
68 thread.join().unwrap();
69 }
70
gen_lock_unlock_write_contention<M: Mutex<u32>>(b: &mut Bencher)71 fn gen_lock_unlock_write_contention<M: Mutex<u32>>(b: &mut Bencher) {
72 let m = Arc::new(M::new(0));
73 let thread = std::thread::spawn({
74 let m = m.clone();
75 move || {
76 while Arc::strong_count(&m) > 1 {
77 for _ in 0..1000 {
78 let mut m = m.lock();
79 *m = m.wrapping_add(1);
80 drop(m);
81 }
82 }
83 }
84 });
85 b.iter(|| {
86 let mut m = m.lock();
87 *m = m.wrapping_add(1);
88 drop(m);
89 });
90 drop(m);
91 thread.join().unwrap();
92 }
93
create(b: &mut Criterion)94 fn create(b: &mut Criterion) {
95 b.bench_function("create-spin-spinmutex", |b| gen_create::<spin::mutex::SpinMutex<u32>>(b));
96 b.bench_function("create-spin-ticketmutex", |b| gen_create::<spin::mutex::TicketMutex<u32>>(b));
97 b.bench_function("create-std", |b| gen_create::<std::sync::Mutex<u32>>(b));
98 }
99
lock_unlock(b: &mut Criterion)100 fn lock_unlock(b: &mut Criterion) {
101 b.bench_function("lock_unlock-spin-spinmutex", |b| gen_lock_unlock::<spin::mutex::SpinMutex<u32>>(b));
102 b.bench_function("lock_unlock-spin-ticketmutex", |b| gen_lock_unlock::<spin::mutex::TicketMutex<u32>>(b));
103 b.bench_function("lock_unlock-std", |b| gen_lock_unlock::<std::sync::Mutex<u32>>(b));
104 }
105
lock_unlock_read_contention(b: &mut Criterion)106 fn lock_unlock_read_contention(b: &mut Criterion) {
107 b.bench_function("lock_unlock_read_contention-spin-spinmutex", |b| gen_lock_unlock_read_contention::<spin::mutex::SpinMutex<u32>>(b));
108 b.bench_function("lock_unlock_read_contention-spin-ticketmutex", |b| gen_lock_unlock_read_contention::<spin::mutex::TicketMutex<u32>>(b));
109 b.bench_function("lock_unlock_read_contention-std", |b| gen_lock_unlock_read_contention::<std::sync::Mutex<u32>>(b));
110 }
111
lock_unlock_write_contention(b: &mut Criterion)112 fn lock_unlock_write_contention(b: &mut Criterion) {
113 b.bench_function("lock_unlock_write_contention-spin-spinmutex", |b| gen_lock_unlock_write_contention::<spin::mutex::SpinMutex<u32>>(b));
114 b.bench_function("lock_unlock_write_contention-spin-ticketmutex", |b| gen_lock_unlock_write_contention::<spin::mutex::TicketMutex<u32>>(b));
115 b.bench_function("lock_unlock_write_contention-std", |b| gen_lock_unlock_write_contention::<std::sync::Mutex<u32>>(b));
116 }
117
118 criterion_group!(
119 mutex,
120 create,
121 lock_unlock,
122 lock_unlock_read_contention,
123 lock_unlock_write_contention,
124 );
125
126 criterion_main!(mutex);
127