Skip to content

perf(http3): avoid pool scans when coalescing is disabled - #3

Open
hawkingrei wants to merge 4 commits into
mainfrom
perf/h3-coalescing-gate
Open

hawkingrei wants to merge 4 commits into
mainfrom
perf/h3-coalescing-gate

Conversation

@hawkingrei

@hawkingrei hawkingrei commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Changes

An HTTP/3 pool miss currently locks route health and scans all pooled routes even when cross-origin coalescing is disabled (the default). The setting is only checked after collecting candidates.

  • Skip route-health locking and candidate collection when coalescing is disabled or the selected route requires ECH.
  • Keep optional coalescing in a synchronous helper, with the existing certificate, proxy/destination, handshake, and client-authentication checks intact.
  • Extend the existing cross-origin regression to cover the default setting alongside explicit false/true, including rejection of an uncovered certificate name and reuse of the healthy original connection.
  • Add a reproducible public-API benchmark and compile all benchmarks in CI. No public API or default policy changes.

Related: follow-up to #2. No tracked issue.

Performance

Wall-clock nanoseconds per public Client::preconnect call; smaller is better.

Scenario Before (ns) After (ns) Reduction
empty_miss 1451.47 1402.66 3.4%
single_miss 1750.95 1746.42 0.3%
64_origins_miss 1902.65 1422.36 25.2%
256_origins_miss 2758.77 1501.67 45.6%
enabled_256_origins_miss 2622.80 2639.68 -0.6%
pooled_hit 559.33 558.16 0.2%
enabled_pooled_hit 556.06 560.90 -0.9%

The populated default-policy cases improve by 25.2% (64 connections) and 45.6% (256 connections). Single-connection misses and the enabled-coalescing/existing-connection controls have overlapping interquartile ranges; no improvement is claimed for them. The enabled controls are 0.6% and 0.9% slower in their medians.

The pool contains real loopback QUIC connections, authenticated against a local certificate covering the benchmark origins. An injected resolver immediately fails the measured missing hostname. Setup, successful handshakes, and pool population are outside timing. Each run checks pool size, released connecting locks, every expected resolver failure, and hit/miss outcomes. There are no timed HTTP requests or handshakes, so these results do not establish end-to-end HTTP latency or throughput gains.

Each case is measured separately in baseline/optimized/optimized/baseline order, with 9 samples of 100,000 calls per round (18 per variant), after 1,000 warm-up calls. Both variants use the same benchmark source, locked dependencies, and standard Cargo bench profile, with -j 2 and only http3 enabled. Host scheduling still contributes noise; raw samples and interquartile ranges follow.

  • Host: macOS-27.0.1-arm64-arm-64bit; Rust 1.99.1, LLVM 23.1.1.
  • Baseline: decc20948b1a89ba6a955208aadc7b1657445f9c; its production src tree matches main 47d0cec9f994e82d787203cd8691c5508e7b48df.
  • Optimized: a1af88d8a5e6bedea3b7202fbb4d78b4864c95b2.
  • Shared benchmark SHA-256: 3d20dea4737803587a3edb69ded1f02e3471857eef3bebb6be420ca20c013046.

Reproduce on either commit:

cargo bench --locked -j 2 --no-default-features --features http3 --bench h3_pool_miss -- --case 256_origins_miss --iterations 100000 --samples 9

Use --case pooled_hit for the existing-connection control, or omit --case for all seven scenarios. Local raw files, binaries, and the measurement receipt are under /private/tmp/htrio-h3-pool-perf-20261113/.

Interquartile ranges and raw samples
Scenario Before Q1–Q3 (ns) After Q1–Q3 (ns)
empty_miss 1401.61–1479.07 1396.78–1414.50
single_miss 1668.58–2013.53 1592.57–2296.72
64_origins_miss 1872.97–1960.16 1413.44–1439.04
256_origins_miss 2576.06–3092.27 1451.02–1541.21
enabled_256_origins_miss 2588.78–2641.41 2606.46–2690.65
pooled_hit 556.69–563.70 553.98–567.49
enabled_pooled_hit 552.30–568.45 555.47–563.36

