1#![feature(test)]
2
3extern crate test;
4use crate::test::Bencher;
5
6use futures::executor::block_on;
7use futures::future::Future;
8use futures::task::{Context, Poll, Waker};
9use std::pin::Pin;
10
11#[bench]
12fn thread_yield_single_thread_one_wait(b: &mut Bencher) {
13 const NUM: usize = 10_000;
14
15 struct Yield {
16 rem: usize,
17 }
18
19 impl Future for Yield {
20 type Output = ();
21
22 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
23 if self.rem == 0 {
24 Poll::Ready(())
25 } else {
26 self.rem -= 1;
27 cx.waker().wake_by_ref();
28 Poll::Pending
29 }
30 }
31 }
32
33 b.iter(|| {
34 let y = Yield { rem: NUM };
35 block_on(y);
36 });
37}
38
39#[bench]
40fn thread_yield_single_thread_many_wait(b: &mut Bencher) {
41 const NUM: usize = 10_000;
42
43 struct Yield {
44 rem: usize,
45 }
46
47 impl Future for Yield {
48 type Output = ();
49
50 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
51 if self.rem == 0 {
52 Poll::Ready(())
53 } else {
54 self.rem -= 1;
55 cx.waker().wake_by_ref();
56 Poll::Pending
57 }
58 }
59 }
60
61 b.iter(|| {
62 for _ in 0..NUM {
63 let y = Yield { rem: 1 };
64 block_on(y);
65 }
66 });
67}
68
69#[bench]
70fn thread_yield_multi_thread(b: &mut Bencher) {
71 use std::sync::mpsc;
72 use std::thread;
73
74 const NUM: usize = 1_000;
75
76 let (tx, rx) = mpsc::sync_channel::<Waker>(10_000);
77
78 struct Yield {
79 rem: usize,
80 tx: mpsc::SyncSender<Waker>,
81 }
82 impl Unpin for Yield {}
83
84 impl Future for Yield {
85 type Output = ();
86
87 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
88 if self.rem == 0 {
89 Poll::Ready(())
90 } else {
91 self.rem -= 1;
92 self.tx.send(cx.waker().clone()).unwrap();
93 Poll::Pending
94 }
95 }
96 }
97
98 thread::spawn(move || {
99 while let Ok(task) = rx.recv() {
100 task.wake();
101 }
102 });
103
104 b.iter(move || {
105 let y = Yield { rem: NUM, tx: tx.clone() };
106
107 block_on(y);
108 });
109}
110