mirror of
https://github.com/kristoferssolo/tls-pq-bench.git
synced 2026-03-22 00:36:21 +00:00
feat: implement raw TCP benchmark protocol
- protocol: 8-byte LE u64 request -> N-byte deterministic response - bench-server: TCP server with per-connection handlers - bench-runner: benchmark loop with warmup, NDJSON output - Integration tested: server and client communicate correctly
This commit is contained in:
@@ -6,10 +6,16 @@
|
||||
//!
|
||||
//! Outputs NDJSON records to stdout or a file.
|
||||
|
||||
use bench_common::KeyExchangeMode;
|
||||
use bench_common::protocol::{read_payload, write_request};
|
||||
use bench_common::{BenchRecord, KeyExchangeMode};
|
||||
use clap::Parser;
|
||||
use miette::miette;
|
||||
use std::fs::File;
|
||||
use std::io::{BufWriter, Write, stdout};
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
/// TLS benchmark runner.
|
||||
#[derive(Debug, Parser)]
|
||||
@@ -44,6 +50,92 @@ struct Args {
|
||||
out: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Result of a single benchmark iteration.
|
||||
struct IterationResult {
|
||||
handshake_ns: u64,
|
||||
ttlb_ns: u64,
|
||||
}
|
||||
|
||||
/// Run a single benchmark iteration over plain TCP.
|
||||
#[allow(clippy::cast_possible_truncation)] // nanoseconds won't overflow u64 for reasonable durations
|
||||
async fn run_iteration(server: SocketAddr, payload_bytes: u64) -> miette::Result<IterationResult> {
|
||||
let start = Instant::now();
|
||||
|
||||
// Connect (this is the "handshake" for plain TCP)
|
||||
let mut stream = TcpStream::connect(server)
|
||||
.await
|
||||
.map_err(|e| miette!("connection failed: {e}"))?;
|
||||
|
||||
let handshake_ns = start.elapsed().as_nanos() as u64;
|
||||
|
||||
// Send request
|
||||
write_request(&mut stream, payload_bytes)
|
||||
.await
|
||||
.map_err(|e| miette!("write request failed: {e}"))?;
|
||||
|
||||
// Read response
|
||||
read_payload(&mut stream, payload_bytes)
|
||||
.await
|
||||
.map_err(|e| miette!("read payload failed: {e}"))?;
|
||||
|
||||
let ttlb_ns = start.elapsed().as_nanos() as u64;
|
||||
|
||||
Ok(IterationResult {
|
||||
handshake_ns,
|
||||
ttlb_ns,
|
||||
})
|
||||
}
|
||||
|
||||
async fn run_benchmark(args: Args) -> miette::Result<()> {
|
||||
let total_iters = args.warmup + args.iters;
|
||||
|
||||
// Open output file or use stdout
|
||||
let mut output: Box<dyn Write + Send> = match &args.out {
|
||||
Some(path) => {
|
||||
let file =
|
||||
File::create(path).map_err(|e| miette!("failed to create output file: {e}"))?;
|
||||
Box::new(BufWriter::new(file))
|
||||
}
|
||||
None => Box::new(stdout()),
|
||||
};
|
||||
|
||||
eprintln!(
|
||||
"Running {} warmup + {} measured iterations (concurrency: {}, TLS disabled)",
|
||||
args.warmup, args.iters, args.concurrency
|
||||
);
|
||||
eprintln!();
|
||||
|
||||
// TODO: Implement concurrency
|
||||
for i in 0..total_iters {
|
||||
let is_warmup = i < args.warmup;
|
||||
|
||||
let result = run_iteration(args.server, args.payload_bytes).await?;
|
||||
|
||||
if !is_warmup {
|
||||
let record = BenchRecord {
|
||||
iteration: i - args.warmup,
|
||||
mode: args.mode,
|
||||
payload_bytes: args.payload_bytes,
|
||||
handshake_ns: result.handshake_ns,
|
||||
ttlb_ns: result.ttlb_ns,
|
||||
};
|
||||
|
||||
writeln!(output, "{record}").map_err(|e| miette!("failed to write record: {e}"))?;
|
||||
}
|
||||
|
||||
if is_warmup && i == args.warmup.saturating_sub(1) {
|
||||
eprintln!("Warmup complete.");
|
||||
}
|
||||
}
|
||||
|
||||
output
|
||||
.flush()
|
||||
.map_err(|e| miette!("failed to flush output: {e}"))?;
|
||||
|
||||
eprintln!("Benchmark complete.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> miette::Result<()> {
|
||||
let args = Args::parse();
|
||||
@@ -61,9 +153,7 @@ async fn main() -> miette::Result<()> {
|
||||
.as_ref()
|
||||
.map_or_else(|| "stdout".to_string(), |p| p.display().to_string())
|
||||
);
|
||||
eprintln!();
|
||||
|
||||
// TODO: Implement TLS client and benchmark loop
|
||||
eprintln!("\nRunner not yet implemented.");
|
||||
|
||||
Ok(())
|
||||
run_benchmark(args).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user