Skip to content

Commit 3591c10

Browse files
committed
Mutex performance benchmarks
Signed-off-by: Gary Guo <gary@garyguo.net>
1 parent ec23632 commit 3591c10

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

benches/mutex.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#![feature(test)]
2+
3+
extern crate test;
4+
5+
use async_std::task;
6+
use test::Bencher;
7+
8+
use async_std::sync::{Arc, Mutex};
9+
10+
use async_std::future::Future;
11+
12+
async fn test(task: usize, iter: usize) {
13+
let mutex = Arc::new(Mutex::new(()));
14+
let mut vec = Vec::new();
15+
for _ in 0..task {
16+
let mutex_clone = mutex.clone();
17+
let handle = async_std::task::spawn(async move {
18+
for _ in 0..iter {
19+
let _ = mutex_clone.lock().await;
20+
}
21+
});
22+
vec.push(handle);
23+
}
24+
for i in vec {
25+
i.await
26+
}
27+
}
28+
29+
/// Create a waker that performs no-op
30+
fn noop_waker() -> task::Waker {
31+
use std::task::{RawWaker, RawWakerVTable};
32+
33+
unsafe fn clone_raw(ptr: *const ()) -> RawWaker {
34+
RawWaker::new(ptr, vtable())
35+
}
36+
37+
unsafe fn wake_raw(_ptr: *const ()) {}
38+
39+
unsafe fn wake_by_ref_raw(_ptr: *const ()) {}
40+
41+
unsafe fn drop_raw(_ptr: *const ()) {}
42+
43+
fn vtable() -> &'static RawWakerVTable {
44+
&RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw)
45+
}
46+
47+
unsafe { task::Waker::from_raw(RawWaker::new(std::ptr::null(), vtable())) }
48+
}
49+
50+
#[bench]
51+
fn mutex_contention(b: &mut Bencher) {
52+
b.iter(|| task::block_on(test(10, 1000)));
53+
}
54+
55+
#[bench]
56+
fn mutex_no_contention(b: &mut Bencher) {
57+
b.iter(|| task::block_on(test(1, 10000)));
58+
}
59+
60+
#[bench]
61+
fn mutex_unused(b: &mut Bencher) {
62+
b.iter(|| Mutex::new(()));
63+
}
64+
65+
#[bench]
66+
fn mutex_mimick_contention(b: &mut Bencher) {
67+
let noop_waker = noop_waker();
68+
let mut context = task::Context::from_waker(&noop_waker);
69+
70+
b.iter(|| {
71+
let mutex = Mutex::new(());
72+
let mut vec = Vec::with_capacity(10);
73+
74+
// Mimick 10 tasks concurrently trying to acquire the lock.
75+
for _ in 0..10 {
76+
let mut lock_future = Box::pin(mutex.lock());
77+
let poll_result = lock_future.as_mut().poll(&mut context);
78+
vec.push((lock_future, poll_result));
79+
}
80+
81+
// Go through all 10 tasks and release the lock.
82+
for (mut future, mut poll) in vec {
83+
while let task::Poll::Pending = poll {
84+
poll = future.as_mut().poll(&mut context);
85+
}
86+
}
87+
});
88+
}

0 commit comments

Comments
 (0)