Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,141 @@
|
||||
use super::{Limits, Runtime, Socket, net};
|
||||
use bytes::BufMut;
|
||||
use std::{io::ErrorKind, time::Instant};
|
||||
use tokio::{io::AsyncWriteExt, net::TcpStream};
|
||||
|
||||
async fn independent_read(socket: &TcpStream, limit: usize) -> Option<Vec<u8>> {
|
||||
socket.readable().await.unwrap();
|
||||
let mut bytes = Vec::new();
|
||||
bytes.try_reserve_exact(limit).unwrap();
|
||||
loop {
|
||||
let result = socket.try_read_buf(&mut (&mut bytes).limit(limit));
|
||||
match result {
|
||||
Ok(count) => return (count != 0).then_some(bytes),
|
||||
Err(error) if error.kind() == ErrorKind::WouldBlock => {
|
||||
socket.readable().await.unwrap();
|
||||
}
|
||||
Err(error) => panic!("independent TCP read failed: {error}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn sample(
|
||||
peer: &mut TcpStream,
|
||||
payload: &[u8],
|
||||
limit: usize,
|
||||
iterations: usize,
|
||||
mut read: impl AsyncFnMut() -> Option<Vec<u8>>,
|
||||
) -> (u128, usize, usize) {
|
||||
let mut elapsed = 0;
|
||||
let mut reads = 0;
|
||||
let mut total = 0;
|
||||
for _ in 0..iterations {
|
||||
peer.write_all(payload).await.unwrap();
|
||||
let mut received = 0;
|
||||
loop {
|
||||
let started = Instant::now();
|
||||
let bytes = read().await;
|
||||
elapsed += started.elapsed().as_nanos();
|
||||
reads += 1;
|
||||
let Some(bytes) = bytes else {
|
||||
assert!(payload.is_empty());
|
||||
break;
|
||||
};
|
||||
assert!(!bytes.is_empty() && bytes.len() <= limit);
|
||||
assert!(received + bytes.len() <= payload.len());
|
||||
assert_eq!(bytes, payload[received..received + bytes.len()]);
|
||||
received += bytes.len();
|
||||
total += bytes.len();
|
||||
if received == payload.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(total, payload.len() * iterations);
|
||||
(elapsed, reads, total)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "explicit release performance probe; http enables the independent bytes/io-util peer"]
|
||||
fn tcp_read_buffer_cost() {
|
||||
let runtime = Runtime::new(Limits {
|
||||
threads: 1,
|
||||
workers: 1,
|
||||
tasks: 8,
|
||||
})
|
||||
.unwrap();
|
||||
runtime
|
||||
.run(async |scope| {
|
||||
eprintln!(
|
||||
"tcp_read_buffer: 15 fixed rounds; one async worker; two persistent loopback pairs; \
|
||||
peer writes, byte verification and result drops excluded from read timing; \
|
||||
rust_independent uses Tokio try_read_buf and bytes::BufMut::limit directly; \
|
||||
no shared Dever read implementation; direct peer excludes alias-close and read-lock checks; \
|
||||
actual read counts are retained; empty payload cases measure established EOF"
|
||||
);
|
||||
println!("\ncase,sample,implementation,iterations,elapsed_ns,reads,bytes");
|
||||
for (limit, payload_size, iterations) in [
|
||||
(64, 64, 4096),
|
||||
(65_536, 64, 2048),
|
||||
(1_048_576, 64, 512),
|
||||
(65_536, 65_536, 256),
|
||||
(1_048_576, 65_536, 128),
|
||||
(65_536, 0, 512),
|
||||
(1_048_576, 0, 128),
|
||||
] {
|
||||
let listener = net::listen("127.0.0.1", 0, scope).await.unwrap();
|
||||
let mut dever_peer =
|
||||
TcpStream::connect(("127.0.0.1", listener.port().unwrap() as u16))
|
||||
.await
|
||||
.unwrap();
|
||||
let socket: Socket = listener.accept().await.unwrap();
|
||||
listener.close().unwrap();
|
||||
let listener = tokio::net::TcpListener::bind(("127.0.0.1", 0)).await.unwrap();
|
||||
let mut independent_peer = TcpStream::connect(listener.local_addr().unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
let independent = listener.accept().await.unwrap().0;
|
||||
independent.set_nodelay(true).unwrap();
|
||||
dever_peer.set_nodelay(true).unwrap();
|
||||
independent_peer.set_nodelay(true).unwrap();
|
||||
drop(listener);
|
||||
if payload_size == 0 {
|
||||
dever_peer.shutdown().await.unwrap();
|
||||
independent_peer.shutdown().await.unwrap();
|
||||
}
|
||||
let payload = (0..payload_size)
|
||||
.map(|position| (position % 251) as u8)
|
||||
.collect::<Vec<_>>();
|
||||
sample(&mut dever_peer, &payload, limit, 16, async || {
|
||||
socket.read(limit as i64).await.unwrap()
|
||||
})
|
||||
.await;
|
||||
sample(&mut independent_peer, &payload, limit, 16, async || {
|
||||
independent_read(&independent, limit).await
|
||||
})
|
||||
.await;
|
||||
for round in 0..15 {
|
||||
let mut order = ["dever", "rust_independent", "control"];
|
||||
order.rotate_left(round % 3);
|
||||
for label in order {
|
||||
let (elapsed, reads, total) = if label == "rust_independent" {
|
||||
sample(&mut independent_peer, &payload, limit, iterations, async || {
|
||||
independent_read(&independent, limit).await
|
||||
})
|
||||
.await
|
||||
} else {
|
||||
sample(&mut dever_peer, &payload, limit, iterations, async || {
|
||||
socket.read(limit as i64).await.unwrap()
|
||||
})
|
||||
.await
|
||||
};
|
||||
println!(
|
||||
"tcp_read_{limit}_{payload_size},{round},{label},{iterations},{elapsed},{reads},{total}"
|
||||
);
|
||||
}
|
||||
}
|
||||
socket.close().unwrap();
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
Reference in new issue
Block a user