feat(simulation): T-1152 server half — WindowGranularity enum, derive_orbital_at_metres, Region rung on the same carrier

R1 measured first: a capped Region tile through the real production path
(build_district_window_layer + T-1151 par_iter) at the 64x64 wire cap
costs 0.40-0.48ms — faster than the shipped district n=64 window, so
Jeroen's progressive capped-density tiling ruling is comfortably
interactive on-demand. Raw orbital derive ~0.9µs/cell (~2.3x faster than
full derive; region_baseline dominates, not invent_primitives).

R5 redesign: WindowGranularity enum (Quarter/District/Region), serde
named-variant per the RoadNodeKind precedent, spacing from D-243 scale::
constants — the single source of truth. Additive serde-default
window_granularity_v2 request field (None = legacy u32 path; v2 wins when
Some); DistrictWindowLayer.granularity_v2 always echoed. Legacy u32 echo
for Region uses reserved WINDOW_GRANULARITY_REGION_KEY = u32::MAX (never
a legal input) so the old slot cannot lie about aliasing. Cache and
coalescing keys carry the enum itself (Ord by declaration order, D-010).

n stays district-extent at every rung; Region's cell grid is a DIVISION
(round(n/100), min 1) with its own per-axis ceiling
DISTRICT_WINDOW_MAX_N_REGION=6400 and a bounded halving-loop clamp (no
closed form under the rounding division — the client mirror must
replicate the loop).

derive_orbital_at_metres: bilinear envelope reads + region_baseline
temperature, NO invent_primitives (proven by test — slope_q pinned 0),
routed through the shared build_district_profile classification tail so
the existing colorizer family renders orbital cells unchanged. R2
stepped-categorical behavior documented at the function, not implied.

Region aliasing + clamp/echo tests mirror the T-1150 discipline. 1813
lib tests green; clippy clean; fixture regenerated (254->278 bytes, new
echoed field).
This commit is contained in:
2026-07-22 10:35:37 +02:00
parent 2a4597e108
commit d356b09926
9 changed files with 1155 additions and 133 deletions
+1
View File
@@ -372,6 +372,7 @@ fn single_tick_drains_all_ready_inbound_frames() {
window_center: None,
window_n: 0,
window_granularity: 0,
window_granularity_v2: None,
window_min_wl_m: 0,
};
let payload = rmp_serde::to_vec_named(&req).expect("failed to serialize");
+2 -1
View File
@@ -6,7 +6,7 @@ use settled_reach_server::atlas::layer1::Layer1Output;
use settled_reach_server::atlas::layer_proxy::{
AtlasLayerResponse, AtlasLayerStatus, DistrictWindowLayer, QuarterFootprintEntry,
QuarterFootprintLayer, RegionGridLayer, RoadGraphEdge, RoadGraphLayer, RoadGraphNode,
SettlementEntry, SettlementLayer, SettlementSizeClass, REGION_TEMP_NONE_DC,
SettlementEntry, SettlementLayer, SettlementSizeClass, WindowGranularity, REGION_TEMP_NONE_DC,
WINDOW_GRANULARITY_DISTRICT,
};
use settled_reach_server::atlas::region_profile::{SeasonPhase, WeatherState};
@@ -727,6 +727,7 @@ fn generate_atlas_layer_response_fixtures() {
center: (10, -5),
n: 2,
granularity: WINDOW_GRANULARITY_DISTRICT,
granularity_v2: WindowGranularity::District,
min_wl_m: 0,
morphology: vec![0, 8, 14, 16], // OpenOcean, AlluvialPlain, Alpine, Wetland
elev_q: vec![0, 45, 98, 60],
+188 -1
View File
@@ -17,11 +17,14 @@
use std::time::Instant;
use settled_reach_server::atlas::district_profile::{
derive_at_metres, BodyParams, ClimateConstants,
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_REGION, WIRE_CAP_CELLS,
};
use settled_reach_server::atlas::scale;
use settled_reach_server::seed::{SeedChain, SeedDomain};
@@ -151,3 +154,187 @@ fn bench_derive_at_metres_district_and_quarter_spacing() {
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 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,
(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,
(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"
);
}