batch_send_test/
batch_send_test.rs1use rperf3::{UdpSendBatch, MAX_BATCH_SIZE};
7use std::net::SocketAddr;
8use std::time::Instant;
9use tokio::net::UdpSocket;
10
11#[tokio::main]
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13 let socket = UdpSocket::bind("0.0.0.0:0").await?;
15 let local_addr = socket.local_addr()?;
16 println!("Socket bound to: {}", local_addr);
17
18 let target: SocketAddr = "127.0.0.1:5201".parse()?;
20
21 let mut batch = UdpSendBatch::new();
23
24 let packet_size = 1024;
26 let packet_count = 1000;
27
28 println!(
29 "\nSending {} packets of {} bytes each",
30 packet_count, packet_size
31 );
32 println!("Batch size: {} packets per system call", MAX_BATCH_SIZE);
33
34 let start = Instant::now();
36 let mut total_bytes = 0;
37 let mut total_packets = 0;
38 let mut batch_count = 0;
39
40 for i in 0..packet_count {
41 let mut packet = vec![0u8; packet_size];
42 packet[0..4].copy_from_slice(&(i as u32).to_be_bytes());
44
45 if !batch.add(packet, target) {
46 match batch.send(&socket).await {
48 Ok((bytes, packets)) => {
49 total_bytes += bytes;
50 total_packets += packets;
51 batch_count += 1;
52 }
53 Err(e) => {
54 eprintln!("Error sending batch: {}", e);
55 break;
56 }
57 }
58 }
59 }
60
61 if !batch.is_empty() {
63 match batch.send(&socket).await {
64 Ok((bytes, packets)) => {
65 total_bytes += bytes;
66 total_packets += packets;
67 batch_count += 1;
68 }
69 Err(e) => eprintln!("Error sending final batch: {}", e),
70 }
71 }
72
73 let duration = start.elapsed();
74
75 println!("\n=== Results ===");
76 println!("Total packets sent: {}", total_packets);
77 println!(
78 "Total bytes sent: {} ({:.2} MB)",
79 total_bytes,
80 total_bytes as f64 / 1_000_000.0
81 );
82 println!("Batches sent: {}", batch_count);
83 println!(
84 "Avg packets per batch: {:.1}",
85 total_packets as f64 / batch_count as f64
86 );
87 println!("Duration: {:.3} seconds", duration.as_secs_f64());
88 println!(
89 "Throughput: {:.2} Mbps",
90 (total_bytes * 8) as f64 / duration.as_secs_f64() / 1_000_000.0
91 );
92 println!(
93 "Packet rate: {:.0} pps",
94 total_packets as f64 / duration.as_secs_f64()
95 );
96
97 #[cfg(target_os = "linux")]
98 println!("\n✓ Using Linux sendmmsg for batched operations");
99
100 #[cfg(not(target_os = "linux"))]
101 println!("\n⚠ Using fallback (individual send_to calls)");
102
103 Ok(())
104}