fn auto_tuning_approximates_bandwidth_delay_product()

in neqo-transport/src/fc.rs [1120:1223]


    fn auto_tuning_approximates_bandwidth_delay_product() -> Res<()> {
        const DATA_FRAME_SIZE: u64 = 1_500;
        /// Allow auto-tuning algorithm to be off from actual bandwidth-delay
        /// product by up to 1KiB.
        const TOLERANCE: u64 = 1024;

        test_fixture::fixture_init();

        // Run multiple iterations with randomized bandwidth and rtt.
        for _ in 0..1_000 {
            // Random bandwidth between 1 Mbit/s and 1 Gbit/s.
            let bandwidth =
                u64::from(u16::from_be_bytes(random::<2>()) % 1_000 + 1) * 1_000 * 1_000;
            // Random delay between 1 ms and 256 ms.
            let rtt = Duration::from_millis(u64::from(random::<1>()[0]) + 1);
            let bdp = bandwidth * u64::try_from(rtt.as_millis()).unwrap() / 1_000 / 8;

            let mut now = Instant::now();

            let mut send_to_recv = VecDeque::new();
            let mut recv_to_send = VecDeque::new();

            let mut last_max_active = INITIAL_RECV_WINDOW_SIZE as u64;
            let mut last_max_active_changed = now;

            let mut sender_window = INITIAL_RECV_WINDOW_SIZE as u64;
            let mut fc =
                ReceiverFlowControl::new(StreamId::new(0), INITIAL_RECV_WINDOW_SIZE as u64);

            loop {
                // Sender receives window updates.
                if recv_to_send.front().is_some_and(|(at, _)| *at <= now) {
                    let (_, update) = recv_to_send.pop_front().unwrap();
                    sender_window += update;
                }

                // Sender sends data frames.
                let sender_progressed = if sender_window > 0 {
                    let to_send = min(DATA_FRAME_SIZE, sender_window);
                    send_to_recv.push_back((now, to_send));
                    sender_window -= to_send;
                    now += Duration::from_secs_f64(to_send as f64 * 8.0 / bandwidth as f64);
                    true
                } else {
                    false
                };

                // Receiver receives data frames.
                let mut receiver_progressed = false;
                if send_to_recv.front().is_some_and(|(at, _)| *at <= now) {
                    let (_, data) = send_to_recv.pop_front().unwrap();
                    let consumed = fc.set_consumed(fc.retired() + data)?;
                    fc.add_retired(consumed);

                    // Receiver sends window updates.
                    let prev_max_allowed = fc.max_allowed;
                    if write_frames(&mut fc, rtt, now) == 1 {
                        recv_to_send.push_front((now, fc.max_allowed - prev_max_allowed));
                        receiver_progressed = true;
                        if last_max_active < fc.max_active() {
                            last_max_active = fc.max_active();
                            last_max_active_changed = now;
                        }
                    }
                }

                // When idle, travel in (simulated) time.
                if !sender_progressed && !receiver_progressed {
                    now = [recv_to_send.front(), send_to_recv.front()]
                        .into_iter()
                        .flatten()
                        .map(|(at, _)| *at)
                        .min()
                        .expect("both are None");
                }

                // Consider auto-tuning done once receive window hasn't changed for 4 RTT.
                if now.duration_since(last_max_active_changed) > 4 * rtt {
                    break;
                }
            }

            let summary = format!(
                "Got receive window of {} MiB on connection with bandwidth {} MBit/s ({bandwidth} Bit/s), delay {rtt:?}, bdp {} MiB.",
                fc.max_active() / 1024 / 1024,
                bandwidth / 1_000 / 1_000,
                bdp / 1024 / 1024,
            );

            assert!(
                fc.max_active() + TOLERANCE >= bdp || fc.max_active() == MAX_RECV_WINDOW_SIZE,
                "{summary} Receive window is smaller than the bdp."
            );
            assert!(
                fc.max_active - TOLERANCE <= bdp
                    || fc.max_active == INITIAL_RECV_WINDOW_SIZE as u64,
                "{summary} Receive window is larger than the bdp."
            );

            qdebug!("{summary}");
        }

        Ok(())
    }