f512478bcc
`AudioLatencyComparisonTest`:
- Three new scenarios: 10 %, 20 %, 30 % loss in addition to the
existing clean and 5 %. The whole benchmark now sweeps a useful
arc for finding the breakdown point.
- Frame-count floor now scales with loss instead of a fixed 60 %
threshold. QUIC streams are reliable so loss surfaces mainly as
latency, but at high rates the retransmit + congestion-control
feedback can eat into the 10 s window, so the floor relaxes to
`max(50, (1 - 3*lossRate) * EXPECTED_FRAMES)`. The 50-frame
absolute floor (= 1 s of audio) catches a catastrophic publisher
failure without flapping on the loaded loss-path runs.
Linux benchmark harness (`nestsClient/tests/hang-interop/linux-bench/`):
- `Dockerfile` for an arm64/amd64 image with JDK 21 + rustc 1.95 +
cmake + the *-sys-crate build deps (libssl-dev, build-essential,
pkg-config). Pins rustc 1.95 explicitly so moq-relay v0.10.25's
Cargo.lock-requested `constant_time_eq@0.4.3` builds cleanly.
- `run.sh` wrapper that:
* builds the image,
* unpacks a filtered tarball of the host repo into the container
(mac host `nestsClient/build/` and `cargo target/` stay
untouched),
* symlinks `nestsClient/build` -> `/persistent-gradle-build` and
`nestsClient/tests/hang-interop/target` ->
`/persistent-cargo-target` so successive runs reuse compiled
artefacts (~3-5 min cached vs ~7-15 min cold),
* runs the gradle test invocation and surfaces the JUnit XML
stats to `linux-bench/out/`.
Linux numbers observed (arm64 Docker on a MacBook M2, 10 s window):
| Loss | Stack | p50 | p95 | p99 | max | Frames |
|------|--------|-------|-------|-------|-------|--------|
| 0 % | Kotlin | 61.1 | 63.1 | 65.5 | 79.1 | 573 |
| 0 % | Rust | 100.7 | 102.7 | 104.9 | 140.2 | 495 |
| 5 % | Kotlin | 380.9 | 383.4 | 385.7 | 390.5 | 556 |
| 5 % | Rust | 0.7 | 7.3 | 23.2 | 84.2 | 500 |
| 10 % | Kotlin | 120.5 | 122.4 | 124.0 | 132.6 | 568 |
| 10 % | Rust | 0.5 | 21.9 | 60.4 | 84.4 | 500 |
| 20 % | Kotlin | 159.7 | 164.3 | 170.3 | 183.1 | 566 |
| 20 % | Rust | 1.6 | 61.3 | 101.9 | 144.9 | 499 |
| 30 % | Kotlin | 181.0 | 184.2 | 188.1 | 194.0 | 566 |
| 30 % | Rust | 1.2 | 80.7 | 105.3 | 140.8 | 491 |
Notes for future readers: Rust's p50 collapsing to ~1 ms under loss
is the SUBSCRIBE-late-arrival signal, not "Rust is 100x faster" — by
the time the SUBSCRIBE lands at the publisher, the in-flight
encoder has moved past those early frames, so the listener starts
receiving in near-real-time. Read p95/p99/max for the per-frame
story (Rust expands 7 -> 22 -> 61 -> 80 ms p95 across loss rates).
Frame delivery is stable for both stacks even at 30 % loss on Linux,
unlike the macOS run which hits a 3.4 s Rust catastrophe at 30 %.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
37 lines
1.5 KiB
Docker
37 lines
1.5 KiB
Docker
# Linux audio-latency benchmark image for AudioLatencyComparisonTest.
|
|
# Mirrors the macOS host toolchain (JDK 21, rustc 1.95, cmake 3) so the
|
|
# Kotlin vs Rust hang-publish comparison runs end-to-end against the
|
|
# same set of sidecars, just on a different OS.
|
|
|
|
FROM eclipse-temurin:21-jdk-jammy
|
|
|
|
# rustup pulls 1.95.0 explicitly. cmake/build-essential/pkg-config/libssl-dev
|
|
# are needed by transitive *-sys crates (audiopus_sys bundles libopus and
|
|
# builds it via cmake; rustls→aws-lc-sys also uses cmake).
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
curl ca-certificates git \
|
|
build-essential pkg-config cmake \
|
|
libssl-dev \
|
|
bash \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
ENV RUSTUP_HOME=/opt/rustup \
|
|
CARGO_HOME=/opt/cargo \
|
|
PATH=/opt/cargo/bin:$PATH
|
|
|
|
# Pin rustc 1.95.0 to match the host. moq-relay v0.10.25's transitive
|
|
# Cargo.lock requires rustc >= 1.95 (constant_time_eq@0.4.3).
|
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh \
|
|
&& sh /tmp/rustup.sh -y --default-toolchain 1.95.0 --profile minimal \
|
|
&& rm /tmp/rustup.sh \
|
|
&& rustc --version && cargo --version
|
|
|
|
# CMake 4.x stripped support for very old `cmake_minimum_required` floors,
|
|
# which audiopus_sys's bundled libopus CMakeLists trips over. Jammy ships
|
|
# cmake 3.22 (still affected by some old crate `*-sys` requirements but
|
|
# tolerates the policy). Set the env var defensively to match the
|
|
# gradle Exec tasks.
|
|
ENV CMAKE_POLICY_VERSION_MINIMUM=3.5
|
|
|
|
WORKDIR /repo
|