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