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 sync operations as performance baselines.
15 
16 #![feature(test)]
17 
18 pub mod task_helpers;
19 
20 #[cfg(test)]
21 mod sync_benchmarks {
22     extern crate test;
23     #[cfg(unix)]
24     use std::fs::File;
25     use std::hint::black_box;
26     #[cfg(unix)]
27     use std::io::prelude::*;
28     use std::sync::mpsc;
29 
30     use test::Bencher;
31 
32     use crate::task_helpers::*;
33 
34     #[bench]
single_thread_run_1000_fibbo(b: &mut Bencher)35     fn single_thread_run_1000_fibbo(b: &mut Bencher) {
36         b.iter(black_box(|| {
37             let handlers: Vec<[u8; TASK_NUM]> = black_box(Vec::with_capacity(TASK_NUM));
38             for _ in 0..TASK_NUM {
39                 let ret = black_box(fibbo(30));
40                 assert_eq!(ret, FIBBO_ANS);
41             }
42             assert_eq!(handlers.len(), 0);
43         }));
44     }
45 
46     #[bench]
single_thread_run_task(b: &mut Bencher)47     fn single_thread_run_task(b: &mut Bencher) {
48         b.iter(black_box(|| {
49             let result = work();
50             assert_eq!(result, 3);
51         }))
52     }
53 
54     #[cfg(unix)]
55     #[bench]
std_read_file(b: &mut Bencher)56     fn std_read_file(b: &mut Bencher) {
57         b.iter(|| {
58             let mut file = File::open(READ_FILE).unwrap();
59 
60             for _i in 0..TASK_NUM {
61                 unsafe {
62                     file.read_exact(&mut READ_BUFFER).unwrap();
63                 }
64             }
65         });
66     }
67 
68     #[cfg(unix)]
69     #[bench]
std_read_file_by_chars(b: &mut Bencher)70     fn std_read_file_by_chars(b: &mut Bencher) {
71         b.iter(|| {
72             let mut file = File::open(READ_FILE).unwrap();
73             let mut buffer = [0_u8];
74 
75             unsafe {
76                 for tar in READ_BUFFER.iter_mut().take(TASK_NUM) {
77                     file.read_exact(&mut buffer).unwrap();
78                     *tar = buffer[0];
79                 }
80             }
81         });
82     }
83 
84     #[cfg(unix)]
85     #[bench]
std_write_file(b: &mut Bencher)86     fn std_write_file(b: &mut Bencher) {
87         init_write_buffer();
88 
89         b.iter(black_box(|| {
90             let mut file = File::create(WRITE_FILE).unwrap();
91             for _i in 0..TASK_NUM {
92                 unsafe {
93                     let _ = file.write(&WRITE_BUFFER).unwrap();
94                 }
95             }
96         }));
97     }
98 
99     #[bench]
std_multi_threaded_ping(b: &mut Bencher)100     fn std_multi_threaded_ping(b: &mut Bencher) {
101         let (send, recv) = mpsc::sync_channel(TASK_NUM);
102 
103         b.iter(black_box(|| {
104             let sender = send.clone();
105             let _ = std::thread::spawn(move || {
106                 for _ in 0..TASK_NUM {
107                     sender.send(()).unwrap();
108                 }
109             });
110 
111             for _ in 0..TASK_NUM {
112                 recv.recv().unwrap();
113             }
114         }));
115     }
116 
117     #[bench]
std_multi_threaded_ping_pong(b: &mut Bencher)118     fn std_multi_threaded_ping_pong(b: &mut Bencher) {
119         let (send, recv) = mpsc::sync_channel(TASK_NUM);
120 
121         b.iter(black_box(|| {
122             let done_send = send.clone();
123             std::thread::spawn(move || {
124                 for _ in 0..TASK_NUM {
125                     let (send1, recv1) = mpsc::sync_channel(TASK_NUM);
126                     let (send2, recv2) = mpsc::sync_channel(TASK_NUM);
127 
128                     std::thread::spawn(move || {
129                         recv1.recv().unwrap();
130                         send2.send(()).unwrap();
131                     });
132 
133                     send1.send(()).unwrap();
134                     recv2.recv().unwrap();
135 
136                     done_send.send(()).unwrap();
137                 }
138             });
139 
140             for _ in 0..TASK_NUM {
141                 recv.recv().unwrap();
142             }
143         }));
144     }
145 }
146