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.
- 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
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 β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
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"
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.
- Installation & Quickstart Homebrew (macOS & Linux):
brew tap TarunVishwakarma1/homebrew-tap
brew install netspd
cargo install netspd
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
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)