ci: remove flaky Windows benchmark (#8941)

This tunnel throughput benchmark isn't a very useful benchmark and it is
very flaky. Remove it entirely until we can replace it with something
more robust and useful.

Resolves: #8172
This commit is contained in:
Thomas Eizinger
2025-05-01 00:24:21 +10:00
committed by GitHub
parent 6f11568c8c
commit 8a201494d0
3 changed files with 0 additions and 192 deletions

View File

@@ -17,25 +17,6 @@ env:
RUSTDOCFLAGS: "-D warnings"
jobs:
bench:
name: bench-${{ matrix.runs-on }}
strategy:
fail-fast: false
matrix:
runs-on: [
windows-2019, # Only platform with a benchmark right now
]
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: ./.github/actions/setup-rust
id: setup-rust
- run: cargo bench ${{ steps.setup-rust.outputs.bench-packages }}
env:
RUST_LOG: "debug"
name: "cargo bench"
shell: bash
static-analysis:
name: static-analysis-${{ matrix.runs-on }}
strategy:

View File

@@ -70,7 +70,3 @@ tokio = { workspace = true, features = ["net", "time"] }
[lints]
workspace = true
[[bench]]
name = "tunnel"
harness = false

View File

@@ -1,169 +0,0 @@
#![allow(clippy::unwrap_used)]
use anyhow::Result;
fn main() -> Result<()> {
let _guard = firezone_logging::test("debug");
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(platform::perf())?;
Ok(())
}
#[cfg(not(target_os = "windows"))]
mod platform {
#[expect(
clippy::unused_async,
reason = "Must match signature of Windows platform"
)]
pub(crate) async fn perf() -> anyhow::Result<()> {
Ok(())
}
}
/// Synthetic performance test
///
/// Echoes UDP packets between a local socket and the Wintun interface
#[cfg(target_os = "windows")]
mod platform {
use anyhow::Result;
use firezone_bin_shared::TunDeviceManager;
use std::{
future::poll_fn,
net::{Ipv4Addr, Ipv6Addr},
time::Duration,
};
use tokio::{
net::UdpSocket,
time::{Instant, timeout},
};
pub(crate) async fn perf() -> Result<()> {
const MTU: usize = 1_280;
const NUM_REQUESTS: u64 = 1_000;
const REQ_CODE: u8 = 42;
const REQ_LEN: usize = 1_000;
const RESP_CODE: u8 = 43;
const SERVER_PORT: u16 = 3000;
const NUM_THREADS: usize = 1; // Note: Unused on Windows.
let ipv4 = Ipv4Addr::from([100, 90, 215, 97]);
let ipv6 = Ipv6Addr::from([0xfd00, 0x2021, 0x1111, 0x0, 0x0, 0x0, 0x0016, 0x588f]);
let mut device_manager = TunDeviceManager::new(MTU, NUM_THREADS)?;
let mut tun = device_manager.make_tun()?;
device_manager.set_ips(ipv4, ipv6).await?;
device_manager.set_routes(vec![ipv4.into()], vec![]).await?;
let server_addr = (ipv4, SERVER_PORT).into();
// Listen for incoming packets on Wintun, and echo them.
let server_task = tokio::spawn(async move {
tracing::debug!("Server task entered");
let mut requests_served = 0;
let mut time_spent = Duration::from_millis(0);
loop {
let mut buf = Vec::with_capacity(1);
poll_fn(|cx| tun.poll_recv_many(cx, &mut buf, 1)).await;
let original_pkt = buf.remove(0);
let start = Instant::now();
let Some(original_udp) = original_pkt.as_udp() else {
continue;
};
if original_udp.destination_port() != SERVER_PORT {
continue;
}
if original_udp.payload()[0] != REQ_CODE {
panic!("Wrong request code");
}
poll_fn(|cx| tun.poll_send_ready(cx)).await.unwrap();
tun.send(
ip_packet::make::udp_packet(
original_pkt.destination(),
original_pkt.source(),
original_udp.destination_port(),
original_udp.source_port(),
vec![RESP_CODE],
)
.unwrap(),
)?;
requests_served += 1;
time_spent += start.elapsed();
if requests_served >= NUM_REQUESTS {
break;
}
}
tracing::info!(?time_spent, "Server all good");
Ok::<_, anyhow::Error>(())
});
// Wait for Wintun to be ready, then send it UDP packets and listen for
// the echo.
let client_task = tokio::spawn(async move {
// We'd like to hit 90 Mbps up which is nothing special but it's a good
// start.
// TODO: Investigate why we can't hit 100 anymore with the additional thread.
const EXPECTED_BITS_PER_SECOND: u64 = 80_000_000;
// This has to be an `Option` because Windows takes about 4 seconds
// to get the interface ready.
let mut start_instant = None;
tracing::debug!("Client task entered");
let sock = UdpSocket::bind("0.0.0.0:0").await?;
let mut responses_received = 0;
let mut req_buf = vec![0u8; REQ_LEN];
req_buf[0] = REQ_CODE;
loop {
let Ok(_) = sock.send_to(&req_buf, server_addr).await else {
// It seems to take a few seconds for Windows to set everything up.
tracing::warn!("Failed to send");
tokio::time::sleep(Duration::from_secs(1)).await;
continue;
};
start_instant.get_or_insert_with(Instant::now);
let mut recv_buf = [0u8; MTU];
let Ok((bytes_received, packet_src)) = sock.recv_from(&mut recv_buf).await else {
tracing::warn!("Timeout or couldn't recv packet");
continue;
};
if packet_src != server_addr {
tracing::warn!("Packet not from server");
continue;
}
assert_eq!(bytes_received, 1);
assert_eq!(recv_buf[0], RESP_CODE);
responses_received += 1;
if responses_received >= NUM_REQUESTS {
break;
}
}
let actual_dur = start_instant.unwrap().elapsed();
// The 1_000_000 is needed to get decent precision without floats
let actual_bps =
NUM_REQUESTS * REQ_LEN as u64 * 8 * 1_000_000 / actual_dur.as_micros() as u64;
assert!(
actual_bps >= EXPECTED_BITS_PER_SECOND,
"{:?} < {:?}",
actual_bps,
EXPECTED_BITS_PER_SECOND
);
tracing::info!(?actual_bps, "Client all good");
Ok::<_, anyhow::Error>(())
});
timeout(Duration::from_secs(30), async move {
client_task.await??;
server_task.await??;
Ok::<_, anyhow::Error>(())
})
.await??;
Ok(())
}
}