# RustProxy 0.34.0: hot-path throughput revision **Status: uncompiled source candidate.** This revision does not change the application version, public API, dashboard controls, cache policy or tuning defaults. It must not be labelled production-ready until the new Rust binary passes compile, unit tests, live regressions and paired performance comparisons. ## Code changes and intended cost reductions | Focus | Change | Kept behavior / risk to verify | |---|---|---| | Per-request identity | Draw a 256-bit nonce from the OS-seeded/reseeded thread-local CSPRNG instead of asking `getrandom` on every request. Preserve SHA-256 of nonce+monotonic sequence and the existing 64-hex ID format. | IDs remain non-predictable. Check ID uniqueness and raw upstream headers. | | Upstream HTTP request target | Compile the validated scheme/authority `http::Uri` once with each immutable backend; parse only the request path+query and rebuild using typed `Uri::from_parts`. | Never accept a client-supplied authority, bypass DNS/address policies or change SNI. Test H1, H2, IPv6, query and percent-encoding. | | Load balancing | Do not clone the member ID string for an existing smooth-WRR scoreboard entry. Continue the previously introduced no-mutex single-member non-cookie path. | Sticky-cookie modes, capacity limits, retry exclusions, health and drain remain unchanged. | | Active health | Use already-compiled `Arc` when dispatching probes, avoiding a clone of its path/headers for each scheduled probe. | Same 250-ms supervisor, timeout, enabled/claim gate and health state transitions. | | Per-frame streaming | Capture the leased backend once at first streamed request DATA (response already captured at wrapper construction). Do not take `Exchange.backend` mutex on every upload chunk. | Request/response byte counters, mid-stream failures, idle timeouts and lease lifetime remain active. | | Pool recycling | Preserve exact request-count and elapsed-time recycling checks per request, with the existing independent 250-ms maintenance cycle. The pool factory/connection policy is unchanged. | Exact lifecycle semantics are more important than saving one cheap clock read; tune idle/age limits only after profiling. | | Log history | Move completed `LogEntry` directly into bounded history when there are no live viewers or enabled external sinks, instead of deeply cloning its strings. Continue cloning and delivering to live viewers/sinks when enabled. | Same JSON fields, history size, drop counters, file/Loki/Logstash forwarding. | | Route/HTTP instrumentation | Remove redundant route-ID mutex/write in forwarding and collapse H1/H2 version tallying into one branch. | Route is recorded once before forwarding; H1/H2 counters remain. | These changes build on the previous 0.34.0 route-Arc, single-backend LB, conditional retry/fallback-header cloning, atomic exchange flags and cache HOT LRU changes. There are no new UI toggles. Pool defaults remain `max_idle_per_host` 4 and `pool_recycle_requests` 25,000; tune these only in separately labelled trials. `sendfile: auto` remains opt-in and applies only to eligible Linux plaintext H1 static WWW responses, not reverse proxy or TLS/H2/H3. ## Cache transform/query policy An enabled `bypass_query` is a deliberate policy: `/theme.css?v=...` is a `BYPASS` even when the origin sends `Cache-Control: public`. Turning the bypass off permits a transformed CSS object to follow `MISS -> HIT` and appear in the cache dashboard. An existing transformed HOT row with hit count and TTL is positive evidence of this. This throughput revision does not modify the cache eligibility logic or discard Age/ETag/Cache-Control headers. ## Verification already possible here - **Old/reproducible reference executable only:** 110 passed, 0 failed, 1 skipped (`compression.codec.zstd` skipped because the optional decoder was missing), from live proxy/policy/cache/transform loopback regression. This does **not** exercise the newly modified Rust source. - **Old/reproducible reference executable only:** query bypass enabled gives `BYPASS -> BYPASS`, disabled gives `MISS -> HIT` and a transformed representation; the older Age regression is also reproducible on this old executable. - Source-only invariants: `scripts/tests/rps_hotpath_034_static_test.py` plus existing route/cache/sendfile checks. SQL migration and upgrade scripts pass. - **Not performed:** Rust compilation or newly added Rust unit tests, live behavior of the optimized binary, HTTP/2 live TLS, comparative RPS, CPU profiling and long-duration memory/health soak. The environment does not include `cargo`, `rustc` or `wrk`. No post-change RPS gain is claimed. ## Acceptance commands on a Rust-capable Linux host ```bash ./dev.sh check CARGO_INCREMENTAL=0 ./dev.sh test CARGO_INCREMENTAL=0 cargo build --release --locked python3 scripts/tests/rps_hotpath_034_static_test.py python3 scripts/tests/cache_age_transform_034_live.py \ --binary "$(realpath target/release/rust-proxy)" \ --output /tmp/rustproxy034-cache-after python3 scripts/performance/regression.py \ --binary optimized="$(realpath target/release/rust-proxy)" \ --out /tmp/rustproxy034-http-regression ``` Run `scripts/performance/benchmark.py` from the documented reproducible before/after/nginx command in `scripts/performance/README.md`. Compare the unchanged old 0.34.0 binary with the newly compiled source, not a baseline with different feature flags. Record RPS at 1,040 B, 64 KiB, 1 MiB, p95/p99, CPU/request, RSS, connection counts, errors and exact response-body hashes. Use `perf record -g -p ` during a stable request interval and inspect `perf report --stdio` to identify the next true bottleneck. Do not interpret Python origin self-tests, source inspections, or speculative Amdahl models as measured RustProxy throughput.