DEV Community

Tarun Vishwakarma
Tarun Vishwakarma

Posted on

Why Your 500 Mbps Internet Still Lags: Building a Zero-Panic, Bufferbloat-Aware Speed Tester in Rust πŸ¦€

Ever stared at a speed test reporting "300 Mbps Down / 50 Mbps Up" right after your video call glitched or your game lagged?

Traditional speed test utilities report pipe width (raw bandwidth), but they rarely test pipe responsiveness. When your network is saturated, unmanaged router buffers fill up, causing round-trip latency to spike into hundreds of milliseconds. This is bufferbloatβ€”and it's the real reason high-speed connections stutter.

To fix this blind spot and avoid leaving the terminal, I built netspd: a fast, zero-panic, bufferbloat-aware network measurement tool written in Rust with an instrument-cluster terminal UI.

  1. The Core Problem: Why Throughput Numbers Lie When a connection is idle, ping is low. But when transfers happen simultaneously, packets get queued up:
Idle Latency:   [Ping Packet] ───────────────────────────▢ 14 ms
Under Load:     [Ping Packet] ───[BUFFER QUEUE (450ms)]──▢ High Jitter / Lag
Enter fullscreen mode Exit fullscreen mode

netspd evaluates connection health across three dimensions:

  • Active Latency Sampling: Measures round-trip times continuously during both download and upload saturation.
  • Bufferbloat Grade ($A+\text{ to }F$): Quantifies responsiveness under full load compared to baseline idle latency.
  • Plain-Language Verdict: Outputs actionable diagnostics like:"Good for 4K streaming Β· Video calls may stutter under load"

Architecture & Rust Implementation

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   netspd core engine                   β”‚
β”‚         (Tokio runtime β€’ Provider Abstraction)         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚ Typed EngineEvents (mpsc)
            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
            β–Ό               β–Ό               β–Ό
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚ Ratatui TUI β”‚ β”‚ JSON / CSV  β”‚ β”‚ Prometheus  β”‚
     β”‚  Interface  β”‚ β”‚   Stream    β”‚ β”‚   Exporter  β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

A. Decoupled, UI-Agnostic Core
The engine never imports the UI crate. It communicates solely by emitting typed EngineEvent instances over an asynchronous channel. When no TTY is detected (such as inside a Docker container or Kubernetes CronJob), netspd drops to headless mode automatically.

B. Zero-Panic Discipline
Speed testing involves hostile network environmentsβ€”dropped sockets, abrupt resets, and DNS timeouts. To ensure stability, panics are prevented at compile time via Cargo.toml:

Ini, TOML
[lints.clippy]
unwrap_used = "deny"
expect_used = "deny"
panic = "deny"
Enter fullscreen mode Exit fullscreen mode

Every fallible branch across DNS resolution, socket initialization, and provider failover is strictly handled.

C. Streaming Transfers with Clamped-Alpha EMA
Benchmarking gigabit links shouldn't allocate gigabytes of memory. Data chunks are streamed directly into discard sinks across concurrent Tokio tasks. Throughput smoothing is computed using a decoupled Exponential Moving Average (EMA), keeping memory flat regardless of duration.

D. Graceful ICMP Fallback
Accurate packet loss measurement relies on raw ICMP echoes via surge-ping. In environments lacking CAP_NET_RAW (e.g., rootless containers), netspd catches socket privilege limits and cleanly degrades to HTTP-based latency estimation without failing the test run.

  1. Installation & Quickstart Homebrew (macOS & Linux):
brew tap TarunVishwakarma1/homebrew-tap
brew install netspd
Enter fullscreen mode Exit fullscreen mode
cargo install netspd
Enter fullscreen mode Exit fullscreen mode

Common Commands

# Interactive TUI mode
netspd

# Headless JSON output (for scripting)
netspd --no-tui --json

# CI Gate: Exit non-zero if throughput falls below threshold
netspd --fail-below 100mbps

# Start a local measurement server for LAN benchmarking
netspd serve --port 8080
Enter fullscreen mode Exit fullscreen mode

Try It Out & Share Your Results
netspd is completely open-source. If you run a test, what bufferbloat grade did your setup receive?

πŸ™ Source Code: github.com/TarunVishwakarma1/netspd

🍺 Homebrew Tap: github.com/TarunVishwakarma1/homebrew-tap

Feel free to drop feedback, report edge cases, or share ideas in the comments below!

Top comments (0)