feat: SRTT-based nameserver selection #19

Merged
razvandimescu merged 4 commits from feat/srtt-nameserver-selection into main 2026-03-29 05:22:32 +08:00
razvandimescu commented 2026-03-29 04:41:24 +08:00 (Migrated from github.com)

Summary

  • BIND-style Smoothed RTT (EWMA) tracking per nameserver IP address — resolver learns which NS respond fastest and prefers them
  • Eliminates cascading timeouts from slow/unreachable IPv6 servers forced through TCP
  • New src/srtt.rs module: SrttCache with per-IP RTT recording, failure penalty (5s), decay (5min), TCP penalty (+100ms)
  • enabled flag embedded in SrttCache — all methods become no-ops when disabled, no boolean threading through signatures
  • Extracted tcp_with_srtt helper to deduplicate 4 identical TCP match arms in send_query
  • Batch eviction (64 entries) for amortized O(1) writes at capacity (was O(N) per write)
  • Configurable via [upstream] srtt = true/false (default: true)
  • Benchmark script scripts/benchmark.sh with compare-srtt, compare-dnssec, compare-all modes

Benchmarks (40 domains, warm SRTT + cold cache)

Metric SRTT OFF SRTT ON
Avg 2842ms 237ms (12x)
Median 1322ms 204ms (6.5x)
P95 9651ms 405ms (24x)
>1s 58% 0%

Test plan

  • make all passes (fmt, clippy, audit, build, 90 tests)
  • 8 SRTT unit tests including disabled_is_noop, eviction_removes_oldest
  • Existing 82 tests unchanged and passing
  • Benchmarked A/B with scripts/benchmark.sh compare-all
  • Manual: dig @127.0.0.1 google.com resolves <200ms after warmup
  • Manual: set srtt = false in config, verify slower resolution

🤖 Generated with Claude Code

## Summary - BIND-style Smoothed RTT (EWMA) tracking per nameserver IP address — resolver learns which NS respond fastest and prefers them - Eliminates cascading timeouts from slow/unreachable IPv6 servers forced through TCP - New `src/srtt.rs` module: `SrttCache` with per-IP RTT recording, failure penalty (5s), decay (5min), TCP penalty (+100ms) - `enabled` flag embedded in `SrttCache` — all methods become no-ops when disabled, no boolean threading through signatures - Extracted `tcp_with_srtt` helper to deduplicate 4 identical TCP match arms in `send_query` - Batch eviction (64 entries) for amortized O(1) writes at capacity (was O(N) per write) - Configurable via `[upstream] srtt = true/false` (default: `true`) - Benchmark script `scripts/benchmark.sh` with `compare-srtt`, `compare-dnssec`, `compare-all` modes ## Benchmarks (40 domains, warm SRTT + cold cache) | Metric | SRTT OFF | SRTT ON | |---|---|---| | Avg | 2842ms | **237ms** (12x) | | Median | 1322ms | **204ms** (6.5x) | | P95 | 9651ms | **405ms** (24x) | | >1s | 58% | **0%** | ## Test plan - [x] `make all` passes (fmt, clippy, audit, build, 90 tests) - [x] 8 SRTT unit tests including `disabled_is_noop`, `eviction_removes_oldest` - [x] Existing 82 tests unchanged and passing - [x] Benchmarked A/B with `scripts/benchmark.sh compare-all` - [x] Manual: `dig @127.0.0.1 google.com` resolves <200ms after warmup - [x] Manual: set `srtt = false` in config, verify slower resolution 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.