Files
core/test/rust/performance/websocket/mod.rs
T
2026-11-03 03:32:07 +00:00

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();
}