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