1use crate::common::control::TestResults;
2use crate::common::data::Direction;
3use colored::Colorize;
4
5const KBYTES: usize = 1024;
7const MBYTES: usize = 1024 * KBYTES;
8const GBYTES: usize = 1024 * MBYTES;
9const TBYTES: usize = 1024 * GBYTES;
10
11const KBITS: usize = 1000;
13const MBITS: usize = 1000 * KBITS;
14const GBITS: usize = 1000 * MBITS;
15const TBITS: usize = 1000 * GBITS;
16
17pub fn print_header() {
18 println!("[ ID] Interval Transfer Bitrate");
19}
20pub fn print_server_banner(port: u16) {
21 println!("--------------------------------------");
22 println!("{} {}", "Listening on port".cyan(), port);
23 println!("--------------------------------------");
24}
25
26pub fn humanize_bytes(bytes: usize) -> String {
27 if bytes < KBYTES {
28 format!("{} B", bytes)
29 } else if bytes < MBYTES {
30 format!("{:.2} KiB", bytes as f64 / KBYTES as f64)
31 } else if bytes < GBYTES {
32 format!("{:.2} MiB", bytes as f64 / MBYTES as f64)
33 } else if bytes < TBYTES {
34 format!("{:.2} GiB", bytes as f64 / GBYTES as f64)
35 } else {
36 format!("{:.2} TiB", bytes as f64 / TBYTES as f64)
37 }
38}
39
40pub fn humanize_bitrate(bytes: usize, duration_millis: u64) -> String {
41 let bits = bytes * 8;
44 let rate = (bits as f64 / duration_millis as f64) * 1000f64;
46 if rate < KBITS as f64 {
47 format!("{} Bits/sec", rate)
48 } else if bytes < MBITS {
49 format!("{:.2} Kbits/sec", rate / KBITS as f64)
50 } else if bytes < GBITS {
51 format!("{:.2} Mbits/sec", rate / MBITS as f64)
52 } else if bytes < TBITS {
53 format!("{:.2} Gbits/sec", rate / GBITS as f64)
54 } else {
55 format!("{:.2} Tbits/sec", rate / TBITS as f64)
56 }
57}
58
59pub fn print_stats(
60 id: Option<usize>,
61 offset_from_start_millis: u64,
62 duration_millis: u64,
63 bytes_transferred: usize,
64 sender: bool,
65 _syscalls: usize,
66 _block_size: usize,
67) {
68 let end_point = offset_from_start_millis + duration_millis;
69 println!(
71 "[{:>3}] {:.2}..{:.2} sec {} {} {}",
72 id.map(|x| x.to_string())
73 .unwrap_or_else(|| "SUM".to_owned()),
74 offset_from_start_millis as f64 / 1000f64,
75 end_point as f64 / 1000f64,
76 humanize_bytes(bytes_transferred),
77 humanize_bitrate(bytes_transferred, duration_millis),
78 if sender {
79 "sender".yellow()
80 } else {
81 "receiver".magenta()
82 },
83 );
84}
85
86pub fn print_summary(
87 local_results: &TestResults,
88 remote_results: &TestResults,
89 direction: &Direction,
90) {
91 println!("- - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
92 print_summary_header();
93 let mut sender_duration_millis = 0;
96 let mut receiver_duration_millis = 0;
97 let mut sender_bytes_transferred = 0;
98 let mut receiver_bytes_transferred = 0;
99 for (id, local_stats) in &local_results.streams {
100 print_stats(
101 Some(*id),
102 0,
103 local_stats.duration_millis,
104 local_stats.bytes_transferred,
105 local_stats.sender,
106 local_stats.syscalls,
107 0,
108 );
109 if local_stats.sender {
110 sender_bytes_transferred += local_stats.bytes_transferred;
111 sender_duration_millis =
112 std::cmp::max(sender_duration_millis, local_stats.duration_millis);
113 } else {
114 receiver_bytes_transferred += local_stats.bytes_transferred;
115 receiver_duration_millis =
116 std::cmp::max(receiver_duration_millis, local_stats.duration_millis);
117 }
118 if *direction != Direction::Bidirectional {
122 if let Some(remote_stats) = remote_results.streams.get(id) {
123 print_stats(
124 Some(*id),
125 0,
126 remote_stats.duration_millis,
127 remote_stats.bytes_transferred,
128 remote_stats.sender,
129 remote_stats.syscalls,
130 0,
131 );
132 if remote_stats.sender {
133 sender_bytes_transferred += remote_stats.bytes_transferred;
134 sender_duration_millis =
135 std::cmp::max(sender_duration_millis, remote_stats.duration_millis);
136 } else {
137 receiver_bytes_transferred += remote_stats.bytes_transferred;
138 receiver_duration_millis =
139 std::cmp::max(receiver_duration_millis, remote_stats.duration_millis);
140 }
141 }
142 }
143 }
144 if local_results.streams.len() > 1 {
146 println!();
147 print_stats(
148 None,
149 0,
150 sender_duration_millis,
151 sender_bytes_transferred,
152 true,
153 0,
154 0,
155 );
156 print_stats(
157 None,
158 0,
159 receiver_duration_millis,
160 receiver_bytes_transferred,
161 false,
162 0,
163 0,
164 );
165 }
166}
167
168fn print_summary_header() {
169 println!(
170 "{} {} {} {}",
171 "ID".bold(),
172 "Interval".bold(),
173 "Transfer".bold(),
174 "Bitrate".bold()
175 );
176}