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 tcp.
15 //!
16 //! Designs of ylong_runtime benchmarks:
17 //! - Create a client and a server and connect them to each other.
18 //! - The client sends a message and the server receives the message.
19 //! - The server sends a message and the client receives the message.
20 //! - Repeat the preceding operations 1000 times.
21 
22 use std::thread;
23 use std::time::Instant;
24 
25 use tokio::io::{AsyncReadExt as tokioAsyncReadExt, AsyncWriteExt as tokioAsyncWriteExt};
26 use tokio::net::{TcpListener as tokioTcpListener, TcpStream as tokioTcpStream};
27 use ylong_runtime::builder::RuntimeBuilder;
28 use ylong_runtime::io::{AsyncReadExt, AsyncWriteExt};
29 use ylong_runtime::net::{TcpListener, TcpStream};
30 
31 const LOOP_NUMS: usize = 1000;
32 
ylong_create_client()33 fn ylong_create_client() {
34     let mut recv_buf = [0_u8; 12];
35     let runtime = RuntimeBuilder::new_multi_thread().build().unwrap();
36     let handle = runtime.spawn(async move {
37         let addr = "127.0.0.1:9081";
38         loop {
39             if let Ok(mut client) = TcpStream::connect(addr).await {
40                 match client.write(b"hello server").await {
41                     Ok(n) => {
42                         assert_eq!(n as usize, "hello server".len());
43                     }
44                     Err(e) => {
45                         panic!("client send failed {}", e);
46                     }
47                 }
48                 match client.read(&mut recv_buf).await {
49                     Ok(n) => {
50                         assert_eq!(
51                             std::str::from_utf8(&recv_buf).unwrap(),
52                             "hello client".to_string()
53                         );
54                         assert_eq!(n as usize, "hello client".len());
55                         break;
56                     }
57                     Err(e) => {
58                         panic!("client recv failed {}", e);
59                     }
60                 }
61             };
62         }
63     });
64     runtime.block_on(handle).unwrap();
65 }
66 
tokio_create_client()67 fn tokio_create_client() {
68     let mut recv_buf = [0_u8; 12];
69     let runtime = tokio::runtime::Builder::new_multi_thread()
70         .enable_all()
71         .build()
72         .unwrap();
73     let handle = runtime.spawn(async move {
74         loop {
75             if let Ok(mut client) = tokioTcpStream::connect("127.0.0.1:9082").await {
76                 match client.write(b"hello server").await {
77                     Ok(n) => {
78                         assert_eq!(n as usize, "hello server".len());
79                     }
80                     Err(e) => {
81                         panic!("client send failed {}", e);
82                     }
83                 }
84                 match client.read(&mut recv_buf).await {
85                     Ok(n) => {
86                         assert_eq!(
87                             std::str::from_utf8(&recv_buf).unwrap(),
88                             "hello client".to_string()
89                         );
90                         assert_eq!(n as usize, "hello client".len());
91                         break;
92                     }
93                     Err(e) => {
94                         panic!("client recv failed {}", e);
95                     }
96                 }
97             };
98         }
99     });
100     runtime.block_on(handle).unwrap();
101 }
102 
main()103 fn main() {
104     println!("ylong tcp read()+write() Loops: {}", LOOP_NUMS);
105 
106     let runtime = RuntimeBuilder::new_multi_thread().build().unwrap();
107     let addr = "127.0.0.1:9081";
108 
109     let st = Instant::now();
110     for _ in 0..LOOP_NUMS {
111         // start client
112         thread::spawn(ylong_create_client);
113         let handle = runtime.spawn(async move {
114             let listener = TcpListener::bind(addr).await.unwrap();
115 
116             let (mut socket, _) = listener.accept().await.unwrap();
117 
118             loop {
119                 let mut buf = [0_u8; 12];
120                 let _ = match socket.read(&mut buf).await {
121                     Ok(n) if n == 0 => break,
122                     Ok(n) => {
123                         assert_eq!(
124                             std::str::from_utf8(&buf).unwrap(),
125                             "hello server".to_string()
126                         );
127                         assert_eq!(n as usize, "hello server".len());
128                         n
129                     }
130                     Err(e) => {
131                         panic!("recv Failed {}", e);
132                     }
133                 };
134 
135                 let _ = socket.write(b"hello client").await.unwrap();
136             }
137         });
138         runtime.block_on(handle).unwrap();
139     }
140 
141     println!(
142         "ylong tcp read()+write() cost: {:.6} ms",
143         st.elapsed().as_secs_f64() * 1000f64 / 1000.0
144     );
145 
146     println!("tokio tcp read()+write() Loops: {}", LOOP_NUMS);
147 
148     let runtime = tokio::runtime::Builder::new_multi_thread()
149         .enable_all()
150         .build()
151         .unwrap();
152 
153     let st = Instant::now();
154     for _ in 0..LOOP_NUMS {
155         // start client
156         thread::spawn(tokio_create_client);
157         let handle = runtime.spawn(async move {
158             let listener = tokioTcpListener::bind("127.0.0.1:9082").await.unwrap();
159 
160             let (mut socket, _) = listener.accept().await.unwrap();
161 
162             loop {
163                 let mut buf = [0_u8; 12];
164                 let _ = match socket.read(&mut buf).await {
165                     Ok(n) if n == 0 => break,
166                     Ok(n) => {
167                         assert_eq!(
168                             std::str::from_utf8(&buf).unwrap(),
169                             "hello server".to_string()
170                         );
171                         assert_eq!(n as usize, "hello server".len());
172                         n
173                     }
174                     Err(e) => {
175                         panic!("recv Failed {}", e);
176                     }
177                 };
178 
179                 let _ = socket.write(b"hello client").await.unwrap();
180             }
181         });
182         runtime.block_on(handle).unwrap();
183     }
184 
185     println!(
186         "tokio tcp read()+write() cost: {:.6} ms",
187         st.elapsed().as_secs_f64() * 1000f64 / 1000.0
188     );
189 }
190