All 28 runs, in measurement order; each array contains the nine per-sample average ns/call values:

{"case": "empty_miss", "variant": "baseline", "round": 1, "ns_per_prepare_samples": [1336.77042, 1339.6408400000003, 1348.62166, 1397.21833, 1397.82292, 1412.98917, 1426.20209, 1433.15, 1492.12375]}
{"case": "empty_miss", "variant": "optimized", "round": 1, "ns_per_prepare_samples": [1373.31958, 1388.68959, 1396.4925, 1397.64292, 1397.74083, 1402.93125, 1422.51625, 1431.69041, 1659.51792]}
{"case": "empty_miss", "variant": "optimized", "round": 2, "ns_per_prepare_samples": [1385.23583, 1389.80583, 1400.45, 1402.39542, 1404.75167, 1405.76083, 1414.17291, 1414.60917, 1428.97583]}
{"case": "empty_miss", "variant": "baseline", "round": 2, "ns_per_prepare_samples": [1446.8225, 1456.125, 1458.13083, 1461.43084, 1472.92625, 1481.11625, 1486.28625, 1506.42542, 1543.88542]}
{"case": "single_miss", "variant": "baseline", "round": 1, "ns_per_prepare_samples": [1579.83917, 1593.73208, 1619.6775, 1621.36041, 1665.85042, 1676.77375, 1700.51375, 1741.47083, 1748.95167]}
{"case": "single_miss", "variant": "optimized", "round": 1, "ns_per_prepare_samples": [1566.55, 1573.045, 1575.21458, 1580.67333, 1591.08291, 1597.01208, 1605.31708, 1609.18167, 1628.96709]}
{"case": "single_miss", "variant": "optimized", "round": 2, "ns_per_prepare_samples": [1863.87875, 2043.65625, 2187.02542, 2296.49792, 2296.79833, 2340.67583, 2394.52125, 2501.19792, 2995.96583]}
{"case": "single_miss", "variant": "baseline", "round": 2, "ns_per_prepare_samples": [1752.94125, 1762.05667, 1821.76833, 1900.20916, 2051.30208, 2127.77084, 2221.2925, 2254.52208, 2260.43417]}
{"case": "64_origins_miss", "variant": "baseline", "round": 1, "ns_per_prepare_samples": [1715.39125, 1731.2, 1778.01709, 1814.53958, 1869.33542, 1883.88458, 1889.64541, 1917.20292, 1936.34917]}
{"case": "64_origins_miss", "variant": "optimized", "round": 1, "ns_per_prepare_samples": [1398.91708, 1403.32291, 1407.7425, 1412.57708, 1417.6975, 1419.23375, 1421.79416, 1425.80791, 1458.93125]}
{"case": "64_origins_miss", "variant": "optimized", "round": 2, "ns_per_prepare_samples": [1405.56625, 1416.03917, 1422.91708, 1430.76542, 1436.69416, 1439.81916, 1441.57291, 1443.28, 1448.55792]}
{"case": "64_origins_miss", "variant": "baseline", "round": 2, "ns_per_prepare_samples": [1900.75875, 1900.91917, 1904.38291, 1908.63208, 1968.09042, 1977.86959, 1980.36, 1983.06375, 2049.71875]}
{"case": "256_origins_miss", "variant": "baseline", "round": 1, "ns_per_prepare_samples": [2864.68916, 2970.84875, 3026.30542, 3039.08708, 3110.00167, 3116.23541, 3166.15334, 3225.5125, 3233.24708]}
{"case": "256_origins_miss", "variant": "optimized", "round": 1, "ns_per_prepare_samples": [1475.9575, 1500.73042, 1502.60625, 1511.10042, 1521.30167, 1536.64125, 1549.525, 1599.695, 1680.64875]}
{"case": "256_origins_miss", "variant": "optimized", "round": 2, "ns_per_prepare_samples": [1429.68375, 1434.11458, 1441.97625, 1442.37375, 1447.5525, 1461.41541, 1466.00709, 1542.72708, 1593.98584]}
{"case": "256_origins_miss", "variant": "baseline", "round": 2, "ns_per_prepare_samples": [2571.15625, 2571.7879100000005, 2572.29208, 2575.06375, 2575.9300000000003, 2576.4495799999995, 2578.71375, 2593.04875, 2652.85667]}
{"case": "enabled_256_origins_miss", "variant": "baseline", "round": 1, "ns_per_prepare_samples": [2582.1187499999996, 2582.2291600000003, 2586.35125, 2588.4275, 2588.54292, 2589.47625, 2599.98208, 2600.69333, 2724.62375]}
{"case": "enabled_256_origins_miss", "variant": "optimized", "round": 1, "ns_per_prepare_samples": [2597.7395800000004, 2604.04209, 2604.47083, 2605.49417, 2605.8545900000004, 2608.26, 2625.20959, 2692.40625, 2700.74375]}
{"case": "enabled_256_origins_miss", "variant": "optimized", "round": 2, "ns_per_prepare_samples": [2633.28375, 2634.7991599999996, 2644.56875, 2645.84667, 2652.71667, 2685.39958, 2692.52708, 2751.16125, 2797.33417]}
{"case": "enabled_256_origins_miss", "variant": "baseline", "round": 2, "ns_per_prepare_samples": [2622.2025, 2623.40625, 2631.14917, 2635.31625, 2639.8025000000002, 2641.93917, 2679.0379199999998, 2689.6175, 2824.15666]}
{"case": "pooled_hit", "variant": "baseline", "round": 1, "ns_per_prepare_samples": [549.94167, 551.74375, 555.25417, 556.65875, 556.77334, 557.24, 561.4825, 567.35625, 662.35084]}
{"case": "pooled_hit", "variant": "optimized", "round": 1, "ns_per_prepare_samples": [552.30958, 555.88, 558.09875, 558.23083, 559.99375, 561.53625, 565.54208, 590.37125, 709.67458]}
{"case": "pooled_hit", "variant": "optimized", "round": 2, "ns_per_prepare_samples": [548.75375, 552.91959, 553.31042, 553.38875, 555.7425, 556.29541, 568.13459, 585.49416, 695.95]}
{"case": "pooled_hit", "variant": "baseline", "round": 2, "ns_per_prepare_samples": [553.99042, 558.85333, 559.06125, 559.59625, 560.10292, 563.37291, 563.80625, 564.35459, 659.5345800000001]}
{"case": "enabled_pooled_hit", "variant": "baseline", "round": 1, "ns_per_prepare_samples": [547.77209, 550.20875, 551.57125, 552.08959, 552.93041, 553.10708, 555.57208, 556.54583, 712.33417]}
{"case": "enabled_pooled_hit", "variant": "optimized", "round": 1, "ns_per_prepare_samples": [554.16292, 554.655, 555.92917, 558.61542, 561.13875, 561.735, 561.75917, 567.65375, 652.53042]}
{"case": "enabled_pooled_hit", "variant": "optimized", "round": 2, "ns_per_prepare_samples": [553.15125, 554.43375, 555.3125, 557.05833, 560.65625, 561.65208, 563.89167, 565.13459, 639.8437499999999]}
{"case": "enabled_pooled_hit", "variant": "baseline", "round": 2, "ns_per_prepare_samples": [549.21458, 554.80833, 560.85375, 561.06875, 565.45875, 569.44375, 572.07083, 574.78709, 679.61291]}

Validation

  • Local: built the benchmark for both production trees and completed the measurements above. Reviewed the final diff and formatting.
  • CI on a1af88d8a5e6bedea3b7202fbb4d78b4864c95b2: push and pull request each passed all eight jobs (16/16 total): native Linux/macOS/Windows regressions and Native TLS, MSRV, feature profiles, documentation, workspace package dry-run, HTTP/3 protocol, and Quinn suites. Local regression suites were not duplicated.
  • Native logs on all three platforms confirm cross_origin_coalescing_is_opt_in_and_rechecks_certificate_authority passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant