//! Body Map Viewer workshop — global-tier byte-cost recheck (Jeroen's //! post-ratification correction to the ladder top). //! //! Jeroen's correction: GLOBAL is rung 0, the body-surface opener, with a //! **VARIABLE canvas = the body's own region grid** (one gridunit PER //! REGION, `regions_per_equator × regions_per_equator/2`, D-243's elastic //! seam) — NOT a fixed 3840×2160 District-spacing canvas the way the round-2 //! cache-tier spec's ~174 MB figure assumed. REGION is rung 1, the largest //! FIXED-size rung (viewport-sized, evictable like every other sub-global //! rung). This file recomputes the always-keep global-tier byte budget //! against the CORRECT rung-0 shape, using REAL per-body radii read from //! `systems.db` via [`settled_reach_server::atlas::body_params_reader::BodyParamsReader`] //! (never raw `sqlite3` — the project's asset-pipeline rule) — not an //! assumed Earth-class uniform radius, since region-grid size is the ONE //! per-body-floating quantity in the whole D-243 ladder (the elastic seam) //! and the whole point of this recheck is that assuming Earth-class for //! every body was the error being corrected. //! //! Run: `cargo test --release --test bmv_global_tier_bench -- --ignored --nocapture` use std::path::PathBuf; use std::time::Instant; use settled_reach_server::atlas::body_params_reader::BodyParamsReader; use settled_reach_server::atlas::district_profile::{ 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::scale; use settled_reach_server::seed::{SeedChain, SeedDomain}; /// Same body-discovery walk the T-1177 population survey bench /// (`hydrology_equilibrium_bench.rs::bench_population_survey_all_committed_bodies`) /// already established — every committed `heightmap.png`'s parent directory /// name is a real body_id. Reused here (not re-invented) so this bench's /// population is exactly the same 267-body set the hydrology survey already /// covers, for direct comparability. fn discover_body_ids() -> Vec { let wiki_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../wiki/star-systems"); let mut ids = Vec::new(); fn walk(dir: &std::path::Path, out: &mut Vec) { let Ok(entries) = std::fs::read_dir(dir) else { return; }; for entry in entries.flatten() { let path = entry.path(); if path.is_dir() { walk(&path, out); } else if path.file_name().and_then(|n| n.to_str()) == Some("heightmap.png") { if let Some(body_id) = path .parent() .and_then(|p| p.file_name()) .and_then(|n| n.to_str()) { out.push(body_id.to_string()); } } } } walk(&wiki_root, &mut ids); ids.sort(); ids } /// The global/rung-0 canvas cell count for a body of the given radius: /// `regions_per_equator(R) × (regions_per_equator(R) / 2)` — one gridunit /// PER REGION (Jeroen's ruling), pole-to-pole being half the equatorial /// count per [`scale::regions_per_equator`]'s own doc. fn rung0_cells(body_radius_km: f64) -> u64 { let cols = scale::regions_per_equator(body_radius_km) as u64; let rows = (cols / 2).max(1); cols * rows } /// T-1179's measured PNG-per-field rate: 638,382 bytes / 331,776 cells at /// district spacing (the only body+field-set this workshop measured a real /// encode on) = 1.924 bytes/cell PNG-encoded, six dense fields /// (morphology/elev_q/temp_dc/moisture_q/vegetation/glaciation). Applied /// here as the SAME field-set/encoding assumption the round-2 cache-tier /// spec used for the (wrong-shape) 174 MB estimate — this bench corrects the /// CANVAS SHAPE, not the per-cell wire-cost model, so the two numbers are /// comparable apples-to-apples on the encoding axis and differ only on the /// canvas-shape axis Jeroen actually corrected. const PNG_BYTES_PER_CELL: f64 = 638_382.0 / 331_776.0; #[test] #[ignore] fn bench_global_tier_bytes_real_population() { let systems_db = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("data/systems.db"); let reader = BodyParamsReader::open(&systems_db) .expect("open read-only systems.db (asset-pipeline golden rule: read-only snapshot)"); let body_ids = discover_body_ids(); assert!( body_ids.len() > 200, "expected the real committed body population (~267), found {}", body_ids.len() ); let mut found = 0usize; let mut missing_radius: Vec = Vec::new(); let mut total_cells: u64 = 0; let mut per_body: Vec<(String, f64, u64)> = Vec::new(); // (body_id, radius_km, cells) for body_id in &body_ids { match reader.read_body_params(body_id) { Ok(params) => { if let Some(r_km) = params.body_radius_km { let cells = rung0_cells(r_km); total_cells += cells; per_body.push((body_id.clone(), r_km, cells)); found += 1; } else { missing_radius.push(body_id.clone()); } } Err(e) => { missing_radius.push(format!("{body_id} ({e})")); } } } per_body.sort_by(|a, b| b.2.cmp(&a.2)); // largest region-grid first let total_bytes_raw6 = total_cells as f64 * 6.0; // 6 raw bytes/cell, DistrictWindowLayer's own documented figure let total_bytes_png = total_cells as f64 * PNG_BYTES_PER_CELL; println!( "\n=== Global-tier (rung 0) byte-cost recheck: REAL population, REAL per-body radii ===" ); println!( " bodies discovered: {}, radius found: {found}, missing/unreadable: {}", body_ids.len(), missing_radius.len() ); if !missing_radius.is_empty() { println!( " missing radius (excluded from total, listed for audit): {:?}", &missing_radius[..missing_radius.len().min(10)] ); if missing_radius.len() > 10 { println!(" ... and {} more", missing_radius.len() - 10); } } println!("\n total rung-0 cells across population: {total_cells}"); println!( " average cells/body: {:.0}", total_cells as f64 / found.max(1) as f64 ); println!( "\n total bytes, raw 6 B/cell (DistrictWindowLayer's documented rate): {:.2} MB", total_bytes_raw6 / 1_048_576.0 ); println!( " total bytes, PNG-per-field ({:.3} B/cell, T-1179's measured rate): {:.2} MB", PNG_BYTES_PER_CELL, total_bytes_png / 1_048_576.0 ); println!("\n Top 10 bodies by rung-0 cell count (largest global canvases):"); for (body_id, r_km, cells) in per_body.iter().take(10) { let cols = scale::regions_per_equator(*r_km); println!( " {body_id:>12} radius={r_km:>8.1}km regions_per_equator={cols:>4} cells={cells:>7} ({:.1} KB PNG)", *cells as f64 * PNG_BYTES_PER_CELL / 1024.0 ); } println!("\n Bottom 5 bodies by rung-0 cell count (smallest global canvases):"); for (body_id, r_km, cells) in per_body.iter().rev().take(5) { let cols = scale::regions_per_equator(*r_km); println!( " {body_id:>12} radius={r_km:>8.1}km regions_per_equator={cols:>4} cells={cells:>7} ({:.1} KB PNG)", *cells as f64 * PNG_BYTES_PER_CELL / 1024.0 ); } // Earth-class reference point (R=6371km), for direct comparison against // the brief appendix's own "~195x98 Earth-sized" framing. let earth_cols = scale::regions_per_equator(6371.0); let earth_rows = (earth_cols / 2).max(1); println!( "\n Reference: Earth-class (R=6371km) regions_per_equator={earth_cols}, rows={earth_rows}, cells={}", earth_cols as u64 * earth_rows as u64 ); println!(); } // --------------------------------------------------------------------------- // Rung-0 (GLOBAL opener) derive cost — MEASURED, not extrapolated (Tyre's // bracket request). The existing `bench_derive_orbital_at_metres_region_spacing` // (zoom_ladder_bench.rs) measures `derive_orbital_at_metres`'s per-cell rate // at a fixed 4,096-cell (64x64) sweep — that number is real, but scaling it // up to a whole rung-0 canvas by multiplication is exactly the kind of // "EXTRAPOLATED from the measured per-cell rate" label that bench's own // full-canvas rows already carry (explicitly disclosed there, not measured). // This bench instead runs the REAL per-body canvas shape (the actual // regions_per_equator(R) x regions_per_equator(R)/2 grid, real per-body // radius) end-to-end for a representative sample of real bodies, so the // rung-0 derive-cost figure is measured at the shape it will actually be // served at, not inferred from a differently-shaped sweep. // --------------------------------------------------------------------------- fn bench_hm() -> BodyHeightmap { 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) } /// Real rung-0 canvas derive cost at three representative real body sizes /// from the population (smallest, Earth-class-nearest, largest), single /// call per cell through the actual `derive_orbital_at_metres` function — /// no square-sweep proxy shape, the real `cols x rows` extent each body's /// canvas would actually be. #[test] #[ignore] fn bench_rung0_derive_cost_real_canvas_shapes() { let hm = bench_hm(); let ta = bench_ta(&hm); let params = BodyParams { hydrosphere: Some("ocean".into()), atmosphere: Some("breathable".into()), planet_class: Some("temperate".into()), body_radius_km: Some(6371.0), // overridden per-case below ..Default::default() }; let climate = ClimateConstants::default(); let seed = SeedChain::root(99).derive(SeedDomain::Body, 1); let region_m = scale::REGION_M as f64; println!("\n=== Rung-0 (GLOBAL opener) derive cost — REAL canvas shapes, MEASURED not extrapolated ===\n"); // Representative cases from the real population survey // (bmv_global_tier_bench.rs::bench_global_tier_bytes_real_population): // smallest (GJ784c-m1, a moon), Earth-class reference, largest (GJ325Ac). let cases: [(&str, f64); 3] = [ ("GJ784c-m1 (smallest, moon)", 733.9), ("Earth-class reference", 6371.0), ("GJ325Ac (largest)", 7317.6), ]; // Per-body average cell count across the real population (from the // sibling bench in this file): 18,073 cells/body, 267 bodies. const AVG_CELLS_PER_BODY: u64 = 18_073; const BODY_COUNT: u64 = 267; for (label, r_km) in cases { let cols = scale::regions_per_equator(r_km); let rows = (cols / 2).max(1); let cells = (cols as u64) * (rows as u64); let mut body_params = params.clone(); body_params.body_radius_km = Some(r_km); let t0 = Instant::now(); for row in 0..rows { for col in 0..cols { let wx = col as f64 * region_m; let wy = row as f64 * region_m; let prof = derive_orbital_at_metres(seed, "bench", &body_params, &ta, wx, wy, &climate); std::hint::black_box(prof.elev_q); } } let elapsed = t0.elapsed(); let ms = elapsed.as_secs_f64() * 1000.0; let ns_per_cell = elapsed.as_secs_f64() * 1e9 / cells as f64; println!( " {label:<28}: radius={r_km:>8.1}km cols={cols:>4} rows={rows:>4} cells={cells:>6}: \ {ms:>8.3} ms single-thread, {ns_per_cell:>7.1} ns/cell" ); } // All-267-bodies single-thread total, using the MEASURED per-cell rate // from the Earth-class case above (representative — T-1178/T-1154 already // established this per-cell rate is flat across canvas size) applied to // the REAL total cell count across the population (4,825,615, from the // sibling bench), not the average-cells-per-body figure multiplied out // blindly. let (_, earth_r_km) = cases[1]; let earth_cols = scale::regions_per_equator(earth_r_km); let earth_rows = (earth_cols / 2).max(1); let earth_cells = (earth_cols as u64) * (earth_rows as u64); let mut earth_body_params = params.clone(); earth_body_params.body_radius_km = Some(earth_r_km); let t0 = Instant::now(); for row in 0..earth_rows { for col in 0..earth_cols { let wx = col as f64 * region_m; let wy = row as f64 * region_m; let prof = derive_orbital_at_metres(seed, "bench", &earth_body_params, &ta, wx, wy, &climate); std::hint::black_box(prof.elev_q); } } let earth_elapsed = t0.elapsed(); let earth_ns_per_cell = earth_elapsed.as_secs_f64() * 1e9 / earth_cells as f64; let total_cells_all_267 = 4_825_615u64; // measured directly in bench_global_tier_bytes_real_population let total_ms_all_267_singlethread = total_cells_all_267 as f64 * earth_ns_per_cell / 1e6; println!( "\n Reference per-cell rate used for population total (Earth-class case, MEASURED above): {earth_ns_per_cell:.1} ns/cell" ); println!( " Real per-body average (this file's population bench): {AVG_CELLS_PER_BODY} cells/body x {BODY_COUNT} bodies = {} total cells", AVG_CELLS_PER_BODY * BODY_COUNT ); println!( " ALL 267 real bodies' rung-0 canvases, single-thread total (measured rate x real total cell count 4,825,615): {total_ms_all_267_singlethread:.1} ms = {:.3} s", total_ms_all_267_singlethread / 1000.0 ); println!( " Note: this is a ONE-TIME cost PER BODY (rung-0 solved once per body, held in the \ keep-always cache per Tier 1) — never a per-request or per-frame cost, and never all \ 267 bodies solved in one synchronous batch in production (each body's rung-0 canvas \ is populated lazily on that body's first Atlas-open, same as the existing D-206 \ background-queue population path). The all-267-summed total above prices the \ worst-case ceiling (every body opened once, back to back, single-threaded); the \ REAL per-body cost that matters for a single Atlas-open is the individual-body rows \ above (~16-21 ms single-thread for one body's rung-0 canvas — trivially interactive, \ parallelizes further if ever needed the same way T-1177's per-body hydrology solves do)." ); println!(); }