]>
Commit | Line | Data |
---|---|---|
5099ac24 FG |
1 | #![feature(test)] |
2 | ||
3 | #[cfg(feature = "bilock")] | |
4 | mod bench { | |
5 | use futures::executor::LocalPool; | |
6 | use futures::task::{Context, Waker}; | |
7 | use futures_util::lock::BiLock; | |
8 | use futures_util::lock::BiLockAcquire; | |
9 | use futures_util::lock::BiLockAcquired; | |
10 | use futures_util::task::ArcWake; | |
11 | ||
12 | use std::sync::Arc; | |
13 | use test::Bencher; | |
14 | ||
15 | fn notify_noop() -> Waker { | |
16 | struct Noop; | |
17 | ||
18 | impl ArcWake for Noop { | |
19 | fn wake(_: &Arc<Self>) {} | |
20 | } | |
21 | ||
22 | ArcWake::into_waker(Arc::new(Noop)) | |
23 | } | |
24 | ||
25 | /// Pseudo-stream which simply calls `lock.poll()` on `poll` | |
26 | struct LockStream { | |
27 | lock: BiLockAcquire<u32>, | |
28 | } | |
29 | ||
30 | impl LockStream { | |
31 | fn new(lock: BiLock<u32>) -> Self { | |
32 | Self { lock: lock.lock() } | |
33 | } | |
34 | ||
35 | /// Release a lock after it was acquired in `poll`, | |
36 | /// so `poll` could be called again. | |
37 | fn release_lock(&mut self, guard: BiLockAcquired<u32>) { | |
38 | self.lock = guard.unlock().lock() | |
39 | } | |
40 | } | |
41 | ||
42 | impl Stream for LockStream { | |
43 | type Item = BiLockAcquired<u32>; | |
44 | type Error = (); | |
45 | ||
46 | fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Option<Self::Item>, Self::Error> { | |
47 | self.lock.poll(cx).map(|a| a.map(Some)) | |
48 | } | |
49 | } | |
50 | ||
51 | #[bench] | |
52 | fn contended(b: &mut Bencher) { | |
53 | let pool = LocalPool::new(); | |
54 | let mut exec = pool.executor(); | |
55 | let waker = notify_noop(); | |
56 | let mut map = task::LocalMap::new(); | |
57 | let mut waker = task::Context::new(&mut map, &waker, &mut exec); | |
58 | ||
59 | b.iter(|| { | |
60 | let (x, y) = BiLock::new(1); | |
61 | ||
62 | let mut x = LockStream::new(x); | |
63 | let mut y = LockStream::new(y); | |
64 | ||
65 | for _ in 0..1000 { | |
66 | let x_guard = match x.poll_next(&mut waker) { | |
67 | Ok(Poll::Ready(Some(guard))) => guard, | |
68 | _ => panic!(), | |
69 | }; | |
70 | ||
71 | // Try poll second lock while first lock still holds the lock | |
72 | match y.poll_next(&mut waker) { | |
73 | Ok(Poll::Pending) => (), | |
74 | _ => panic!(), | |
75 | }; | |
76 | ||
77 | x.release_lock(x_guard); | |
78 | ||
79 | let y_guard = match y.poll_next(&mut waker) { | |
80 | Ok(Poll::Ready(Some(guard))) => guard, | |
81 | _ => panic!(), | |
82 | }; | |
83 | ||
84 | y.release_lock(y_guard); | |
85 | } | |
86 | (x, y) | |
87 | }); | |
88 | } | |
89 | ||
90 | #[bench] | |
91 | fn lock_unlock(b: &mut Bencher) { | |
92 | let pool = LocalPool::new(); | |
93 | let mut exec = pool.executor(); | |
94 | let waker = notify_noop(); | |
95 | let mut map = task::LocalMap::new(); | |
96 | let mut waker = task::Context::new(&mut map, &waker, &mut exec); | |
97 | ||
98 | b.iter(|| { | |
99 | let (x, y) = BiLock::new(1); | |
100 | ||
101 | let mut x = LockStream::new(x); | |
102 | let mut y = LockStream::new(y); | |
103 | ||
104 | for _ in 0..1000 { | |
105 | let x_guard = match x.poll_next(&mut waker) { | |
106 | Ok(Poll::Ready(Some(guard))) => guard, | |
107 | _ => panic!(), | |
108 | }; | |
109 | ||
110 | x.release_lock(x_guard); | |
111 | ||
112 | let y_guard = match y.poll_next(&mut waker) { | |
113 | Ok(Poll::Ready(Some(guard))) => guard, | |
114 | _ => panic!(), | |
115 | }; | |
116 | ||
117 | y.release_lock(y_guard); | |
118 | } | |
119 | (x, y) | |
120 | }) | |
121 | } | |
122 | } |