1#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
26
27use std::fmt::Display;
28
29use libp2p_swarm::StreamProtocol;
30use web_time::Duration;
31
32pub mod client;
33mod protocol;
34pub mod server;
35
36pub const PROTOCOL_NAME: StreamProtocol = StreamProtocol::new("/perf/1.0.0");
37const RUN_TIMEOUT: Duration = Duration::from_secs(5 * 60);
38const MAX_PARALLEL_RUNS_PER_CONNECTION: usize = 1_000;
39
40#[derive(Debug, Clone, Copy)]
41pub enum RunUpdate {
42 Intermediate(Intermediate),
43 Final(Final),
44}
45
46#[derive(Debug, Clone, Copy)]
47pub struct Intermediate {
48 pub duration: Duration,
49 pub sent: usize,
50 pub received: usize,
51}
52
53impl Display for Intermediate {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 let Intermediate {
56 duration,
57 sent,
58 received,
59 } = self;
60 write!(
61 f,
62 "{:4} s uploaded {} downloaded {} ({})",
63 duration.as_secs_f64(),
64 format_bytes(*sent),
65 format_bytes(*received),
66 format_bandwidth(*duration, sent + received),
67 )?;
68
69 Ok(())
70 }
71}
72
73#[derive(Debug, Clone, Copy)]
74pub struct Final {
75 pub duration: RunDuration,
76}
77
78#[derive(Debug, Clone, Copy)]
83pub struct RunParams {
84 pub to_send: usize,
85 pub to_receive: usize,
86}
87
88#[derive(Debug, Clone, Copy)]
90pub struct RunDuration {
91 pub upload: Duration,
92 pub download: Duration,
93}
94
95#[derive(Debug, Clone, Copy)]
96pub struct Run {
97 pub params: RunParams,
98 pub duration: RunDuration,
99}
100
101const KILO: f64 = 1024.0;
102const MEGA: f64 = KILO * 1024.0;
103const GIGA: f64 = MEGA * 1024.0;
104
105fn format_bytes(bytes: usize) -> String {
106 let bytes = bytes as f64;
107 if bytes >= GIGA {
108 format!("{:.2} GiB", bytes / GIGA)
109 } else if bytes >= MEGA {
110 format!("{:.2} MiB", bytes / MEGA)
111 } else if bytes >= KILO {
112 format!("{:.2} KiB", bytes / KILO)
113 } else {
114 format!("{} B", bytes)
115 }
116}
117
118fn format_bandwidth(duration: Duration, bytes: usize) -> String {
119 const KILO: f64 = 1024.0;
120 const MEGA: f64 = KILO * 1024.0;
121 const GIGA: f64 = MEGA * 1024.0;
122
123 let bandwidth = (bytes as f64 * 8.0) / duration.as_secs_f64();
124
125 if bandwidth >= GIGA {
126 format!("{:.2} Gbit/s", bandwidth / GIGA)
127 } else if bandwidth >= MEGA {
128 format!("{:.2} Mbit/s", bandwidth / MEGA)
129 } else if bandwidth >= KILO {
130 format!("{:.2} Kbit/s", bandwidth / KILO)
131 } else {
132 format!("{:.2} bit/s", bandwidth)
133 }
134}
135
136impl Display for Run {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 let Run {
139 params: RunParams {
140 to_send,
141 to_receive,
142 },
143 duration: RunDuration { upload, download },
144 } = self;
145
146 write!(
147 f,
148 "uploaded {} in {:.4} s ({}), downloaded {} in {:.4} s ({})",
149 format_bytes(*to_send),
150 upload.as_secs_f64(),
151 format_bandwidth(*upload, *to_send),
152 format_bytes(*to_receive),
153 download.as_secs_f64(),
154 format_bandwidth(*download, *to_receive),
155 )?;
156
157 Ok(())
158 }
159}