• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 //! Benchmarks for the threaded scheduler.
15 //!
16 //! Designs of ylong_runtime benchmarks:
17 //! - Mainly follow designs of tokio multi threaded tests.
18 //!
19 //! Designs of tokio benchmarks:
20 //! - Reference: [tokio/benches/multi_threaded.rs](https://github.com/tokio-rs/tokio/blob/master/benches/rt_multi_threaded.rs)
21 //! - Get changed to keep benchmarks in the same manner.
22 //! - Move ping-pong tests to channel related benchmarks.
23 
24 #![feature(test)]
25 
26 pub mod task_helpers;
27 
28 #[macro_export]
29 macro_rules! runtime_spawn_function {
30     () => {
31         fn runtime_spawn_many(runtime: &Runtime, sender: mpsc::SyncSender<()>) {
32             runtime.spawn(async move {
33                 sender.send(()).unwrap();
34             });
35         }
36 
37         fn runtime_yield_many(runtime: &Runtime, sender: mpsc::SyncSender<()>) {
38             runtime.spawn(async move {
39                 for _ in 0..YIELD_NUM {
40                     yield_now().await;
41                 }
42                 sender.send(()).unwrap();
43             });
44         }
45     };
46 }
47 
48 // Change not to use atomic variables, and thus avoid those costs.
49 #[macro_export]
50 macro_rules! spawn_yield_many {
51     ($runtime: ident, $test: ident, $fn: ident) => {
52         #[bench]
53         fn $test(b: &mut Bencher) {
54             let runtime = $runtime();
55 
56             let (send, recv) = mpsc::sync_channel(TASK_NUM);
57 
58             b.iter(black_box(|| {
59                 let task = || async {
60                     for _ in 0..TASK_NUM {
61                         $fn(&runtime, send.clone());
62                     }
63                 };
64 
65                 runtime.block_on(task());
66 
67                 for _ in 0..TASK_NUM {
68                     let _ = recv.recv().unwrap();
69                 }
70             }));
71         }
72     };
73 }
74 
75 #[cfg(test)]
76 mod ylong_multi_threaded {
77     extern crate test;
78     use std::hint::black_box;
79     use std::sync::{mpsc, Arc};
80 
81     use test::Bencher;
82     use ylong_runtime::executor::Runtime;
83     use ylong_runtime::task::yield_now;
84 
85     use crate::task_helpers::*;
86 
87     runtime_spawn_function!();
88 
89     spawn_yield_many!(ylong_runtime, spawn_many, runtime_spawn_many);
90     spawn_yield_many!(ylong_runtime, yield_many, runtime_yield_many);
91 
92     #[bench]
chained_spawn(b: &mut Bencher)93     fn chained_spawn(b: &mut Bencher) {
94         fn iter(runtime: Arc<Runtime>, sender: mpsc::SyncSender<()>, n: usize) {
95             if n == 0 {
96                 sender.send(()).unwrap();
97             } else {
98                 let runtime_clone = runtime.clone();
99                 runtime.spawn(async move { iter(runtime_clone, sender, n - 1) });
100             }
101         }
102 
103         let runtime = Arc::new(ylong_runtime());
104         let (send, recv) = mpsc::sync_channel(TASK_NUM);
105 
106         let runtime_clone = runtime.clone();
107         b.iter(black_box(move || {
108             let sender = send.clone();
109             runtime.block_on(async {
110                 let runtime_iter_clone = runtime_clone.clone();
111                 runtime_clone.spawn(async move { iter(runtime_iter_clone, sender, TASK_NUM) });
112 
113                 recv.recv().unwrap();
114             });
115         }));
116     }
117 }
118 
119 #[cfg(test)]
120 mod tokio_multi_threaded {
121     extern crate test;
122     use std::hint::black_box;
123     use std::sync::mpsc;
124 
125     use test::Bencher;
126     use tokio::runtime::Runtime;
127     use tokio::task::yield_now;
128 
129     use crate::task_helpers::*;
130 
131     runtime_spawn_function!();
132 
133     spawn_yield_many!(tokio_runtime, spawn_many, runtime_spawn_many);
134     spawn_yield_many!(tokio_runtime, yield_many, runtime_yield_many);
135 
136     #[bench]
chained_spawn(b: &mut Bencher)137     fn chained_spawn(b: &mut Bencher) {
138         fn iter(sender: mpsc::SyncSender<()>, n: usize) {
139             if n == 0 {
140                 sender.send(()).unwrap();
141             } else {
142                 tokio::spawn(async move { iter(sender, n - 1) });
143             }
144         }
145 
146         let runtime = tokio_runtime();
147         let (send, recv) = mpsc::sync_channel(TASK_NUM);
148 
149         b.iter(black_box(move || {
150             let sender = send.clone();
151             runtime.block_on(async {
152                 tokio::spawn(async move { iter(sender, TASK_NUM) });
153 
154                 recv.recv().unwrap();
155             });
156         }));
157     }
158 }
159