Files
RustProxy/docs/TEST_REPORT_0.34.0.md
T
2026-10-18 06:13:42 +02:00

222 lines
13 KiB
Markdown

# RustProxy 0.34.0 verification report
## Acceptance status
**Source candidate, not verified production release.** Rust (`cargo`, `rustc`) is
not installed in this execution environment, and the runtime has no access to
its dependency registry. Consequently the modified Rust source was **not
compiled**, the new Rust tests were **not executed**, and no 0.34.0 RustProxy
binary or live throughput figures are supplied. Source inspection and simulated
UI/cache tests do not close the runtime acceptance gate.
## DEV 1 KiB reverse-proxy follow-up (October 2026; source only)
The supplied **old executable** passed loopback HTTP/1.1 1,040-byte content
checks and ApacheBench 12,000-request samples. The configuration trial
`max_idle_per_host=4 -> 64` increased short-run RPS, but shared-CPU noise
precludes a stable nginx-parity percentage. The edited sources now use 64 by
default for absent/new keepalive fields and reduce exclusive-Drop mutex/clone
and absent-cookie overhead. See `docs/PROXY_1KB_HOTPATH_DEV_0.34.0.md`.
**No newly modified binary was built or run.** Rust unit tests, runtime
regressions, long soaks and post-edit code A/B are still required.
Current DEV source checks performed on the modified tree:
| Check | Result | Scope |
|---|---|---|
| `./dev.sh doctor` | PASS | Source preflight; reports `cargo` and `rustc` absent |
| `scripts/tests/rps_hotpath_034_static_test.py` | PASS | Guardrails, defaults, retained routing/security and source-size limits only |
| `scripts/tests/proxy_hotpath_034_static_test.py` | PASS | Routing and telemetry source guards only |
| `scripts/tests/cache_scope_034_static_test.py`, `cache_hot_034_static_test.py`, `sendfile_034_static_test.py` | PASS | Cache and WWW source guards only |
| `scripts/tests/dashboard_presets_sql_test.py` | PASS | SQLite migrations and preset constraints |
| `scripts/tests/upgrade_performance_test.py` | PASS | Disposable upgrade/preservation/locking test |
| `scripts/tests/sendfile_034_panel_browser_test.py` | PASS, 2 widths | Simulated Chromium admin API, not live Rust |
| `scripts/tests/vhost_backend_popup_0337_browser_test.py` | PASS, 4 widths | Simulated Chromium admin API, not live Rust |
| Node `--check` (vhost editor), Python `compileall`, JSON parser (OpenAPI) | PASS | Syntax only |
| `./dev.sh check`, `./dev.sh test` | BLOCKED, exit 127 | Rust toolchain missing; no Rust unit/build acceptance |
| Old supplied binary, `ab`/nginx configuration A/B | COMPLETED, DIAGNOSTIC | 1,040-byte H1 payload; shared-CPU and no new code exercised |
## Later 0.34.0 reverse-proxy optimization revision
The refreshed source archive additionally reuses immutable route handles,
limits lazy host wildcard allocation, fast-paths one-backend non-cookie LB,
atomically caches healthy state and exchange scalar log fields, shares
compiled per-member health policies across leases, and avoids
unneeded fallback/retry header clones and empty-subscriber broadcast clones.
The existing cache/sendfile work and all panel controls remain. Added Rust
regression cases and the source-only hot-path guard are **not a substitute**
for compilation and live HTTP, health, capacity, sticky, and H2 retry tests.
No RPS improvement, corrected nginx gap, or full functional parity has been
measured for this new revision. Details: `docs/PROXY_HOTPATH_0.34.0.md`.
## RPS-focused follow-up source revision (not yet compiled)
See `docs/PROXY_RPS_0.34.0.md` for detailed changes in request IDs, validated
upstream URI construction, LB scheduling, probes, streaming byte accounting,
unchanged pool generation lifetimes and log-history ownership. Source-only invariants pass.
A live test of the PREVIOUS executable (not this source revision) completed
110 passing cases, 0 failing cases and 1 skipped optional zstd decoder in the
proxy/policy/cache/transform harness. The old executable also confirms query-
string bypass is deliberate and reproduces the older Age/TTL bug. The new
binary has NOT been built or tested and its RPS gain is unknown.
## HOT HIT follow-up source revision (not yet compiled)
See `docs/CACHE_HOTPATH_0.34.0.md`. Response header cloning has moved outside
the global HOT lock, and redundant bounded stats key allocation, empty BAN
checks and full HOT TTL sweeps were removed. A new Rust concurrency/regression
suite and an ignored microbenchmark have been added. Existing COLD and Vary
behavior, exact LRU and cache semantics remain. This source has not been built
or run under Rust in this environment; no RPS gain is claimed.
## Changes and correctness boundaries
- Operational per-vhost saves (upstream keepalive/recycling, connection limits,
load-balancing/health policy, timeouts, request gate and diagnostics) retain
HOT and COLD entries. Backend origin, routing, content, cache and transform
changes retain conservative invalidation. Vhost-specific changes purge only
that vhost; global cache, transform, forwarding, headers and Web Service or
PHP-FPM profile changes may conservatively purge all tiers.
- Scope-specific cold-cache records persist an origin/content compatibility
fingerprint. COLD startup rejects stale scope records and deletes their cache
artifacts. Legacy COLD metadata defaults its fingerprint to zero; production
vhosts have a nonzero SHA-derived fingerprint. A one-time cold refill can
occur on the 0.33.8 -> 0.34.0 upgrade because the global identity changed.
- A separate administrative configuration revision acts as a cache-ticket
publication barrier: a request bound to a pre-save routing snapshot cannot
create a new cache ticket after the save. The data revision stays stable for
operational-only saves, so previously cached objects remain available.
- Reverse-proxy response-body byte metering captures the backend lease once at
wrapper creation instead of acquiring a backend-selection mutex per DATA
frame. Request-body accounting, error paths and exchange ownership remain.
- An **opt-in `sendfile: auto`** setting is wired through Web Service serde,
compiled config, the Delivery UI and documented API. The Linux HTTP/1.1
TCP transport adapter calls `libc::sendfile` for eligible static files;
cache-enabled, ranged, compressed, transformed and TLS/H2/H3 paths retain
existing streaming. It is **disabled by default** and must pass native
compilation, correctness, transport and load tests before use. No persisted
SQLite schema migration or LB UI change is required.
## Local verification
| Check | Outcome | Coverage / caveat |
|---|---|---|
| `./dev.sh doctor` | PASS | Project source layout and tool inventory |
| SQL migration/preset test | PASS | All ten migrations re-applied, preset access and limits |
| Upgrade test | PASS | Stop/lock guards, SQLite/.env/language preservation, symlink rejection |
| Python compileall | PASS | Python syntax only |
| Vhost LB/Cache Chromium test | PASS | Simulated browser quick-view, 320/375/768/1440px |
| Other Chromium scripts | 15 PASS | Simulated API/CSS/JS, not a live Rust server |
| Sidebar navigation Chromium test | INCOMPLETE | Execution time budget; not counted as a pass |
| Three Node dashboard scripts | PASS | Simulated UI logic |
| `./dev.sh check` and `./dev.sh test` | BLOCKED | `cargo`/`rustc` unavailable |
| Rust unit/integration tests (including new scoped COLD regression) | NOT RUN | Requires Rust toolchain |
| Live HTTP/protocol/LB regressions | NOT RUN | Requires built 0.34.0 binary |
| 0.33.8 / 0.34.0 / nginx paired RPS benchmarks | NOT RUN | No verified 0.34.0 binary |
| Zero-copy sendfile WWW setting | SOURCE IMPLEMENTED / NOT RUNTIME VERIFIED | Linux plain H1 static GET only, `off` by default |
| Sendfile editor Chromium save/reload | PASS | 375/1440px, simulated admin API, off -> auto -> off |
| Sendfile Rust adapter + fallback test code | ADDED / NOT RUN | TCP marker replacement, persistent socket, HEAD, range, conditional; compiler unavailable |
| Amdahl sendfile/nginx sensitivity study | PASS MODEL | No runtime evidence for simulated improvements |
The 0.33.8 report in the supplied evidence archive recorded **706 passing
Rust tests**, **152 HTTP assertions**, **111 transport assertions** and
**17 LB assertions**. Those are *prior-version* results and are **not evidence
that 0.34.0 passes**. This report never transfers previous pass counts.
## Synthetic cache-retention scenario (not an RPS measurement)
Run:
```bash
python3 scripts/performance/simulate_cache_034.py
```
Assume 20 vhosts, 100 HOT + 100 COLD objects each, all public/cacheable with
infinite TTL and adequate cache capacity; 1,000 configuration saves (800
operational-only, 200 content changes to one vhost), followed by 500 uniformly
random GETs per save. A miss immediately reloads an object into its original
tier. No networking, filesystem, CPU timing, origin delay or concurrency is
modeled. Results with seed 3400:
| Synthetic metric | Old global purge | 0.34.0 scoped retention |
|---|---:|---:|
| Object invalidations | 473,540 | 37,300 |
| GET misses | 470,006 | 37,069 |
| GET hits | 29,994 | 462,931 |
| HIT ratio | 5.999% | 92.586% |
The modeled change yields **92.123% fewer invalidations**, **92.113% fewer
misses**, and **+86.587 percentage points** of synthetic cache HIT ratio.
**Measured 0.34.0 requests/s gain: unknown.** These values must not be
presented as a real speedup or a projection against nginx.
## Previously measured comparison (0.33.8, not this candidate)
From the attached 0.33.8 evidence, five paired benchmark runs with cache OFF,
median RPS:
| Mode / payload | 0.33.8 RPS | nginx RPS | 0.33.8 / nginx |
|---|---:|---:|---:|
| Reverse proxy 1,040 B | 29,334.12 | 170,610.16 | 17.19% |
| Reverse proxy 64 KiB | 20,735.07 | 35,393.29 | 58.58% |
| Reverse proxy 1 MiB | 4,461.19 | 2,730.23 | 163.40% |
| WWW 1,040 B | 24,906.20 | 351,605.13 | 7.08% |
| WWW 64 KiB | 20,856.67 | 203,709.91 | 10.24% |
| WWW 1 MiB | 2,833.71 | 12,611.49 | 22.47% |
The 0.33.8 1 MiB proxy path was **2.77% slower than rebuilt 0.33.7**.
Removing a per-response-frame mutex is a performance candidate but is **not**
a measured correction of that regression. No throughput gains are attributed
here to the new source changes.
## Hypothetical 0.34.0/nginx gap sensitivity (NOT MEASURED)
Run `python3 scripts/performance/simulate_nginx_gap_034.py`. Using the **real
0.33.8 measured medians** above, assume zero-copy removes 50% of the
read/copy part of per-request cost; that part hypothetically accounts for
20/40/60% of *total* cost for eligible static files. Model **1/3/5%** total
service-time savings from removed proxy-frame mutexes, independently.
Amdahl: `RPS_sim = RPS_0.33.8 / (1 - hypothetical_fraction_saved)`. The
result is a sensitivity calculation, **not a prediction or 0.34.0 benchmark**.
| Workload | Measured 0.33.8/nginx | Modeled low | Modeled middle | Modeled high |
|---|---:|---:|---:|---:|
| Proxy 1040 B | 17.19% | 17.37% | 17.73% | 18.10% |
| Proxy 64 KiB | 58.58% | 59.18% | 60.40% | 61.67% |
| Proxy 1 MiB | 163.40% | 165.05% | 168.45% | 172.00% |
| WWW 1040 B | 7.08% | 7.08% | 7.08% | 7.08% |
| WWW 64 KiB | 10.24% | 11.38% | 12.80% | 14.63% |
| WWW 1 MiB | 22.47% | 24.97% | 28.09% | 32.10% |
These ratios apply only to eligible Linux plain HTTP/1.1 static workloads
with cache OFF. TLS, HTTP/2, HTTP/3, ranged, compressed and object-cached
responses are **not** accelerated by this bridge. Bandwidth, contention,
queueing, realistic filesystem and actual CPU profiles are not modeled.
Even the favorable modeled 1 MiB case remains ~3.1x slower than nginx WWW;
small WWW remains ~14.1x slower. Proxy 1 MiB already exceeds nginx in the
**prior baseline**, not as a demonstrated new 0.34.0 improvement.
## Required rollout gates
1. On a trusted Linux build worker with the pinned Rust toolchain, run
`./dev.sh check`, `CARGO_INCREMENTAL=0 ./dev.sh test`, and a locked release
build. Resolve any compiler/test issues before a deployment.
2. Follow `scripts/performance/README.md` to run `regression.py`,
`transport_regression.py`, `lb_regression.py`, and
`concurrency_regression.py` against verified 0.33.8 and 0.34.0 binaries.
3. Exercise administration saves during simultaneous requests: save keepalive
values and confirm unchanged HOT/COLD entries and hashes; change one backend
origin and confirm only its scope is purged, both before/after restart. Check
that old snapshots cannot recreate invalidated objects.
4. Run the five-repeat, 15-second paired benchmark against 0.33.8, 0.34.0 and
nginx on the *same host and affinity*, including large proxy responses, CPU,
RSS, resource limits and response correctness.
5. Compile the source-level Linux `sendfile` bridge and validate on a running
RustProxy process: plain HTTP/1 sendfile path, headers/body exactness,
keepalive/pipelining, slow clients, cancellation, HEAD, range, cache,
compression, TLS/H2/H3 fallback, symlink security and observability. Do
**not** activate Auto on production before that gate passes.
6. Complete a mixed-traffic soak and staged rollback rehearsal. Until then,
do not describe 0.34.0 as production-accepted.