Files
settled-reach/server/tests/zoom_ladder_bench.rs
T
jpmschweitzerandClaude Fable 5 b9afa19d65 docs(meta): PR #197 review captures — stroke-floor width-inertness + unreachable-pole-branch notes; bench reflow
Tyre's two governance sentences on the D-226 course note: (a) the
Godot rasterizer floor makes per-class course WIDTH differentiation
inert at every shipping fit zoom — classes distinguish by opacity
alone until T-1175's per-vertex tapering; the 'trunk widest' promise
is design intent, not current pixels. (b) The pole-row edge-drain
branch is structurally unreachable; the real mechanism is interior
k<0 (revert-verification discovery). Plus the dangling cargo-fmt
reflow in the course-cost bench from the gate-bounce round.

Tickets: T-1170

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 14:46:27 +02:00

565 lines
21 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Zoom-ladder derivation benchmarks (T-1149, design doc §2/§7/§8 step 1).
//!
//! Measures `derive_at_metres` per-cell cost at district spacing (2,048 m) and
//! quarter spacing (512 m), with and without a `min_wavelength_m` octave
//! cutoff — the exact numbers the design doc flags as UNBUILT/UNMEASURED
//! (§7: "Octave-cutoff derive (min_wavelength_m-bearing) ... not measured").
//!
//! Manual `Instant`-based timing, matching every other bench in this repo
//! (`shadowcast_bench.rs`, `perf_bench.rs`) and the same technique
//! `aliveness_probe --render` used to produce the ~1.21.4 µs/district
//! release figure the design doc cites — no criterion dependency exists here.
//!
//! Run: `cargo test --release --test zoom_ladder_bench -- --ignored --nocapture`
//! (debug numbers are ~5x slower and not representative of the design doc's
//! release-build figures; run `--release` for numbers worth recording).
use std::time::Instant;
use settled_reach_server::atlas::district_profile::{
derive_at_metres, derive_orbital_at_metres, BodyParams, ClimateConstants,
};
use settled_reach_server::atlas::drainage;
use settled_reach_server::atlas::features::TerrainAnalysis;
use settled_reach_server::atlas::heightmap::BodyHeightmap;
use settled_reach_server::atlas::layer_proxy::{
build_district_window_layer, WindowGranularity, DISTRICT_WINDOW_MAX_N,
DISTRICT_WINDOW_MAX_N_REGION, WIRE_CAP_CELLS,
};
use settled_reach_server::atlas::scale;
use settled_reach_server::seed::{SeedChain, SeedDomain};
fn bench_hm() -> BodyHeightmap {
// Same shape as district_profile.rs's own test_hm/window_test_hm fixtures
// — a smooth gradient, deterministic, no PNG I/O.
let (w, h) = (128u32, 64u32);
let n = (w * h) as usize;
let data = (0..n)
.map(|i| {
let r = (i / w as usize) as f32 / h as f32;
let c = (i % w as usize) as f32 / w as f32;
(r * 0.6 + c * 0.4).min(1.0)
})
.collect();
BodyHeightmap {
body_id: "bench".into(),
width: w,
height: h,
data,
sea_level: 0.3,
}
}
fn bench_ta(hm: &BodyHeightmap) -> TerrainAnalysis {
let dr = drainage::analyze(&hm.data, hm.width, hm.height, hm.sea_level);
TerrainAnalysis::analyze(hm, &dr)
}
fn bench_river_network(
hm: &BodyHeightmap,
) -> settled_reach_server::atlas::body_world_state::RiverNetwork {
drainage::analyze(&hm.data, hm.width, hm.height, hm.sea_level).river_network
}
fn bench_params() -> BodyParams {
BodyParams {
hydrosphere: Some("ocean".into()),
atmosphere: Some("breathable".into()),
planet_class: Some("temperate".into()),
body_radius_km: Some(6371.0),
..Default::default()
}
}
/// Time `n_cells` sequential `derive_at_metres` calls on a spacing-`step_m`
/// grid starting at world origin, with the given octave cutoff. Returns
/// (total_elapsed, per_cell_ns).
fn time_derive_sweep(
seed: SeedChain,
body_id: &str,
params: &BodyParams,
ta: &TerrainAnalysis,
climate: &ClimateConstants,
grid_side: u32,
step_m: f64,
min_wavelength_m: f64,
) -> (std::time::Duration, f64) {
let n_cells = (grid_side * grid_side) as u64;
let t0 = Instant::now();
for row in 0..grid_side {
for col in 0..grid_side {
let wx = col as f64 * step_m;
let wy = row as f64 * step_m;
let prof = derive_at_metres(
seed,
body_id,
params,
ta,
wx,
wy,
climate,
min_wavelength_m,
&[],
);
// Prevent the optimizer from hoisting the call out of the loop.
std::hint::black_box(prof.elev_q);
}
}
let elapsed = t0.elapsed();
let per_cell_ns = elapsed.as_secs_f64() * 1e9 / n_cells as f64;
(elapsed, per_cell_ns)
}
#[test]
#[ignore]
fn bench_derive_at_metres_district_and_quarter_spacing() {
let hm = bench_hm();
let ta = bench_ta(&hm);
let params = bench_params();
let climate = ClimateConstants::default();
let seed = SeedChain::root(99).derive(SeedDomain::Body, 1);
let grid_side = 64u32; // 4,096 cells per sweep — matches the D-226 window cap
println!("\n=== T-1149 zoom-ladder derive_at_metres benchmark ===");
println!(
"grid: {grid_side}x{grid_side} = {} cells/sweep\n",
grid_side * grid_side
);
let district_m = scale::DISTRICT_M as f64;
let quarter_m = scale::QUARTER_M as f64;
// District spacing (2,048 m), cutoff 0 — today's uncut behavior.
let (elapsed, per_cell_ns) = time_derive_sweep(
seed, "bench", &params, &ta, &climate, grid_side, district_m, 0.0,
);
println!(
"district spacing, cutoff=0: {:>8.2} ms total, {:>7.1} ns/cell ({:.3} µs/cell)",
elapsed.as_secs_f64() * 1000.0,
per_cell_ns,
per_cell_ns / 1000.0
);
// District spacing, cutoff 2,048 m — truncates every OCTAVE_WAVELENGTHS_M
// entry below the district's own spacing (finest is 4,096 m, so this
// cutoff is BELOW that — confirms the cutoff plumbing at district scale
// without changing which octaves survive, since 2,048 < 4,096 admits all
// of them; recorded for the design doc's requested (district, cutoff
// 2048) combination regardless).
let (elapsed, per_cell_ns) = time_derive_sweep(
seed, "bench", &params, &ta, &climate, grid_side, district_m, 2_048.0,
);
println!(
"district spacing, cutoff=2048m: {:>8.2} ms total, {:>7.1} ns/cell ({:.3} µs/cell)",
elapsed.as_secs_f64() * 1000.0,
per_cell_ns,
per_cell_ns / 1000.0
);
// Quarter spacing (512 m), cutoff 512 m — the T-1150 Option B rung: full
// reclassification at quarter spacing with the matching octave cutoff.
let (elapsed, per_cell_ns) = time_derive_sweep(
seed, "bench", &params, &ta, &climate, grid_side, quarter_m, 512.0,
);
println!(
"quarter spacing, cutoff=512m: {:>8.2} ms total, {:>7.1} ns/cell ({:.3} µs/cell)",
elapsed.as_secs_f64() * 1000.0,
per_cell_ns,
per_cell_ns / 1000.0
);
println!();
}
/// Time `n_cells` sequential `derive_orbital_at_metres` calls — the
/// region-baseline-blend-only path (T-1152, design doc §2/§4/§9 R1), no
/// `invent_primitives` call at any point. Mirrors `time_derive_sweep`'s shape
/// exactly so the two numbers are directly comparable.
fn time_orbital_sweep(
seed: SeedChain,
body_id: &str,
params: &BodyParams,
ta: &TerrainAnalysis,
climate: &ClimateConstants,
grid_side: u32,
step_m: f64,
) -> (std::time::Duration, f64) {
let n_cells = (grid_side * grid_side) as u64;
let t0 = Instant::now();
for row in 0..grid_side {
for col in 0..grid_side {
let wx = col as f64 * step_m;
let wy = row as f64 * step_m;
let prof = derive_orbital_at_metres(seed, body_id, params, ta, wx, wy, climate);
std::hint::black_box(prof.elev_q);
}
}
let elapsed = t0.elapsed();
let per_cell_ns = elapsed.as_secs_f64() * 1e9 / n_cells as f64;
(elapsed, per_cell_ns)
}
/// T-1152 / design doc §9 R1: "MEASURE FIRST" — per-cell cost of the
/// orbital-mode region-baseline-blend-only path (no `invent_primitives`) at
/// coarse (region-scale, ≥205 km) spacings, plus a realistic full-orbital-frame
/// extrapolation (1600×900 canvas). This is the number the design doc's §4/§7
/// planetary-rung cost story rested on as an UNMEASURED extrapolation —
/// this test replaces "extrapolated from the uncut per-cell rate" with an
/// actually-measured orbital-path rate.
#[test]
#[ignore]
fn bench_derive_orbital_at_metres_region_spacing() {
let hm = bench_hm();
let ta = bench_ta(&hm);
let params = bench_params();
let climate = ClimateConstants::default();
let seed = SeedChain::root(99).derive(SeedDomain::Body, 1);
let grid_side = 64u32; // 4,096 cells/sweep, same shape as the district/quarter sweeps above
println!("\n=== T-1152 orbital-rung derive_orbital_at_metres benchmark ===");
println!(
"grid: {grid_side}x{grid_side} = {} cells/sweep\n",
grid_side * grid_side
);
let region_m = scale::REGION_M as f64;
// Region spacing (204,800 m) — the coarsest named rung short of the
// planet-wide elastic seam (D-243).
let (elapsed, per_cell_ns) =
time_orbital_sweep(seed, "bench", &params, &ta, &climate, grid_side, region_m);
println!(
"orbital, region spacing (204.8km): {:>8.2} ms total, {:>7.1} ns/cell ({:.3} µs/cell)",
elapsed.as_secs_f64() * 1000.0,
per_cell_ns,
per_cell_ns / 1000.0
);
// Same spacing, for direct comparison: the FULL derive_at_metres path
// (invent_primitives included) at the SAME region spacing — quantifies
// exactly what skipping invention buys, at the spacing where it matters.
let (elapsed_full, per_cell_ns_full) = time_derive_sweep(
seed, "bench", &params, &ta, &climate, grid_side, region_m, 0.0,
);
println!(
"district-mode (full derive_at_metres) at region spacing: {:>8.2} ms total, {:>7.1} ns/cell ({:.3} µs/cell)",
elapsed_full.as_secs_f64() * 1000.0,
per_cell_ns_full,
per_cell_ns_full / 1000.0
);
println!(
"orbital speedup vs. full derive at the same spacing: {:.2}x\n",
per_cell_ns_full / per_cell_ns
);
// Realistic full-orbital-frame estimate: a 1600x900 canvas at
// ~1-2 px/cell equivalents (design doc §4's worked example resolution
// class). Single-thread extrapolation from the MEASURED per-cell rate —
// labelled as an extrapolation, not claimed as independently measured at
// full canvas size (the parallel/chunked throughput is a SEPARATE
// measurement, T-1151's row-chunked par_iter, already landed and reused
// unchanged by the orbital rung's serving path — see the ticket report).
for (label, px_per_cell) in [("1 px/cell", 1u32), ("2 px/cell", 2u32)] {
let cols = 1600 / px_per_cell;
let rows = 900 / px_per_cell;
let cells = (cols as u64) * (rows as u64);
let est_ms = cells as f64 * per_cell_ns / 1e6;
println!(
"full-canvas 1600x900 @ {label} ({cols}x{rows} = {cells} cells): \
{est_ms:.1} ms single-thread (EXTRAPOLATED from the measured per-cell rate above)"
);
}
println!();
}
/// **T-1152 R1 — the number that actually governs interactive latency**, as
/// opposed to the full-canvas single-shot extrapolation above (which the
/// design doc's own carrier ruling makes moot — Jeroen's ruling is
/// progressive capped-density TILING, never a whole-canvas one-shot derive).
/// This measures a single served Region-granularity window tile through the
/// REAL production path (`build_district_window_layer`, including its
/// row-chunked `par_iter`, T-1151) at the wire-size cap — the same function
/// `serve_district_window`/`run_work_item`'s `DeriveWindow` arm calls, not a
/// hand-rolled sweep. This is the measured (not extrapolated) parallel
/// number the design doc's §7 flagged as missing ("no chunked-par_iter
/// benchmark has been run").
#[test]
#[ignore]
fn bench_served_region_window_tile_at_wire_cap() {
let hm = bench_hm();
let ta = bench_ta(&hm);
let rn = bench_river_network(&hm);
let params = bench_params();
let climate = ClimateConstants::default();
let seed = SeedChain::root(99).derive(SeedDomain::Body, 1);
println!("\n=== T-1152 served Region-window-tile benchmark (real production path) ===");
// The largest n the server will ever actually derive at Region
// granularity is DISTRICT_WINDOW_MAX_N_REGION, clamped further by
// clamp_window_n_v2 to the WIRE_CAP_CELLS ceiling — use the SAME
// capped n a real client's oversized request would resolve to.
let n = DISTRICT_WINDOW_MAX_N_REGION;
// Warm-up call (first call on a body pays no extra cost here since ta is
// already built — this just avoids counting one-time allocator warm-up
// noise in the timed sample).
let _ = build_district_window_layer(
seed,
"bench",
&params,
&ta,
&rn,
(0, 0),
n,
&climate,
WindowGranularity::Region,
0,
);
let iterations = 20;
let t0 = Instant::now();
let mut last_side = 0usize;
for _ in 0..iterations {
let layer = build_district_window_layer(
seed,
"bench",
&params,
&ta,
&rn,
(0, 0),
n,
&climate,
WindowGranularity::Region,
0,
);
last_side = (layer.morphology.len() as f64).sqrt().round() as usize;
std::hint::black_box(layer.elev_q.len());
}
let elapsed = t0.elapsed();
let per_call_ms = elapsed.as_secs_f64() * 1000.0 / iterations as f64;
println!(
"n={n} (DISTRICT_WINDOW_MAX_N_REGION), derived {last_side}x{last_side} region cells \
({} cells, WIRE_CAP_CELLS={WIRE_CAP_CELLS}):",
last_side * last_side
);
println!(
" {iterations} calls, {:.2} ms total, {per_call_ms:.3} ms/call \
(row-chunked par_iter, {} Rayon threads available)",
elapsed.as_secs_f64() * 1000.0,
std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(0)
);
println!(
" compare: shipped district n=64 cap measures ~5 ms/call (design doc §7, MEASURED)\n"
);
}
/// **T-1170 Discipline item 2 (mandatory): course-cost bench.** Window
/// derive with courses on vs. off, at District granularity, real cap `n=64`
/// — the shape Tyre's cost probe measured (+0.09-0.21 ms against a ~5 ms
/// baseline, under 5%). "Off" uses an empty `RiverNetwork` (zero edges to
/// invent, exactly the pre-T-1170 cost shape); "on" uses a real body with
/// genuine river geometry (GJ1c) so the course inventor's Stage A/B pipeline
/// actually runs for the edges that cull into the window, not a synthetic
/// gradient body that might have zero river cells at all.
#[test]
#[ignore]
fn bench_course_cost_on_vs_off() {
use settled_reach_server::atlas::body_world_state::RiverNetwork;
use settled_reach_server::atlas::drainage;
use settled_reach_server::atlas::heightmap::load_heightmap_png;
let src = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../wiki/star-systems/GJ-1/bodies/GJ1c/heightmap.png");
let heightmap = load_heightmap_png(&src, "GJ1c", 0.3).expect("decode committed GJ1c heightmap");
let small = heightmap.downsample(512, 256); // GRID_W x GRID_H, the real production working grid
let dr = drainage::analyze(&small.data, small.width, small.height, small.sea_level);
let ta = TerrainAnalysis::analyze(&small, &dr);
let rn_on = &dr.river_network;
let rn_off = RiverNetwork::default();
assert!(
!rn_on.river_cells.is_empty(),
"GJ1c at production working resolution must have river cells for this bench to be meaningful"
);
let params = BodyParams {
hydrosphere: Some("ocean".into()),
atmosphere: Some("breathable".into()),
planet_class: Some("temperate".into()),
body_radius_km: Some(6371.0),
..Default::default()
};
let climate = ClimateConstants::default();
let seed = SeedChain::root(0xC0FFEE_u64).derive(SeedDomain::Body, 7);
let n = DISTRICT_WINDOW_MAX_N; // the real n=64 shipped cap
// Centre the window on a real river cell — a window at the world origin
// (unrelated to where GJ1c's rivers actually are) would cull EVERY edge
// out and measure nothing but baseline noise. Convert a real river cell
// to world metres (the SAME pixel_to_world_m formula
// `district_profile.rs` uses internally — inlined here since that
// function is `pub(crate)`, not reachable from an integration test),
// then to the DistrictPos the window centres on.
let river_cell = dr.river_network.river_cells[dr.river_network.river_cells.len() / 2];
let r_km = params.body_radius_km.unwrap();
let world_pos = (
river_cell.1 as f64 / ta.w as f64 * (std::f64::consts::TAU * r_km * 1000.0),
(river_cell.0 as f64 / (ta.h - 1) as f64 - 0.5) * (std::f64::consts::PI * r_km * 1000.0),
);
let center: (i32, i32) = (
(world_pos.0 / scale::DISTRICT_M as f64).floor() as i32,
(world_pos.1 / scale::DISTRICT_M as f64).floor() as i32,
);
println!("\n=== T-1170 course-cost bench (District, n={n}, real GJ1c river geometry) ===");
println!(" window centred at district {center:?} (river cell {river_cell:?})");
// Warm-up (allocator/cache warm, not counted).
let _ = build_district_window_layer(
seed,
"GJ1c",
&params,
&ta,
&rn_off,
center,
n,
&climate,
WindowGranularity::District,
0,
);
let _ = build_district_window_layer(
seed,
"GJ1c",
&params,
&ta,
rn_on,
center,
n,
&climate,
WindowGranularity::District,
0,
);
let iterations = 1000; // higher count than the other benches — window cost here is ~1 ms, noisy at low n
let t_off = Instant::now();
for _ in 0..iterations {
let layer = build_district_window_layer(
seed,
"GJ1c",
&params,
&ta,
&rn_off,
center,
n,
&climate,
WindowGranularity::District,
0,
);
std::hint::black_box(layer.morphology.len());
}
let elapsed_off = t_off.elapsed();
let ms_off = elapsed_off.as_secs_f64() * 1000.0 / iterations as f64;
let t_on = Instant::now();
let mut courses_seen = 0usize;
for _ in 0..iterations {
let layer = build_district_window_layer(
seed,
"GJ1c",
&params,
&ta,
rn_on,
center,
n,
&climate,
WindowGranularity::District,
0,
);
courses_seen = layer.courses.len();
std::hint::black_box(layer.morphology.len());
}
let elapsed_on = t_on.elapsed();
let ms_on = elapsed_on.as_secs_f64() * 1000.0 / iterations as f64;
assert!(
courses_seen > 0,
"bench measured nothing meaningful — the window at {center:?} culled every edge out; \
re-pick a district position genuinely near GJ1c's river geometry"
);
let delta_pct = ((ms_on - ms_off) / ms_off) * 100.0;
println!(
" courses OFF (empty RiverNetwork): {:.3} ms/call ({iterations} calls, {:.2} ms total)",
ms_off,
elapsed_off.as_secs_f64() * 1000.0
);
println!(
" courses ON (real GJ1c network): {:.3} ms/call ({iterations} calls, {:.2} ms total, \
{courses_seen} courses in the n={n} window at {center:?})",
ms_on,
elapsed_on.as_secs_f64() * 1000.0
);
println!(" delta: {delta_pct:+.1}% (Discipline item 2 budget: < ~5%)\n");
}
#[test]
#[ignore]
fn bench_near_perennial_water_percell_isolated() {
use settled_reach_server::atlas::drainage;
use settled_reach_server::atlas::heightmap::load_heightmap_png;
use settled_reach_server::atlas::river_course;
let src = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../wiki/star-systems/GJ-1/bodies/GJ1c/heightmap.png");
let heightmap = load_heightmap_png(&src, "GJ1c", 0.3).expect("decode heightmap");
let small = heightmap.downsample(512, 256);
let dr = drainage::analyze(&small.data, small.width, small.height, small.sea_level);
let ta = TerrainAnalysis::analyze(&small, &dr);
let params = BodyParams {
hydrosphere: Some("ocean".into()),
atmosphere: Some("breathable".into()),
planet_class: Some("temperate".into()),
body_radius_km: Some(6371.0),
..Default::default()
};
let seed = SeedChain::root(0xC0FFEE_u64).derive(SeedDomain::Body, 7);
let edges = river_course::build_edges(&dr.river_network);
let edge = &edges[edges.len() / 2];
let course = river_course::invent_course(seed, edge, &ta, &params, 2048.0, 0.0);
let courses = vec![course];
let n = 4096u32;
let t0 = Instant::now();
let mut count = 0;
for i in 0..n {
let pos = (i as f64 * 100.0, i as f64 * 37.0);
if river_course::near_perennial_water(pos, &courses) {
count += 1;
}
}
let elapsed = t0.elapsed();
eprintln!(
"near_perennial_water: {:.3} ns/call ({n} calls, {} hits)",
elapsed.as_secs_f64() * 1e9 / n as f64,
count
);
// invent_course cost, isolated.
let t1 = Instant::now();
for _ in 0..100 {
let c = river_course::invent_course(seed, edge, &ta, &params, 2048.0, 0.0);
std::hint::black_box(c.points.len());
}
eprintln!(
"invent_course: {:.3} us/call",
t1.elapsed().as_secs_f64() * 1e6 / 100.0
);
}