#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
use std::fmt::Display;
use instant::Duration;
use libp2p_swarm::StreamProtocol;
pub mod client;
mod protocol;
pub mod server;
pub const PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/perf/1.0.0");
#[derive(Debug, Clone, Copy)]
pub struct RunParams {
pub to_send: usize,
pub to_receive: usize,
}
#[derive(Debug, Clone, Copy)]
pub struct RunDuration {
pub upload: Duration,
pub download: Duration,
}
pub struct Run {
pub params: RunParams,
pub duration: RunDuration,
}
impl Display for Run {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
const KILO: f64 = 1024.0;
const MEGA: f64 = KILO * 1024.0;
const GIGA: f64 = MEGA * 1024.0;
fn format_bytes(bytes: usize) -> String {
let bytes = bytes as f64;
if bytes >= GIGA {
format!("{:.2} GiB", bytes / GIGA)
} else if bytes >= MEGA {
format!("{:.2} MiB", bytes / MEGA)
} else if bytes >= KILO {
format!("{:.2} KiB", bytes / KILO)
} else {
format!("{} B", bytes)
}
}
fn format_bandwidth(duration: Duration, bytes: usize) -> String {
const KILO: f64 = 1024.0;
const MEGA: f64 = KILO * 1024.0;
const GIGA: f64 = MEGA * 1024.0;
let bandwidth = (bytes as f64 * 8.0) / duration.as_secs_f64();
if bandwidth >= GIGA {
format!("{:.2} Gbit/s", bandwidth / GIGA)
} else if bandwidth >= MEGA {
format!("{:.2} Mbit/s", bandwidth / MEGA)
} else if bandwidth >= KILO {
format!("{:.2} Kbit/s", bandwidth / KILO)
} else {
format!("{:.2} bit/s", bandwidth)
}
}
let Run {
params: RunParams {
to_send,
to_receive,
},
duration: RunDuration { upload, download },
} = self;
write!(
f,
"uploaded {} in {:.4} s ({}), downloaded {} in {:.4} s ({})",
format_bytes(*to_send),
upload.as_secs_f64(),
format_bandwidth(*upload, *to_send),
format_bytes(*to_receive),
download.as_secs_f64(),
format_bandwidth(*download, *to_receive),
)?;
Ok(())
}
}