-
-
Notifications
You must be signed in to change notification settings - Fork 390
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bench(udp): measure non-GSO & GSO on localhost (#1915)
This commit adds a basic benchmark, measuring the time to transfer 10 MiB with and without GSO on localhost. ``` gso_false/throughput time: [23.455 ms 25.230 ms 27.004 ms] thrpt: [370.31 MiB/s 396.35 MiB/s 426.35 MiB/s] gso_true/throughput time: [1.0168 ms 1.1239 ms 1.2496 ms] thrpt: [7.8153 GiB/s 8.6889 GiB/s 9.6044 GiB/s] ``` ``` $ cat /proc/cpuinfo model name : 12th Gen Intel(R) Core(TM) i9-12900HK ``` --- Given various optimizations for `localhost` traffic on Linux, we were wondering whether GSO actually has an impact on `localhost`. According to this benchmark: Yes it does. For what a `localhost` network benchmark is worth, here it is. Feel free to close in case it isn't useful.
- Loading branch information
Showing
2 changed files
with
82 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use criterion::{criterion_group, criterion_main, Criterion}; | ||
use quinn_udp::{RecvMeta, Transmit, UdpSocketState}; | ||
use std::cmp::min; | ||
use std::{io::IoSliceMut, net::UdpSocket, slice}; | ||
|
||
pub fn criterion_benchmark(c: &mut Criterion) { | ||
const TOTAL_BYTES: usize = 10 * 1024 * 1024; | ||
// Maximum GSO buffer size is 64k. | ||
const MAX_BUFFER_SIZE: usize = u16::MAX as usize; | ||
const SEGMENT_SIZE: usize = 1280; | ||
|
||
let send = UdpSocket::bind("[::1]:0") | ||
.or_else(|_| UdpSocket::bind("127.0.0.1:0")) | ||
.unwrap(); | ||
let recv = UdpSocket::bind("[::1]:0") | ||
.or_else(|_| UdpSocket::bind("127.0.0.1:0")) | ||
.unwrap(); | ||
let max_segments = min( | ||
UdpSocketState::new((&send).into()) | ||
.unwrap() | ||
.max_gso_segments(), | ||
MAX_BUFFER_SIZE / SEGMENT_SIZE, | ||
); | ||
let dst_addr = recv.local_addr().unwrap(); | ||
let send_state = UdpSocketState::new((&send).into()).unwrap(); | ||
let recv_state = UdpSocketState::new((&recv).into()).unwrap(); | ||
// Reverse non-blocking flag set by `UdpSocketState` to make the test non-racy | ||
recv.set_nonblocking(false).unwrap(); | ||
|
||
let mut receive_buffer = vec![0; MAX_BUFFER_SIZE]; | ||
let mut meta = RecvMeta::default(); | ||
|
||
for gso_enabled in [false, true] { | ||
let mut group = c.benchmark_group(format!("gso_{}", gso_enabled)); | ||
group.throughput(criterion::Throughput::Bytes(TOTAL_BYTES as u64)); | ||
|
||
let segments = if gso_enabled { max_segments } else { 1 }; | ||
let msg = vec![0xAB; SEGMENT_SIZE * segments]; | ||
|
||
let transmit = Transmit { | ||
destination: dst_addr, | ||
ecn: None, | ||
contents: &msg, | ||
segment_size: gso_enabled.then_some(SEGMENT_SIZE), | ||
src_ip: None, | ||
}; | ||
|
||
group.bench_function("throughput", |b| { | ||
b.iter(|| { | ||
let mut sent: usize = 0; | ||
while sent < TOTAL_BYTES { | ||
send_state.send((&send).into(), &transmit).unwrap(); | ||
sent += transmit.contents.len(); | ||
|
||
let mut received_segments = 0; | ||
while received_segments < segments { | ||
let n = recv_state | ||
.recv( | ||
(&recv).into(), | ||
&mut [IoSliceMut::new(&mut receive_buffer)], | ||
slice::from_mut(&mut meta), | ||
) | ||
.unwrap(); | ||
assert_eq!(n, 1); | ||
received_segments += meta.len / meta.stride; | ||
} | ||
assert_eq!(received_segments, segments); | ||
} | ||
}) | ||
}); | ||
} | ||
} | ||
|
||
criterion_group!(benches, criterion_benchmark); | ||
criterion_main!(benches); |