115 lines
4.8 KiB
Rust
115 lines
4.8 KiB
Rust
// 对照真实发送的生成适配层;双方共用运行库,分别记录发送与完整收发,逐字节校验在计时外。
|
|
use dever_runtime::{
|
|
http::websocket::{self as ws, Message, WebSocket},
|
|
task::{Limits, Runtime},
|
|
};
|
|
use std::{hint::black_box, time::Instant};
|
|
|
|
async fn send(generated: bool, borrowed: bool, socket: &WebSocket, message: &MESSAGE_TYPE) {
|
|
if generated && borrowed {
|
|
WS_SEND_MESSAGE(socket, message).await.unwrap();
|
|
return;
|
|
}
|
|
match message {
|
|
MESSAGE_TYPE::Variant0(text) if generated => WS_SEND_TEXT(socket, text).await.unwrap(),
|
|
MESSAGE_TYPE::Variant1(bytes) if generated => WS_SEND_BINARY(socket, bytes).await.unwrap(),
|
|
MESSAGE_TYPE::Variant0(text) => socket.send(Message::Text(text.clone())).await.unwrap(),
|
|
MESSAGE_TYPE::Variant1(bytes) => socket.send(Message::Binary(bytes.clone())).await.unwrap(),
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
fn payload_size(message: &MESSAGE_TYPE) -> usize {
|
|
match message {
|
|
MESSAGE_TYPE::Variant0(text) => text.len(),
|
|
MESSAGE_TYPE::Variant1(bytes) => bytes.len(),
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
fn check(received: Option<Message>, expected: &MESSAGE_TYPE) {
|
|
match (received, expected) {
|
|
(Some(Message::Text(actual)), MESSAGE_TYPE::Variant0(expected)) => {
|
|
assert_eq!(&actual, expected)
|
|
}
|
|
(Some(Message::Binary(actual)), MESSAGE_TYPE::Variant1(expected)) => {
|
|
assert_eq!(&actual, expected)
|
|
}
|
|
_ => panic!("WebSocket message changed"),
|
|
}
|
|
}
|
|
|
|
async fn ready(socket: &WebSocket, input: &MESSAGE_TYPE, count: usize) {
|
|
socket
|
|
.send(Message::Text(format!("roundtrip:{count}")))
|
|
.await
|
|
.unwrap();
|
|
send(false, false, socket, input).await;
|
|
assert_eq!(
|
|
socket.receive().await.unwrap(),
|
|
Some(Message::Text("ready".to_owned()))
|
|
);
|
|
}
|
|
|
|
fn main() {
|
|
if std::env::args().any(|argument| argument == "--peer") {
|
|
peer::run();
|
|
return;
|
|
}
|
|
let mut peer = peer::Peer::start(1);
|
|
let runtime = Runtime::new(Limits {
|
|
threads: 1,
|
|
workers: 1,
|
|
tasks: 128,
|
|
})
|
|
.unwrap();
|
|
println!("case,sample,implementation,elapsed_ns,checksum");
|
|
runtime.run(async |scope| {
|
|
// 双方轮流使用同一连接;固定协议对端在另一 CPU,隔离连接差异与线程争抢。
|
|
let socket = ws::connect("127.0.0.1", i64::from(peer.port), "/bench", &ws::Limits::default(), scope).await.unwrap();
|
|
for bytes in [64, 65536] {
|
|
for binary in [false, true] {
|
|
let input = if binary {
|
|
MESSAGE_TYPE::Variant1((0..bytes).map(|index| (index % 251) as u8).collect::<Vec<_>>().into())
|
|
} else {
|
|
MESSAGE_TYPE::Variant0("雪a".repeat(bytes / 4))
|
|
};
|
|
for borrowed in [false, true] {
|
|
let name = format!("ws_{}_{}_{}", if binary { "binary" } else { "text" }, if borrowed { "borrowed" } else { "temporary" }, bytes);
|
|
for generated in [true, false] {
|
|
ready(&socket, &input, 20).await;
|
|
for _ in 0..20 {
|
|
send(generated, borrowed, &socket, &input).await;
|
|
check(socket.receive().await.unwrap(), &input);
|
|
}
|
|
}
|
|
for sample in 0..15 {
|
|
let mut order = [("dever", true), ("rust_runtime", false), ("control", true)];
|
|
order.rotate_left(sample % 3);
|
|
for (implementation, generated) in order {
|
|
ready(&socket, &input, 200).await;
|
|
let mut sent = 0;
|
|
let mut roundtrip = 0;
|
|
let mut checksum = 0;
|
|
for _ in 0..200 {
|
|
let start = Instant::now();
|
|
send(generated, borrowed, &socket, black_box(&input)).await;
|
|
sent += start.elapsed().as_nanos();
|
|
let received = socket.receive().await.unwrap();
|
|
roundtrip += start.elapsed().as_nanos();
|
|
check(received, &input);
|
|
checksum += payload_size(black_box(&input));
|
|
}
|
|
assert_eq!(checksum, bytes * 200);
|
|
println!("{name}_send,{sample},{implementation},{sent},{checksum}");
|
|
println!("{name}_roundtrip,{sample},{implementation},{roundtrip},{checksum}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
socket.close(1000, "").await.unwrap();
|
|
}).unwrap();
|
|
peer.finish();
|
|
}
|