|
4 | 4 | // option. This file may not be copied, modified, or distributed
|
5 | 5 | // except according to those terms.
|
6 | 6 |
|
7 |
| -#![expect(clippy::unwrap_used, reason = "OK in a bench.")] |
| 7 | +use std::{hint::black_box, time::Duration}; |
8 | 8 |
|
9 |
| -use std::{hint::black_box, iter::repeat_with}; |
10 |
| - |
11 |
| -use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; |
12 |
| -use neqo_crypto::AuthenticationStatus; |
13 |
| -use neqo_http3::{Http3Client, Http3Parameters, Http3Server, Priority}; |
14 |
| -use neqo_transport::{ConnectionParameters, StreamType}; |
| 9 | +use criterion::{criterion_group, criterion_main, Criterion, Throughput}; |
15 | 10 | use test_fixture::{
|
16 |
| - fixture_init, http3_client_with_params, http3_server_with_params, now, DEFAULT_SERVER_NAME, |
| 11 | + boxed, fixture_init, |
| 12 | + sim::{ |
| 13 | + http3_connection::{Node, Requests, Responses}, |
| 14 | + network::{RandomDelay, TailDrop}, |
| 15 | + ReadySimulator, Simulator, |
| 16 | + }, |
17 | 17 | };
|
18 | 18 |
|
19 |
| -const STREAM_TYPE: StreamType = StreamType::BiDi; |
20 |
| -const STREAMS_MAX: u64 = 1 << 60; |
21 |
| - |
22 |
| -fn use_streams(client: &mut Http3Client, server: &mut Http3Server, streams: usize, data: &[u8]) { |
23 |
| - let stream_ids = repeat_with(|| { |
24 |
| - client |
25 |
| - .fetch( |
26 |
| - now(), |
27 |
| - "GET", |
28 |
| - &("https", DEFAULT_SERVER_NAME, "/"), |
29 |
| - &[], |
30 |
| - Priority::default(), |
31 |
| - ) |
32 |
| - .unwrap() |
33 |
| - }) |
34 |
| - .take(streams) |
35 |
| - .collect::<Vec<_>>(); |
36 |
| - exchange_packets(client, server, false); |
37 |
| - for stream_id in &stream_ids { |
38 |
| - client.send_data(*stream_id, data).unwrap(); |
39 |
| - } |
40 |
| - exchange_packets(client, server, false); |
41 |
| - for stream_id in &stream_ids { |
42 |
| - client.stream_close_send(*stream_id).unwrap(); |
43 |
| - } |
44 |
| - exchange_packets(client, server, false); |
45 |
| -} |
46 |
| - |
47 |
| -fn connect() -> (Http3Client, Http3Server) { |
48 |
| - let cp = ConnectionParameters::default() |
49 |
| - .max_streams(STREAM_TYPE, STREAMS_MAX) |
50 |
| - .pmtud(false) |
51 |
| - .pacing(false) |
52 |
| - .mlkem(false) |
53 |
| - .sni_slicing(false); |
54 |
| - let h3p = Http3Parameters::default().connection_parameters(cp); |
55 |
| - let mut client = http3_client_with_params(h3p.clone()); |
56 |
| - let mut server = http3_server_with_params(h3p); |
57 |
| - exchange_packets(&mut client, &mut server, true); |
58 |
| - (client, server) |
59 |
| -} |
| 19 | +const ZERO: Duration = Duration::from_millis(0); |
| 20 | +const JITTER: Duration = Duration::from_millis(10); |
60 | 21 |
|
61 | 22 | fn criterion_benchmark(c: &mut Criterion) {
|
62 | 23 | fixture_init();
|
63 | 24 |
|
64 |
| - for (streams, data_size) in [(1_000, 1), (1_000, 1_000)] { |
65 |
| - let mut group = c.benchmark_group(format!("{streams} streams of {data_size} bytes")); |
| 25 | + for (streams, data_size) in [(1usize, 1_000usize), (1_000, 1), (1_000, 1_000)] { |
| 26 | + let setup = || { |
| 27 | + let nodes = boxed![ |
| 28 | + Node::default_client(boxed![Requests::new(streams, data_size)]), |
| 29 | + TailDrop::dsl_uplink(), |
| 30 | + RandomDelay::new(ZERO..JITTER), |
| 31 | + Node::default_server(boxed![Responses::new(streams, data_size)]), |
| 32 | + TailDrop::dsl_uplink(), |
| 33 | + RandomDelay::new(ZERO..JITTER), |
| 34 | + ]; |
| 35 | + Simulator::new("", nodes).setup() |
| 36 | + }; |
| 37 | + let routine = |sim: ReadySimulator| black_box(sim.run()); |
| 38 | + |
| 39 | + let mut group = c.benchmark_group(format!("{streams}-streams/each-{data_size}-bytes")); |
| 40 | + |
| 41 | + // Benchmark with wallclock time, i.e. measure the compute efficiency. |
| 42 | + group.bench_function("wallclock-time", |b| { |
| 43 | + b.iter_batched(setup, routine, criterion::BatchSize::SmallInput); |
| 44 | + }); |
66 | 45 |
|
67 |
| - // High variance benchmark. Increase default sample size (100). |
68 |
| - group.sample_size(500); |
| 46 | + // Benchmark with simulated time, i.e. measure the network protocol |
| 47 | + // efficiency. |
| 48 | + // |
| 49 | + // Note: Given that this is using simulated time, we can measure actual |
| 50 | + // throughput. |
| 51 | + group.throughput(Throughput::Bytes((streams * data_size) as u64)); |
| 52 | + group.bench_function("simulated-time", |b| { |
| 53 | + b.iter_custom(|iters| { |
| 54 | + let mut d_sum = Duration::ZERO; |
| 55 | + for _i in 0..iters { |
| 56 | + d_sum += setup().run(); |
| 57 | + } |
69 | 58 |
|
70 |
| - group.bench_function("multistream", |b| { |
71 |
| - let data = vec![0; data_size]; |
72 |
| - b.iter_batched_ref( |
73 |
| - connect, |
74 |
| - |_| black_box(|(client, server)| use_streams(client, server, streams, &data)), |
75 |
| - BatchSize::SmallInput, |
76 |
| - ); |
| 59 | + d_sum |
| 60 | + }); |
77 | 61 | });
|
| 62 | + |
78 | 63 | group.finish();
|
79 | 64 | }
|
| 65 | + |
| 66 | + Criterion::default().configure_from_args().final_summary(); |
80 | 67 | }
|
81 | 68 |
|
82 | 69 | criterion_group!(benches, criterion_benchmark);
|
|
0 commit comments