Skip to main content

logicaffeine_web/ui/pages/
benchmarks.rs

1use std::collections::HashMap;
2#[cfg(not(target_arch = "wasm32"))]
3use std::sync::LazyLock;
4#[cfg(target_arch = "wasm32")]
5use std::sync::OnceLock;
6use dioxus::prelude::*;
7#[cfg(all(feature = "split", target_arch = "wasm32"))]
8use dioxus::wasm_split;
9use serde::Deserialize;
10use crate::ui::components::main_nav::{MainNav, ActivePage};
11use crate::ui::components::footer::Footer;
12use crate::ui::seo::{JsonLdMultiple, PageHead, organization_schema, breadcrumb_schema, webpage_schema, BreadcrumbItem, pages as seo_pages};
13
14/// The toggle vector (one bool per registry optimization, in discriminant order)
15/// as an [`OptimizationConfig`]. Index `i` ↔ `REGISTRY[i].opt` ↔ bit `i`.
16fn config_from_toggles(toggles: &[bool]) -> logicaffeine_compile::optimization::OptimizationConfig {
17    let mut cfg = logicaffeine_compile::optimization::OptimizationConfig::all_off();
18    for (i, m) in logicaffeine_compile::optimization::REGISTRY.iter().enumerate() {
19        if toggles.get(i).copied().unwrap_or(false) {
20            cfg.set(m.opt, true);
21        }
22    }
23    cfg
24}
25
26/// The inverse of [`config_from_toggles`].
27fn toggles_from_config(cfg: &logicaffeine_compile::optimization::OptimizationConfig) -> Vec<bool> {
28    logicaffeine_compile::optimization::REGISTRY
29        .iter()
30        .map(|m| cfg.is_on(m.opt))
31        .collect()
32}
33
34#[derive(Deserialize)]
35struct BenchmarkData {
36    metadata: Metadata,
37    languages: Vec<Language>,
38    benchmarks: Vec<Benchmark>,
39    summary: SummaryData,
40}
41
42#[derive(Deserialize)]
43struct Metadata {
44    date: String,
45    commit: String,
46    logos_version: String,
47    cpu: String,
48    os: String,
49    #[serde(default)]
50    warmup: Option<u32>,
51    #[serde(default)]
52    runs: Option<u32>,
53    versions: HashMap<String, String>,
54}
55
56#[derive(Deserialize)]
57struct Language {
58    id: String,
59    label: String,
60    color: String,
61    tier: String,
62}
63
64#[derive(Deserialize)]
65struct Benchmark {
66    id: String,
67    name: String,
68    description: String,
69    reference_size: String,
70    sizes: Vec<String>,
71    logos_source: String,
72    generated_rust: String,
73    scaling: HashMap<String, HashMap<String, TimingResult>>,
74    compilation: HashMap<String, CompilationResult>,
75    #[serde(default)]
76    timeouts: HashMap<String, f64>,
77    /// Peak RSS per language per size (kB). Absent in older result files.
78    #[serde(default)]
79    memory: Option<MemoryData>,
80    /// Compiled-artifact size per language (bytes), as-built and stripped. Does not
81    /// vary with problem size, so it is a flat `by_language` map. Absent in older files.
82    #[serde(default)]
83    binary_sizes: Option<BinarySizeData>,
84    /// Declared time/space complexity. Absent in older result files.
85    #[serde(default)]
86    complexity: Option<Complexity>,
87    /// The optimizations that fired for this program (all-on), baked by the
88    /// benchmark run so the toggle tree pops in instantly. Absent in older files.
89    #[serde(default)]
90    fired: Vec<String>,
91    /// `(winner, loser)` blocker preemptions that occurred (all-on).
92    #[serde(default)]
93    blockers: Vec<(String, String)>,
94    /// `(dependent, dep)` emergent per-program dependencies (one fired only because
95    /// another was on).
96    #[serde(default)]
97    dependencies: Vec<(String, String)>,
98}
99
100#[derive(Deserialize, Clone)]
101struct MemoryData {
102    #[allow(dead_code)]
103    method: String,
104    /// size → language id → peak RSS in kB (`null` when a language was not measured).
105    by_size: HashMap<String, HashMap<String, Option<f64>>>,
106}
107
108#[derive(Deserialize, Clone)]
109struct BinarySizeData {
110    #[allow(dead_code)]
111    method: String,
112    /// language id → on-disk size of the compiled artifact in bytes.
113    by_language: HashMap<String, BinSizes>,
114}
115
116/// On-disk footprint of one artifact: the real shipped size and the code-only size
117/// after symbol stripping. Shared by per-program binaries and the engine binaries.
118#[derive(Deserialize, Clone, Copy)]
119struct BinSizes {
120    /// Size exactly as the toolchain emits it (the real shipped artifact).
121    as_built: f64,
122    /// Size after `strip --strip-all` on a throwaway copy. `null` when strip is
123    /// unavailable or the artifact carries no symbols to remove.
124    #[serde(default)]
125    stripped: Option<f64>,
126}
127
128#[derive(Deserialize, Clone)]
129struct Complexity {
130    time: String,
131    space: String,
132}
133
134#[derive(Deserialize, Clone)]
135struct TimingResult {
136    mean_ms: f64,
137    median_ms: f64,
138    stddev_ms: f64,
139    min_ms: f64,
140    max_ms: f64,
141    cv: f64,
142    runs: u32,
143    #[serde(default)]
144    user_ms: Option<f64>,
145    #[serde(default)]
146    system_ms: Option<f64>,
147}
148
149#[derive(Deserialize, Clone)]
150struct CompilationResult {
151    mean_ms: f64,
152    stddev_ms: f64,
153}
154
155#[derive(Deserialize)]
156struct SummaryData {
157    geometric_mean_speedup_vs_c: HashMap<String, f64>,
158}
159
160/// Fit a power law `t ≈ a·n^b` to `(n, t)` points by ordinary least squares on the
161/// log-log transform; returns the exponent `b` — the EMPIRICAL big-O growth rate
162/// the page shows next to the declared complexity. `None` for fewer than two
163/// distinct positive points (no slope to fit).
164fn empirical_exponent(points: &[(f64, f64)]) -> Option<f64> {
165    let pts: Vec<(f64, f64)> = points
166        .iter()
167        .filter(|&&(n, t)| n > 0.0 && t > 0.0)
168        .map(|&(n, t)| (n.ln(), t.ln()))
169        .collect();
170    if pts.len() < 2 {
171        return None;
172    }
173    let m = pts.len() as f64;
174    let sx: f64 = pts.iter().map(|p| p.0).sum();
175    let sy: f64 = pts.iter().map(|p| p.1).sum();
176    let sxx: f64 = pts.iter().map(|p| p.0 * p.0).sum();
177    let sxy: f64 = pts.iter().map(|p| p.0 * p.1).sum();
178    let denom = m * sxx - sx * sx;
179    if denom.abs() < 1e-12 {
180        return None; // all x equal → undefined slope
181    }
182    Some((m * sxy - sx * sy) / denom)
183}
184
185#[cfg(test)]
186mod tests {
187    use super::*;
188
189    #[test]
190    fn empirical_exponent_fits_linear() {
191        let pts: Vec<(f64, f64)> = [10.0, 100.0, 1000.0, 10000.0].iter().map(|&n| (n, 3.0 * n)).collect();
192        let b = empirical_exponent(&pts).expect("two+ points");
193        assert!((b - 1.0).abs() < 0.01, "linear data → exponent ~1.0, got {b}");
194    }
195
196    #[test]
197    fn empirical_exponent_fits_quadratic() {
198        let pts: Vec<(f64, f64)> = [10.0, 100.0, 1000.0].iter().map(|&n| (n, 2.0 * n * n)).collect();
199        let b = empirical_exponent(&pts).expect("two+ points");
200        assert!((b - 2.0).abs() < 0.01, "quadratic data → exponent ~2.0, got {b}");
201    }
202
203    #[test]
204    fn empirical_exponent_degenerate_is_none() {
205        assert!(empirical_exponent(&[(10.0, 5.0)]).is_none(), "one point → None");
206        assert!(empirical_exponent(&[]).is_none(), "no points → None");
207        assert!(empirical_exponent(&[(5.0, 1.0), (5.0, 9.0)]).is_none(), "all-equal n → None");
208    }
209
210    #[test]
211    fn linear_bar_pct_is_honest_and_proportional() {
212        // The largest value fills the track.
213        assert!((linear_bar_pct(200.0, 200.0) - 100.0).abs() < 1e-9);
214        // A bar's length is exactly its fraction of the max — no log distortion.
215        assert!((linear_bar_pct(50.0, 200.0) - 25.0).abs() < 1e-9);
216        assert!((linear_bar_pct(100.0, 200.0) - 50.0).abs() < 1e-9);
217        // The ratio between two bars equals the ratio between their values.
218        let a = linear_bar_pct(50.0, 200.0);
219        let b = linear_bar_pct(100.0, 200.0);
220        assert!((b / a - 2.0).abs() < 1e-9, "2x value → 2x bar, got {a} {b}");
221        // The user's grievance, made a test: ~70 µs against a 75 ms field is a sliver
222        // (< 0.2 %), NOT a third of the competitor's bar the way a log scale drew it.
223        assert!(
224            linear_bar_pct(0.070, 75.0) < 0.2,
225            "a ~1000x speed win must read as a sliver, not a third"
226        );
227        // 2.5x vs 1.21x geomean speed reads ~100 % vs ~48 % — plainly ~2x apart, not a smidge.
228        assert!((linear_bar_pct(2.544, 2.544) - 100.0).abs() < 1e-9);
229        let rust = linear_bar_pct(1.210, 2.544);
230        assert!((rust - 47.56).abs() < 0.1, "1.21/2.544 → ~47.6 %, got {rust}");
231        // Never overflows the track; a degenerate (zero) max is safe.
232        assert!(linear_bar_pct(500.0, 200.0) <= 100.0);
233        assert!(linear_bar_pct(5.0, 0.0) == 0.0);
234    }
235
236    #[test]
237    fn solver_bars_track_true_time_ratios() {
238        // On every family we present as a win, the faster solver must draw the shorter
239        // bar, and by the TRUE ratio: on a shared per-row scale, ours vs a competitor is
240        // ours_ms / competitor_ms — the honest comparative the log scale was hiding.
241        let d = &*SOLVER_DATA;
242        for fam in d.families.iter() {
243            for r in &fam.rows {
244                let scale = r.others.iter().map(|o| o.ms).fold(r.ours_ms, f64::max);
245                let ours = linear_bar_pct(r.ours_ms, scale);
246                for o in r.others.iter().filter(|o| o.status == "unsat" || o.status == "sat") {
247                    let theirs = linear_bar_pct(o.ms, scale);
248                    // Faster ⇒ shorter bar.
249                    assert!(
250                        ours <= theirs,
251                        "[{}] n={}: ours {}ms bar {ours} must not exceed {} {}ms bar {theirs}",
252                        fam.id, r.n, r.ours_ms, o.solver, o.ms
253                    );
254                    // And proportional (both above the sliver floor): bar ratio == time ratio.
255                    if ours > 0.5 && theirs > 0.5 {
256                        let bar_ratio = theirs / ours;
257                        let time_ratio = o.ms / r.ours_ms;
258                        assert!(
259                            (bar_ratio - time_ratio).abs() / time_ratio < 1e-6,
260                            "[{}] n={}: bar ratio {bar_ratio} must equal time ratio {time_ratio}",
261                            fam.id, r.n
262                        );
263                    }
264                }
265            }
266        }
267    }
268
269    #[test]
270    fn codec_bars_are_proportional_to_bytes() {
271        // The winning (smallest) LOGOS wire must draw a strictly shorter bar than a codec
272        // it beats, by the exact byte ratio — never a log-flattened near-tie.
273        let d = &*CODEC_DATA;
274        for s in d.scenarios.iter().filter(|s| s.kind == "fair") {
275            let vmax = s.rows.iter().map(|r| r.size as f64).fold(0.0, f64::max);
276            let best = s.rows.iter().filter(|r| is_logos_codec(&r.codec)).map(|r| r.size).min();
277            let json = s.rows.iter().find(|r| r.codec == "json").map(|r| r.size);
278            if let (Some(best), Some(json)) = (best, json) {
279                if best < json {
280                    let pb = linear_bar_pct(best as f64, vmax);
281                    let pj = linear_bar_pct(json as f64, vmax);
282                    assert!(pb < pj, "[{}] logos {best}B bar must be shorter than json {json}B", s.id);
283                    assert!(
284                        (pj / pb - json as f64 / best as f64).abs() < 1e-6,
285                        "[{}] codec bar ratio must equal byte ratio", s.id
286                    );
287                }
288            }
289        }
290    }
291
292    #[test]
293    fn solver_data_loads_and_we_win_where_claimed() {
294        let d = &*SOLVER_DATA; // panics if the baked solvers.json is malformed
295        assert!(d.families.len() >= 3, "solver section must ship multiple families");
296        // The pigeonhole headline must carry measured Z3 AND Kissat timeouts — the resolution wall.
297        let php = d.families.iter().find(|f| f.id == "php").expect("php family present");
298        let walls = php.rows.iter().any(|r| {
299            r.others.iter().any(|o| o.solver == "z3" && o.status == "timeout")
300                && r.others.iter().any(|o| o.solver == "kissat" && o.status == "timeout")
301        });
302        assert!(walls, "PHP must show Z3 AND Kissat hitting the resolution wall");
303        // On every family we present as a WIN, ours must never be slower than a competitor that
304        // COMPLETED (a regression like the dropped clique family — where a solver beat us — trips
305        // this immediately, so the page can never silently claim a loss as a win).
306        for fam in d.families.iter().filter(|f| {
307            f.id == "php"
308                || f.id == "mutilated_chessboard"
309                || f.id == "tseitin"
310                || f.id.starts_with("mod_")
311                || f.id == "clique_coloring"
312                || f.id == "parity_cardinality"
313                || f.id == "count_q_mod3"
314                || f.id == "ordering_gt"
315                || f.id == "grid_tseitin"
316        }) {
317            for r in &fam.rows {
318                for o in &r.others {
319                    if o.status == "unsat" || o.status == "sat" {
320                        assert!(
321                            r.ours_ms < o.ms,
322                            "[{}] n={}: claimed a win but ours {}ms >= {} {}ms",
323                            fam.id,
324                            r.n,
325                            r.ours_ms,
326                            o.solver,
327                            o.ms
328                        );
329                    }
330                }
331            }
332        }
333    }
334
335    #[test]
336    fn fmt_solver_ms_is_readable_and_never_zero() {
337        // No measured time — however tiny — may render as a zero magnitude or lose its unit.
338        let zeros = ["0", "0 µs", "0.0 µs", "0.00 µs", "0.0 ms", "0.00 ms", "0.000 ms"];
339        let mut ms = 5_000.0_f64;
340        while ms > 1e-7 {
341            let s = fmt_solver_ms(ms);
342            assert!(s.contains("µs") || s.contains("ms") || s.contains(" s"), "no unit for {ms}: {s}");
343            assert!(!zeros.contains(&s.as_str()), "ms={ms} rendered as zero: {s}");
344            ms /= 1.7; // sweep every decade down to sub-nanosecond
345        }
346        // Spot checks across the unit boundaries.
347        assert_eq!(fmt_solver_ms(0.002), "2.0 µs");
348        assert_eq!(fmt_solver_ms(0.17), "170 µs");
349        assert_eq!(fmt_solver_ms(0.999), "999 µs");
350        assert_eq!(fmt_solver_ms(9.79), "9.8 ms");
351        assert_eq!(fmt_solver_ms(504.0), "504 ms");
352        assert_eq!(fmt_solver_ms(10_009.8), "10.0 s");
353        assert_eq!(fmt_solver_ms(0.0000004), "<0.01 µs");
354        // Every "ours" time in the shipped data renders cleanly.
355        for fam in &SOLVER_DATA.families {
356            for r in &fam.rows {
357                let s = fmt_solver_ms(r.ours_ms);
358                assert!(!zeros.contains(&s.as_str()), "[{}] n={} ours renders as zero: {s}", fam.id, r.n);
359            }
360        }
361    }
362
363    #[test]
364    fn benchmark_data_deserializes_without_memory_or_complexity() {
365        // Old result files lack `memory`/`complexity`; the page must still load
366        // (BENCH_DATA is `.unwrap()`ed, so a missing field would panic the page).
367        let json = r#"{"id":"x","name":"X","description":"d","reference_size":"1",
368            "sizes":["1"],"logos_source":"","generated_rust":"","scaling":{},
369            "compilation":{}}"#;
370        let b: Benchmark = serde_json::from_str(json).expect("deserialize without memory/complexity");
371        assert!(b.memory.is_none() && b.complexity.is_none() && b.binary_sizes.is_none());
372    }
373
374    #[test]
375    fn interp_schema_backward_and_forward_compatible() {
376        // A complete TimingResult (mean..runs are required; user/system default).
377        let t = |ms: f64| {
378            format!(
379                r#"{{"mean_ms":{ms},"median_ms":{ms},"stddev_ms":0.0,"min_ms":{ms},"max_ms":{ms},"cv":0.0,"runs":10}}"#
380            )
381        };
382        // OLD JSON (pre-tiering): only `logos_interp` + `node`, no tiered geomean.
383        // Must still load (INTERP_DATA is `.unwrap()`ed → a schema break panics the page).
384        let old = format!(
385            r#"{{"metadata":{{"node":"v22","date":"x"}},
386            "benchmarks":[{{"id":"fib","name":"Fib","reference_size":"30",
387                "scaling":{{"30":{{"logos_interp":{li},"node":{nd}}}}}}}],
388            "summary":{{"geometric_mean_logos_interp_over_node":1.09}},"startup":{{}}}}"#,
389            li = t(2.0),
390            nd = t(1.0)
391        );
392        let d: InterpData = serde_json::from_str(&old).expect("old interp JSON must still load");
393        assert_eq!(d.summary.geometric_mean_logos_tiered_over_node, 0.0, "missing tiered geo defaults to 0");
394        assert!(d.interpreter_sizes.is_none(), "old interp JSON has no interpreter_sizes");
395
396        // NEW JSON: adds the `logos_tiered` engine row + the tiered geomean — both the
397        // new summary field AND the new engine in `scaling` deserialize.
398        let new = format!(
399            r#"{{"metadata":{{"node":"v22","date":"x"}},
400            "benchmarks":[{{"id":"fib","name":"Fib","reference_size":"30",
401                "scaling":{{"30":{{"logos_interp":{li},"logos_tiered":{lt},"node":{nd}}}}}}}],
402            "summary":{{"geometric_mean_logos_interp_over_node":1.09,"geometric_mean_logos_tiered_over_node":0.98}},
403            "startup":{{}}}}"#,
404            li = t(2.0),
405            lt = t(1.5),
406            nd = t(1.0)
407        );
408        let d: InterpData = serde_json::from_str(&new).expect("new interp JSON must load");
409        assert!((d.summary.geometric_mean_logos_tiered_over_node - 0.98).abs() < 1e-9);
410        assert_eq!(d.summary.geometric_mean_logos_aot_over_node, 0.0, "missing AOT geo defaults to 0");
411        let scaling = &d.benchmarks[0].scaling["30"];
412        assert!(scaling.contains_key("logos_tiered"), "tiered engine row present");
413        assert!((scaling["logos_tiered"].mean_ms - 1.5).abs() < 1e-9);
414
415        // BUNDLED JSON: adds the `logos_aot` engine row + the AOT geomean (HOTSWAP
416        // §Axis-3) — present only when a native bundle was built for the run.
417        let bundled = format!(
418            r#"{{"metadata":{{"node":"v22","date":"x"}},
419            "benchmarks":[{{"id":"fib","name":"Fib","reference_size":"30",
420                "scaling":{{"30":{{"logos_interp":{li},"logos_tiered":{lt},"logos_aot":{la},"node":{nd}}}}}}}],
421            "summary":{{"geometric_mean_logos_interp_over_node":1.09,"geometric_mean_logos_tiered_over_node":0.98,"geometric_mean_logos_aot_over_node":0.42}},
422            "startup":{{}}}}"#,
423            li = t(2.0),
424            lt = t(1.5),
425            la = t(0.6),
426            nd = t(1.0)
427        );
428        let d: InterpData = serde_json::from_str(&bundled).expect("bundled interp JSON must load");
429        assert!((d.summary.geometric_mean_logos_aot_over_node - 0.42).abs() < 1e-9);
430        let scaling = &d.benchmarks[0].scaling["30"];
431        assert!(scaling.contains_key("logos_aot"), "AOT engine row present when bundled");
432        assert!((scaling["logos_aot"].mean_ms - 0.6).abs() < 1e-9);
433    }
434
435    // ── Footprint metrics: the size data the benchmarks page now surfaces. These
436    // assert against the REAL baked-in result files, so they go RED until a
437    // `benchmarks/measure-sizes.sh --merge` backfills the JSON, then stay GREEN and
438    // guard the contract on every future run.
439
440    #[test]
441    fn every_benchmark_carries_binary_sizes() {
442        for b in &BENCH_DATA.benchmarks {
443            let sizes = b.binary_sizes.as_ref()
444                .unwrap_or_else(|| panic!("benchmark {} is missing binary_sizes", b.id));
445            assert!(!sizes.by_language.is_empty(), "benchmark {} has empty binary_sizes", b.id);
446            assert!(
447                sizes.by_language.contains_key("logos_release"),
448                "benchmark {} binary_sizes is missing the logos_release artifact", b.id
449            );
450            for (lang, s) in &sizes.by_language {
451                assert!(s.as_built > 0.0, "{}/{} as_built must be > 0, got {}", b.id, lang, s.as_built);
452                if let Some(st) = s.stripped {
453                    assert!(
454                        st > 0.0 && st <= s.as_built,
455                        "{}/{} stripped ({st}) must be in (0, as_built={}]", b.id, lang, s.as_built
456                    );
457                }
458            }
459        }
460    }
461
462    #[test]
463    fn interpreter_sizes_cover_logos_and_node() {
464        let sizes = INTERP_DATA.interpreter_sizes.as_ref()
465            .expect("latest-interp.json is missing interpreter_sizes");
466        for id in ["logos", "node"] {
467            let e = sizes.engines.get(id)
468                .unwrap_or_else(|| panic!("interpreter_sizes is missing the {id} engine"));
469            assert!(e.as_built > 0.0, "engine {id} as_built must be > 0, got {}", e.as_built);
470            if let Some(st) = e.stripped {
471                assert!(st > 0.0 && st <= e.as_built, "engine {id} stripped ({st}) out of range");
472            }
473        }
474        if let Some(w) = sizes.wasm_bundle_bytes {
475            assert!(w > 0.0, "wasm_bundle_bytes must be > 0 when present, got {w}");
476        }
477    }
478
479    #[test]
480    fn codec_data_deserializes_and_has_fair_scenarios() {
481        let d = &*CODEC_DATA;
482        assert_eq!(d.schema_version, 2, "schema_version is the page's compatibility gate");
483        let fair: Vec<_> = d.scenarios.iter().filter(|s| s.kind == "fair").collect();
484        assert!(!fair.is_empty(), "latest-codec.json must contain fair scenarios");
485        for s in &fair {
486            assert!(
487                s.rows.iter().any(|r| r.codec == "logos (BEST: all knobs)"),
488                "fair scenario '{}' is missing the BEST row",
489                s.id
490            );
491        }
492        assert!(
493            d.scenarios.iter().any(|s| s.kind == "random_access"),
494            "latest-codec.json must include the random-access scenario"
495        );
496    }
497
498    #[test]
499    fn codec_headline_is_provable() {
500        // The displayed headline ("smallest wire on N/N fair workloads") must be backed by the
501        // committed data: BEST ≤ every competitor on every fair workload.
502        let (wins, total) = codec_size_wins(&CODEC_DATA);
503        assert!(total > 0, "expected fair workloads in latest-codec.json");
504        assert_eq!(wins, total, "the baked data must back the smallest-wire-on-all-workloads headline");
505    }
506
507    #[test]
508    fn codec_scorecard_fair_axes_all_win() {
509        // The scorecard claims "fastest encode N/N" and "fastest decode N/N" — the baked data
510        // must back both (our fastest dial ≤ every competitor on every fair workload).
511        let (enc, total) = codec_axis_wins(&CODEC_DATA, CodecAxis::Encode);
512        let (dec, _) = codec_axis_wins(&CODEC_DATA, CodecAxis::Decode);
513        assert!(total > 0);
514        assert_eq!(enc, total, "scorecard claims fastest encode on all fair workloads");
515        assert_eq!(dec, total, "scorecard claims fastest decode on all fair workloads");
516        // The geo-mean size advantage and top-showcase ratio are real wins (> 1×).
517        assert!(codec_geomean_size(&CODEC_DATA) > 1.0, "geo-mean size advantage must exceed 1×");
518        assert!(codec_top_showcase(&CODEC_DATA).is_some_and(|r| r > 10.0), "a showcase must crush by >10×");
519    }
520
521    #[test]
522    fn format_bytes_scales_units() {
523        assert_eq!(format_bytes(16_120.0), "16 KB");
524        assert_eq!(format_bytes(2.0 * 1024.0 * 1024.0), "2.0 MB");
525        assert_eq!(format_bytes(3.0 * 1024.0 * 1024.0 * 1024.0), "3.0 GB");
526    }
527
528    #[test]
529    fn footprint_label_only_tags_a_distinct_stripped_size() {
530        // Clearly different (Rust ~2 MB → ~300 KB stripped): the tag is shown.
531        assert_eq!(footprint_label(2_033_384.0, Some(307_280.0)), "1.9 MB (300 KB stripped)");
532        // Already-minimal binary (334592 vs 334584 both render "327 KB"): no redundant tag.
533        assert_eq!(footprint_label(334_592.0, Some(334_584.0)), "327 KB");
534        // No stripped figure (java bytecode): just the as-built size.
535        assert_eq!(footprint_label(583.0, None), "1 KB");
536        // Defensive: a stripped value not smaller than as-built is ignored.
537        assert_eq!(footprint_label(1000.0, Some(2000.0)), format_bytes(1000.0));
538    }
539
540    #[test]
541    fn shipped_footprint_prefers_the_deployable_stripped_size() {
542        // Rust ships stripped (300 KB) though it builds to ~2 MB with a symbol table — the
543        // bar must use the 300 KB you actually deploy, with the as-built size alongside.
544        assert_eq!(shipped_bytes(2_033_384.0, Some(307_280.0)), 307_280.0);
545        assert_eq!(shipped_footprint_label(2_033_384.0, Some(307_280.0)), "300 KB (1.9 MB as-built)");
546        // LOGOS already ships stripped (as-built ≈ stripped): the as-built figure is ALWAYS
547        // shown for parity with every other row — the two numbers being equal is the story.
548        assert_eq!(shipped_bytes(334_592.0, Some(334_584.0)), 334_584.0);
549        assert_eq!(shipped_footprint_label(334_592.0, Some(334_584.0)), "327 KB (327 KB as-built)");
550        // No stripped figure (a JVM class directory): shipped == as-built, shown consistently.
551        assert_eq!(shipped_bytes(583.0, None), 583.0);
552        assert_eq!(shipped_footprint_label(583.0, None), "1 KB (1 KB as-built)");
553        // Defensive: a bogus stripped ≥ as-built is ignored (never inflate the shipped size).
554        assert_eq!(shipped_bytes(1000.0, Some(2000.0)), 1000.0);
555    }
556
557    #[test]
558    fn every_language_bar_uses_a_stripped_or_fallback_shipped_size() {
559        // Across every benchmark, the value that drives each bar must be the shipped size:
560        // the stripped binary where we have one, else the as-built artifact — never a mix
561        // that would pit an already-stripped LOGOS against unstripped competitors.
562        for b in BENCH_DATA.benchmarks.iter() {
563            let Some(sizes) = b.binary_sizes.as_ref() else { continue };
564            for (lang, s) in sizes.by_language.iter() {
565                let shipped = shipped_bytes(s.as_built, s.stripped);
566                assert!(shipped > 0.0 && shipped <= s.as_built,
567                    "{}/{lang}: shipped {shipped} must be in (0, as_built={}]", b.id, s.as_built);
568                if let Some(st) = s.stripped {
569                    if st > 0.0 && st <= s.as_built {
570                        assert_eq!(shipped, st, "{}/{lang}: must ship the stripped size", b.id);
571                    }
572                }
573            }
574        }
575    }
576
577    #[test]
578    fn every_codec_scenario_has_a_good_for_line() {
579        // Every example the harness emits must read as a use case — codec_good_for covers every
580        // scenario id, so a new scenario can't ship without its "what it's good for" copy.
581        for s in CODEC_DATA.scenarios.iter() {
582            assert!(codec_good_for(&s.id).is_some(), "scenario '{}' has no codec_good_for copy", s.id);
583        }
584    }
585
586    #[test]
587    fn every_fair_best_row_names_the_dials_that_won() {
588        // The winner card is driven by the BEST row's `chosen`; every fair example must carry it
589        // with a non-empty summary + columns, or the card would fall back to opaque "all knobs".
590        for s in CODEC_DATA.scenarios.iter().filter(|s| s.kind == "fair") {
591            let best = codec_best_row(s).unwrap_or_else(|| panic!("fair '{}' missing the BEST row", s.id));
592            let chosen = best.chosen.as_ref().unwrap_or_else(|| panic!("fair '{}' BEST row missing chosen", s.id));
593            assert!(!chosen.summary.trim().is_empty(), "fair '{}' chosen.summary is empty", s.id);
594            assert!(!chosen.columns.is_empty(), "fair '{}' chosen.columns is empty", s.id);
595        }
596    }
597
598    #[test]
599    fn every_fair_scenario_has_a_fair_fight() {
600        // The honest compressed-vs-compressed comparison must be computable on every fair workload —
601        // i.e. the competitors carry a `fair_size`, so the scorecard's "fair fight" count is real.
602        for s in CODEC_DATA.scenarios.iter().filter(|s| s.kind == "fair") {
603            let (lo, co, _) = codec_fair_fight(s)
604                .unwrap_or_else(|| panic!("fair '{}' has no fair-fight (competitors missing fair_size)", s.id));
605            assert!(lo > 0 && co > 0, "fair '{}' fair-fight sizes must be positive", s.id);
606        }
607        // And the scorecard's fair-fight count is honest: LOGOS does not have to win all of them.
608        let (wins, total) = codec_fair_size_wins(&CODEC_DATA);
609        assert!(total > 0 && wins <= total, "fair-fight count must be a valid n/{total}");
610    }
611
612    #[test]
613    fn sources_cover_every_benchmark() {
614        // Every benchmark in latest.json must resolve its 11-language sources BY ID — the
615        // lookup the page renders — so a regenerated latest.json can never silently
616        // desynchronize from the program sources the way positional indexing could.
617        for b in BENCH_DATA.benchmarks.iter() {
618            let s = bench_sources_for(&b.id)
619                .unwrap_or_else(|| panic!("benchmark '{}' has no sources entry", b.id));
620            for (lang, src) in [
621                ("c", s.c), ("cpp", s.cpp), ("rust", s.rust), ("zig", s.zig), ("go", s.go),
622                ("java", s.java), ("js", s.js), ("python", s.python), ("ruby", s.ruby),
623                ("nim", s.nim), ("logos", s.logos),
624            ] {
625                assert!(!src.trim().is_empty(), "benchmark '{}' source '{lang}' is empty", b.id);
626            }
627        }
628    }
629}
630
631// The page's data feeds. Native builds (tests, SSG prerender) compile the repo's
632// benchmark results straight in; the wasm build fetches the identical bytes from
633// `/data/*` (staged by scripts/stage-web-data.sh) so a megabyte of JSON never rides
634// inside the shipped binary. Both sides answer through the same accessors below.
635#[cfg(not(target_arch = "wasm32"))]
636static BENCH_DATA: LazyLock<BenchmarkData> = LazyLock::new(|| {
637    serde_json::from_str(include_str!("../../../../../benchmarks/results/latest.json")).unwrap()
638});
639#[cfg(target_arch = "wasm32")]
640static BENCH_DATA: OnceLock<BenchmarkData> = OnceLock::new();
641
642/// The language benchmark feed. `None` only on wasm before [`load_bench_bundle`]
643/// resolves — the `Benchmarks` gate renders the loaded page strictly after that.
644fn bench_data() -> Option<&'static BenchmarkData> {
645    #[cfg(not(target_arch = "wasm32"))]
646    {
647        Some(&BENCH_DATA)
648    }
649    #[cfg(target_arch = "wasm32")]
650    {
651        BENCH_DATA.get()
652    }
653}
654
655// Our certified prover vs the field — Z3 (SMT), Kissat (the CDCL world champion) and SaDiCaL (the
656// reference PR/SDCL solver) — on structured-UNSAT families. Produced by benchmarks/run-solver-vs-z3.sh
657// (native; external solvers run as subprocesses on the byte-identical DIMACS, emitting a clausal
658// proof). Our verdicts are pure-Rust and browser-identical; the whole crate is Z3-free in WASM.
659#[derive(Deserialize)]
660struct SolverData {
661    #[serde(default)]
662    metadata: SolverMeta,
663    families: Vec<SolverFamily>,
664}
665
666#[derive(Deserialize, Default)]
667struct SolverMeta {
668    #[serde(default)]
669    date: String,
670    #[serde(default)]
671    cpu: String,
672    #[serde(default)]
673    kissat: String,
674    #[serde(default)]
675    sadical: String,
676    #[serde(default)]
677    cadical: String,
678    #[serde(default)]
679    cryptominisat: String,
680}
681
682#[derive(Deserialize)]
683struct SolverFamily {
684    id: String,
685    name: String,
686    /// How our prover wins (SR proof / matching / GF(2) Gaussian / plain CDCL).
687    mechanism: String,
688    /// The honest one-line separation framing.
689    separation: String,
690    /// Longer caption (e.g. the SDCL auto-discovery callout for PHP).
691    note: String,
692    rows: Vec<SolverRow>,
693}
694
695#[derive(Deserialize)]
696struct SolverRow {
697    n: u32,
698    ours_ms: f64,
699    #[serde(default)]
700    ours_min_ms: f64,
701    ours_detail: String,
702    /// Size in bytes of OUR certified proof where one exists (SR proof / compact GF-ring certificate),
703    /// so the "ours" bar shows a proof size just like the competitors — the answer to "why doesn't
704    /// Logos show its proof size?". `None` for a structural witness (chessboard, pigeonhole variants).
705    #[serde(default)]
706    ours_proof_bytes: Option<u64>,
707    /// Short format label for that proof (`SR`, `GF(2) cert`, `ℤ/6 cert`, …), shown beside the size.
708    #[serde(default)]
709    ours_proof_fmt: Option<String>,
710    /// Competing solvers on the SAME instance (z3 / kissat / sadical / cadical / cryptominisat), in
711    /// display order.
712    #[serde(default)]
713    others: Vec<OtherResult>,
714}
715
716/// One competitor's result on an instance. `status`: "unsat" (solved it), "sat", "timeout" (hit the
717/// wall), or "error"/"absent". `proof_bytes` is the emitted clausal-proof size where it completed.
718#[derive(Deserialize)]
719struct OtherResult {
720    solver: String,
721    status: String,
722    ms: f64,
723    #[serde(default)]
724    proof_bytes: Option<u64>,
725}
726
727#[cfg(not(target_arch = "wasm32"))]
728static SOLVER_DATA: LazyLock<SolverData> = LazyLock::new(|| {
729    serde_json::from_str(include_str!("../../../../../benchmarks/results/solvers.json")).unwrap()
730});
731#[cfg(target_arch = "wasm32")]
732static SOLVER_DATA: OnceLock<SolverData> = OnceLock::new();
733
734/// The solver head-to-head feed — same gating contract as [`bench_data`].
735fn solver_data() -> Option<&'static SolverData> {
736    #[cfg(not(target_arch = "wasm32"))]
737    {
738        Some(&SOLVER_DATA)
739    }
740    #[cfg(target_arch = "wasm32")]
741    {
742        SOLVER_DATA.get()
743    }
744}
745
746/// A duration label that stays readable across the whole range and NEVER collapses to a misleading
747/// "0 ms", no matter how tiny: sub-millisecond times render in microseconds with enough precision to
748/// always show a non-zero figure (and `<0.01 µs` for the physically-impossible deep-sub-µs case),
749/// the 1 ms…10 s band in milliseconds, and anything above in seconds.
750fn fmt_solver_ms(ms: f64) -> String {
751    if !(ms > 0.0) {
752        return "0".to_string();
753    }
754    if ms < 1.0 {
755        let us = ms * 1000.0;
756        if us < 0.01 {
757            "<0.01 µs".to_string()
758        } else if us < 1.0 {
759            format!("{us:.2} µs")
760        } else if us < 10.0 {
761            format!("{us:.1} µs")
762        } else {
763            format!("{us:.0} µs")
764        }
765    } else if ms < 100.0 {
766        format!("{ms:.1} ms")
767    } else if ms < 10_000.0 {
768        format!("{ms:.0} ms")
769    } else {
770        format!("{:.1} s", ms / 1000.0)
771    }
772}
773
774/// Honest bar width: linear and proportional, so a bar's length is its value as a
775/// fraction of the chart's largest value. A value 1000× smaller than the max is a
776/// 1000× shorter bar — the true sliver (kept a hair visible by the track's min-width),
777/// never a log-compressed stub that flatters the loser or shrinks the winner's lead.
778/// The exact number always rides alongside the bar, so a sliver never hides its size.
779fn linear_bar_pct(value: f64, max: f64) -> f64 {
780    if max <= 0.0 {
781        return 0.0;
782    }
783    (value / max * 100.0).clamp(0.0, 100.0)
784}
785
786/// Bar colour per competitor (ours is cyan; each solver its own hue; timeout is red, handled inline).
787fn solver_color(name: &str) -> &'static str {
788    match name {
789        "z3" => "#a78bfa",
790        "kissat" => "#fb923c",
791        "sadical" => "#9ca3af",
792        "cadical" => "#f472b6",
793        "cryptominisat" => "#34d399",
794        _ => "#6b7280",
795    }
796}
797
798/// Display name for a competitor id.
799fn solver_label(name: &str) -> String {
800    match name {
801        "z3" => "Z3".to_string(),
802        "kissat" => "Kissat".to_string(),
803        "sadical" => "SaDiCaL".to_string(),
804        "cadical" => "CaDiCaL".to_string(),
805        "cryptominisat" => "CryptoMiniSat".to_string(),
806        other => other.to_string(),
807    }
808}
809
810/// One labelled bar (ours or a competitor), reusing the page's `bench-bar-*` styling with the
811/// inside/outside label rule the runtime charts use.
812fn solver_bar(label: &str, pct: f64, color: &str, time: &str, detail: &str) -> Element {
813    let show_inside = pct > 34.0;
814    rsx! {
815        div { class: "bench-bar-row",
816            div { class: "bench-bar-label", "{label}" }
817            div { class: "bench-bar-track",
818                div {
819                    class: "bench-bar-fill",
820                    style: "width: {pct:.1}%; background: {color};",
821                    title: "{detail}",
822                    if show_inside {
823                        span { class: "bench-bar-time", "{time}" }
824                    }
825                }
826            }
827            if !show_inside {
828                span { class: "bench-bar-time-outside", "{time}" }
829            }
830        }
831    }
832}
833
834/// The "Our solver vs the field" section: per-family bar charts (ours vs Z3, Kissat, SaDiCaL)
835/// over the families where structure beats brute force, led by the pigeonhole wall. Bars are
836/// linear per row — the slowest fills the track, ours is its true fraction — so a microsecond
837/// refutation reads as the sliver it is. All numbers are measured by
838/// `benchmarks/run-solver-vs-z3.sh`; the framing is the honest one the data supports — SaDiCaL
839/// completes (we beat it), Z3 and Kissat hit the resolution wall.
840#[component]
841pub fn SolverSection() -> Element {
842    let data = solver_data().expect("rendered only inside the loaded Benchmarks page");
843    let meta = &data.metadata;
844    // Headline figures, derived from the measured PHP data so the prose can never drift from it.
845    let php = data.families.iter().find(|f| f.id == "php");
846    let head = php.and_then(|f| {
847        let r0 = f.rows.first()?;
848        let walled: Vec<String> = r0
849            .others
850            .iter()
851            .filter(|o| o.status == "timeout")
852            .map(|o| solver_label(&o.solver))
853            .collect();
854        let sad_max = f
855            .rows
856            .iter()
857            .filter(|r| r.ours_ms > 0.0)
858            .filter_map(|r| {
859                r.others
860                    .iter()
861                    .find(|o| o.solver == "sadical" && o.status == "unsat")
862                    .map(|s| s.ms / r.ours_ms)
863            })
864            .fold(0.0_f64, f64::max);
865        Some((r0.n, fmt_solver_ms(r0.ours_ms), walled, sad_max))
866    });
867
868    rsx! {
869        div { class: "bench-section", id: "solver",
870            div { class: "bench-section-title", "Our solver vs the field" }
871            div { class: "bench-section-desc",
872                "Raw speed is one axis; reasoning is another. On the classic structured-UNSAT families, our pure-Rust certified prover decides in milliseconds what brute-force search cannot — the same engine that runs in the Studio, in your browser, with no Z3. We measure it on a byte-identical formula against Z3 (SMT), Kissat (the CDCL world champion) and SaDiCaL (the reference PR/SDCL solver). Every \u{201c}ours\u{201d} verdict is a re-checked certificate, not a trusted answer."
873            }
874
875            if let Some((n, ours, walled, sad_max)) = head {
876                div {
877                    style: "background: linear-gradient(135deg, rgba(34,211,238,0.10), rgba(167,139,250,0.10)); border: 1px solid rgba(34,211,238,0.25); border-radius: 12px; padding: 16px 18px; margin-bottom: 22px;",
878                    div { style: "font-size: 15px; font-weight: 700; color: #e5e7eb; margin-bottom: 4px;",
879                        "A proof-system gap, not a tuning trick"
880                    }
881                    div { style: "font-size: 13px; color: rgba(229,231,235,0.7); line-height: 1.5;",
882                        {
883                            let walled_str = if walled.is_empty() { "Z3 and Kissat".to_string() } else { walled.join(" and ") };
884                            rsx! {
885                                "{walled_str} can't even finish PHP({n}) — they hit the resolution wall every CDCL solver inherits (Haken 1985, 2^\u{03a9}(n)). We certify it in {ours}"
886                                if sad_max >= 1.5 {
887                                    ", and beat SaDiCaL — the reference PR/SDCL solver, in our own proof class — by up to {sad_max:.0}\u{00d7}, with a kilobyte-scale certificate against its megabytes"
888                                }
889                                ". Our SDCL even "
890                                em { "discovers" }
891                                " that proof from the raw clauses with zero hints."
892                            }
893                        }
894                    }
895                }
896            }
897
898            for fam in data.families.iter() {
899                div {
900                    style: "margin-bottom: 26px;",
901                    div { style: "font-size: 15px; font-weight: 700; color: #fff;", "{fam.name}" }
902                    div { style: "font-size: 12px; color: rgba(34,211,238,0.85); margin: 2px 0 2px;", "ours: {fam.mechanism}" }
903                    div { style: "font-size: 12px; color: rgba(229,231,235,0.55); margin-bottom: 12px;", "{fam.separation}" }
904                    div { class: "bench-chart",
905                        for row in fam.rows.iter() {
906                            div { style: "margin-bottom: 12px;",
907                                div { style: "font-size: 11px; color: rgba(229,231,235,0.5); font-family: ui-monospace, monospace; margin-bottom: 2px;", "n = {row.n}" }
908                                {
909                                    // Per-row honest scale: the slowest bar — a finite solve, or a
910                                    // timeout's ceiling — fills the track, and every other bar is its
911                                    // true fraction of it, so a microsecond refutation reads as the
912                                    // sliver it is next to a multi-second competitor.
913                                    let scale_max = row.others.iter().map(|o| o.ms).fold(row.ours_ms, f64::max);
914                                    rsx! {
915                                        div { class: "bench-chart",
916                                            {
917                                                // Our own bar now carries our proof size too — the SR proof or the
918                                                // compact GF/ring certificate — beside the time, exactly the way the
919                                                // competitors show theirs, with its format labelled so a linear-algebra
920                                                // certificate is never mistaken for a clausal DRAT.
921                                                let mut ours_lbl = fmt_solver_ms(row.ours_ms);
922                                                if let Some(pb) = row.ours_proof_bytes {
923                                                    let fmt = row.ours_proof_fmt.as_deref().unwrap_or("proof");
924                                                    ours_lbl = format!("{ours_lbl} · {} {fmt}", format_bytes(pb as f64));
925                                                }
926                                                solver_bar("ours", linear_bar_pct(row.ours_ms, scale_max), "#22d3ee", &ours_lbl, &row.ours_detail)
927                                            }
928                                            for o in row.others.iter() {
929                                                {
930                                                    let (pct, color, lbl) = match o.status.as_str() {
931                                                        "timeout" => (100.0_f64, "#ef4444", format!("timeout ≥{}", fmt_solver_ms(o.ms))),
932                                                        "unsat" | "sat" => {
933                                                            let mut l = fmt_solver_ms(o.ms);
934                                                            if let Some(pb) = o.proof_bytes {
935                                                                l = format!("{l} · {} proof", format_bytes(pb as f64));
936                                                            }
937                                                            (linear_bar_pct(o.ms, scale_max), solver_color(&o.solver), l)
938                                                        }
939                                                        other => (1.0_f64, "#475569", other.to_string()),
940                                                    };
941                                                    solver_bar(&solver_label(&o.solver), pct, color, &lbl, &format!("{} — solve + proof", solver_label(&o.solver)))
942                                                }
943                                            }
944                                        }
945                                    }
946                                }
947                            }
948                        }
949                    }
950                    div { style: "font-size: 11.5px; color: rgba(229,231,235,0.5); line-height: 1.5; margin-top: 8px;", "{fam.note}" }
951                }
952            }
953
954            div { style: "font-size: 11px; color: rgba(229,231,235,0.4); line-height: 1.5; border-top: 1px solid rgba(255,255,255,0.08); padding-top: 12px;",
955                "Method: Kissat, SaDiCaL, CaDiCaL and CryptoMiniSat run as subprocesses on the byte-identical DIMACS, each emitting a clausal proof to disk whose size is shown (solve + certify, like ours); Z3 is the in-process oracle (no proof). Our own proof size is the size of our certified artifact — the SR proof for the pigeonhole class, the compact GF/ℤ-ring linear certificate for the algebraic families — measured by streaming it through a byte counter in memory, never written to disk and capped so it can never itself exhaust RAM. CryptoMiniSat runs in its default DRAT-emitting config; with its GF(2) Gaussian enabled it would decide parity fast but then could not emit a standard clausal proof — the certified gap. Ours is the median of 5 release runs (identical to the WASM build). Timeouts: Z3 10 s, Kissat/CaDiCaL/CryptoMiniSat 15 s, SaDiCaL 45 s (generous, so the PR solver runs to completion — no inflation). Sub-millisecond times are dominated by external process startup, so the headline claims rest on the cases where a competitor takes seconds or hits the wall. Random 3-SAT is the honesty control."
956                if !meta.cpu.is_empty() {
957                    span { " · Measured on {meta.cpu}" }
958                }
959                if !meta.kissat.is_empty() {
960                    span { " · Kissat {meta.kissat}" }
961                }
962                if !meta.cadical.is_empty() {
963                    span { " · CaDiCaL {meta.cadical}" }
964                }
965                if !meta.cryptominisat.is_empty() {
966                    span { " · CryptoMiniSat {meta.cryptominisat}" }
967                }
968                if !meta.date.is_empty() {
969                    span { " · {meta.date}" }
970                }
971            }
972        }
973    }
974}
975
976#[cfg(test)]
977mod solver_data_guard {
978    use super::*;
979
980    #[test]
981    fn solver_data_parses_and_carries_our_proof_size() {
982        // Guards the `include_str!` contract the page renders — and, specifically, that a regenerated
983        // solvers.json keeps OUR proof size, the answer to "why doesn't Logos show its proof size?".
984        let data = &*SOLVER_DATA;
985        assert!(!data.families.is_empty(), "solvers.json must have families");
986
987        // The pigeonhole family reports our SR proof size on every row.
988        let php = data.families.iter().find(|f| f.id == "php").expect("php family present");
989        assert!(
990            php.rows.iter().all(|r| r.ours_proof_bytes.is_some() && r.ours_proof_fmt.is_some()),
991            "every PHP row must carry our own SR proof size"
992        );
993
994        // Every structural family carries a proof, per its own certificate kind: GF/ring linear
995        // certificate (parity/mod), the O(1) counting certificate (pigeonhole variants), the Hall
996        // witness (chessboard). "Proofs for all", the answer to "shouldn't every family have one?".
997        for id in ["tseitin", "mod_3_tseitin", "mod_6_tseitin", "php_variants", "mutilated_chessboard"] {
998            let fam = data.families.iter().find(|f| f.id == id).unwrap_or_else(|| panic!("{id} present"));
999            assert!(
1000                fam.rows.iter().all(|r| r.ours_proof_bytes.is_some()),
1001                "the {id} family must carry a proof size on every row"
1002            );
1003        }
1004
1005        // The random control carries a plain-CDCL DRAT wherever it refutes (its UNSAT row); a SAT row
1006        // has a model, not a refutation, so no proof size there — and that is the only allowed gap.
1007        let random = data.families.iter().find(|f| f.id == "random_3sat").expect("random present");
1008        assert!(
1009            random.rows.iter().any(|r| r.ours_detail.contains("unsat") && r.ours_proof_bytes.is_some()),
1010            "the random control's UNSAT row must carry a DRAT proof size"
1011        );
1012
1013        // CaDiCaL joined the field (CryptoMiniSat too when its binary is present at bench time).
1014        let solvers: std::collections::HashSet<&str> = data
1015            .families
1016            .iter()
1017            .flat_map(|f| f.rows.iter())
1018            .flat_map(|r| r.others.iter())
1019            .map(|o| o.solver.as_str())
1020            .collect();
1021        assert!(solvers.contains("cadical"), "CaDiCaL must appear in the field");
1022    }
1023}
1024
1025// The LOGOS wire codec vs the industry serializers (Cap'n Proto, MessagePack, protobuf,
1026// bincode, postcard, CBOR, Arrow, JSON) — same logical data, same machine. Produced by
1027// the wirebench harness (crates/logicaffeine_wirebench) via benchmarks/run.sh Phase 7.
1028#[derive(Deserialize)]
1029struct CodecData {
1030    #[serde(default)]
1031    schema_version: u32,
1032    #[serde(default)]
1033    metadata: CodecMetadata,
1034    #[serde(default)]
1035    #[allow(dead_code)]
1036    iters: u32,
1037    #[serde(default)]
1038    scenarios: Vec<CodecScenario>,
1039}
1040
1041#[derive(Deserialize, Default)]
1042struct CodecMetadata {
1043    #[serde(default)]
1044    date: String,
1045    #[serde(default)]
1046    #[allow(dead_code)]
1047    commit: String,
1048    #[serde(default)]
1049    #[allow(dead_code)]
1050    logos_version: String,
1051    #[serde(default)]
1052    cpu: String,
1053    #[serde(default)]
1054    os: String,
1055    #[serde(default)]
1056    versions: HashMap<String, String>,
1057    #[serde(default)]
1058    features: Vec<String>,
1059}
1060
1061#[derive(Deserialize, Clone)]
1062struct CodecScenario {
1063    id: String,
1064    title: String,
1065    #[serde(default)]
1066    n: usize,
1067    kind: String,
1068    rows: Vec<CodecRow>,
1069}
1070
1071#[derive(Deserialize, Clone)]
1072struct CodecRow {
1073    codec: String,
1074    size: usize,
1075    #[serde(default)]
1076    enc_ns: f64,
1077    #[serde(default)]
1078    dec_ns: f64,
1079    #[serde(default)]
1080    read_one_ns: Option<f64>,
1081    #[serde(default)]
1082    chosen: Option<ChosenConfig>,
1083    /// This codec's smallest size once granted the same compression LOGOS bakes in — set on the
1084    /// competitors, so the page can show a fair compressed-vs-compressed size fight. `None` on the
1085    /// LOGOS rows (the all-knobs winner's `size` is already its fair, compression-shopped size).
1086    #[serde(default)]
1087    fair_size: Option<usize>,
1088}
1089
1090/// Which dials the all-knobs winner actually selected — surfaced so a card can say *what* won,
1091/// not just "all knobs". `columns` names the real per-column encoding the codec shipped (one bare
1092/// name for a single-column message, or one `"field: encoding"` per field for a record list);
1093/// `summary` is the line the card shows verbatim. Present only on the `logos (BEST: all knobs)` row.
1094#[derive(Deserialize, Clone)]
1095struct ChosenConfig {
1096    #[serde(default)]
1097    #[allow(dead_code)]
1098    numerics: String,
1099    #[serde(default)]
1100    #[allow(dead_code)]
1101    floats: String,
1102    #[serde(default)]
1103    #[allow(dead_code)]
1104    compression: String,
1105    #[serde(default)]
1106    #[allow(dead_code)]
1107    columns: Vec<String>,
1108    #[serde(default)]
1109    summary: String,
1110}
1111
1112#[cfg(not(target_arch = "wasm32"))]
1113static CODEC_DATA: LazyLock<CodecData> = LazyLock::new(|| {
1114    serde_json::from_str(include_str!("../../../../../benchmarks/results/latest-codec.json")).unwrap()
1115});
1116#[cfg(target_arch = "wasm32")]
1117static CODEC_DATA: OnceLock<CodecData> = OnceLock::new();
1118
1119/// The wire-codec head-to-head feed — same gating contract as [`bench_data`].
1120fn codec_data() -> Option<&'static CodecData> {
1121    #[cfg(not(target_arch = "wasm32"))]
1122    {
1123        Some(&CODEC_DATA)
1124    }
1125    #[cfg(target_arch = "wasm32")]
1126    {
1127        CODEC_DATA.get()
1128    }
1129}
1130
1131/// Every LOGOS dial (varint / fixed / group-varint / affine / struct-view / all-knobs) is
1132/// rendered in the cyan family and highlighted; everything else is a competitor.
1133fn is_logos_codec(c: &str) -> bool {
1134    c.starts_with("logos")
1135}
1136
1137fn codec_label(c: &str) -> &str {
1138    match c {
1139        "logos (BEST: all knobs)" => "LOGOS \u{2014} all knobs",
1140        "logos (varint)" => "LOGOS \u{2014} varint",
1141        "logos (fixed)" => "LOGOS \u{2014} fixed (memcpy)",
1142        "logos (gv/simd)" => "LOGOS \u{2014} group-varint",
1143        "logos (affine)" => "LOGOS \u{2014} affine",
1144        "logos (struct-view)" => "LOGOS \u{2014} struct-view",
1145        "logos (struct-view fixed)" => "LOGOS \u{2014} struct-view (fixed)",
1146        "logos (zero-copy)" => "LOGOS \u{2014} zero-copy",
1147        "bincode" => "bincode",
1148        "postcard" => "postcard",
1149        "messagepack" => "MessagePack",
1150        "cbor" => "CBOR",
1151        "json" => "JSON",
1152        "arrow (ipc)" => "Apache Arrow",
1153        "protobuf/grpc" => "Protobuf / gRPC",
1154        "capnproto" => "Cap'n Proto",
1155        other => other,
1156    }
1157}
1158
1159fn codec_color(c: &str) -> &'static str {
1160    match c {
1161        "logos (BEST: all knobs)" => "#00d4ff",
1162        "logos (struct-view)" => "#00d4ff",
1163        "logos (struct-view fixed)" => "#26c6da",
1164        "logos (zero-copy)" => "#22d3ee",
1165        "logos (varint)" => "#0098c4",
1166        "logos (fixed)" => "#4dd0e1",
1167        "logos (gv/simd)" => "#26c6da",
1168        "logos (affine)" => "#80deea",
1169        "bincode" => "#dea584",
1170        "postcard" => "#f7a41d",
1171        "messagepack" => "#c0392b",
1172        "cbor" => "#8e44ad",
1173        "json" => "#f7df1e",
1174        "arrow (ipc)" => "#00ADD8",
1175        "protobuf/grpc" => "#4285f4",
1176        "capnproto" => "#e67e22",
1177        _ => "#94a3b8",
1178    }
1179}
1180
1181/// A nanoseconds-per-op label that stays readable from a single-field read (~40 ns) to a
1182/// whole-message JSON decode (hundreds of µs).
1183fn format_ns(ns: f64) -> String {
1184    if ns < 1000.0 {
1185        format!("{ns:.0} ns")
1186    } else if ns < 1_000_000.0 {
1187        format!("{:.2} \u{00b5}s", ns / 1000.0)
1188    } else {
1189        format!("{:.2} ms", ns / 1_000_000.0)
1190    }
1191}
1192
1193#[derive(Clone, Copy, PartialEq)]
1194enum CodecAxis {
1195    Size,
1196    Encode,
1197    Decode,
1198    ReadOne,
1199}
1200
1201/// One axis of a codec scenario as a sorted (winner-on-top) horizontal bar chart, reusing
1202/// the page's `bench-bar-*` styling. Rows missing the axis (e.g. no `read_one_ns`) are
1203/// dropped, so the same helper serves the size/encode/decode charts and the random-access one.
1204fn codec_axis_chart(s: &CodecScenario, axis: CodecAxis) -> Element {
1205    let val = |r: &CodecRow| -> Option<f64> {
1206        match axis {
1207            CodecAxis::Size => Some(r.size as f64),
1208            CodecAxis::Encode => Some(r.enc_ns),
1209            CodecAxis::Decode => Some(r.dec_ns),
1210            CodecAxis::ReadOne => r.read_one_ns,
1211        }
1212    };
1213    let fmt = |r: &CodecRow| -> String {
1214        match axis {
1215            CodecAxis::Size => format_bytes(r.size as f64),
1216            _ => format_ns(val(r).unwrap_or(0.0)),
1217        }
1218    };
1219    let mut rows: Vec<CodecRow> = s.rows.iter().filter(|r| val(r).is_some()).cloned().collect();
1220    rows.sort_by(|a, b| val(a).unwrap().partial_cmp(&val(b).unwrap()).unwrap_or(std::cmp::Ordering::Equal));
1221    if rows.is_empty() {
1222        return rsx! {};
1223    }
1224    // Sorted ascending, so the last row is the worst (largest) — it fills the track and
1225    // every other bar is its honest fraction of it.
1226    let vmax = val(rows.last().unwrap()).unwrap();
1227    rsx! {
1228        div { class: "bench-chart",
1229            for r in rows.iter() {
1230                {
1231                    let v = val(r).unwrap();
1232                    let pct = linear_bar_pct(v, vmax);
1233                    let s_str = fmt(r);
1234                    let fill_class = if is_logos_codec(&r.codec) { "bench-codec-fill logos-highlight" } else { "bench-codec-fill" };
1235                    let val_class = if is_logos_codec(&r.codec) { "bench-codec-val logos-val" } else { "bench-codec-val" };
1236                    let color = codec_color(&r.codec);
1237                    let label = codec_label(&r.codec);
1238                    rsx! {
1239                        div { class: "bench-bar-row",
1240                            div { class: "bench-bar-label", "{label}" }
1241                            div { class: "bench-codec-track",
1242                                div { class: "{fill_class}", style: "width: {pct:.1}%; background: {color};" }
1243                            }
1244                            div { class: "{val_class}", "{s_str}" }
1245                        }
1246                    }
1247                }
1248            }
1249        }
1250    }
1251}
1252
1253/// The provable headline: the count of fair workloads where `logos (BEST: all knobs)` is no
1254/// larger than EVERY competitor (ties count), out of all fair workloads. True by construction
1255/// — the all-knobs row tries every dial and reports the minimum — and asserted against the
1256/// committed data by `codec_headline_is_provable`, so the page can never overclaim.
1257fn codec_size_wins(d: &CodecData) -> (usize, usize) {
1258    let fair: Vec<&CodecScenario> = d.scenarios.iter().filter(|s| s.kind == "fair").collect();
1259    let wins = fair
1260        .iter()
1261        .filter(|s| match s.rows.iter().find(|r| r.codec == "logos (BEST: all knobs)") {
1262            Some(best) => s.rows.iter().filter(|r| !is_logos_codec(&r.codec)).all(|r| best.size <= r.size),
1263            None => false,
1264        })
1265        .count();
1266    (wins, fair.len())
1267}
1268
1269/// (smallest LOGOS bytes, smallest-competitor label, its bytes) for a scenario — the data
1270/// behind each "N× smaller than the best of the rest" caption.
1271fn codec_best_vs_competitor(s: &CodecScenario) -> Option<(usize, String, usize)> {
1272    let ours = s.rows.iter().filter(|r| is_logos_codec(&r.codec)).map(|r| r.size).min()?;
1273    let rival = s.rows.iter().filter(|r| !is_logos_codec(&r.codec)).min_by_key(|r| r.size)?;
1274    Some((ours, codec_label(&rival.codec).to_string(), rival.size))
1275}
1276
1277/// (fastest LOGOS read-one ns, Cap'n Proto's read-one ns) for the random-access scenario.
1278fn codec_random_access_vs_capnp(s: &CodecScenario) -> Option<(f64, f64)> {
1279    let ours = s
1280        .rows
1281        .iter()
1282        .filter(|r| is_logos_codec(&r.codec))
1283        .filter_map(|r| r.read_one_ns)
1284        .fold(f64::INFINITY, f64::min);
1285    let capnp = s.rows.iter().find(|r| r.codec == "capnproto").and_then(|r| r.read_one_ns)?;
1286    if ours.is_finite() {
1287        Some((ours, capnp))
1288    } else {
1289        None
1290    }
1291}
1292
1293/// The size caption for a scenario ("LOGOS …B vs best of the rest (…) …B — N× smaller").
1294fn codec_size_caption(s: &CodecScenario) -> Option<String> {
1295    codec_best_vs_competitor(s).map(|(ours, rival, rsize)| {
1296        format!(
1297            "LOGOS {} vs best of the rest ({rival}) {} — {:.2}× smaller",
1298            format_bytes(ours as f64),
1299            format_bytes(rsize as f64),
1300            rsize as f64 / ours.max(1) as f64
1301        )
1302    })
1303}
1304
1305/// The random-access caption ("LOGOS …ns vs Cap'n Proto …ns — N× faster open + read").
1306fn codec_ra_caption(s: &CodecScenario) -> Option<String> {
1307    codec_random_access_vs_capnp(s).map(|(ours, capnp)| {
1308        format!(
1309            "LOGOS {} vs Cap'n Proto {} — {:.2}× faster open + read",
1310            format_ns(ours),
1311            format_ns(capnp),
1312            capnp / ours.max(1.0)
1313        )
1314    })
1315}
1316
1317/// (#fair workloads where the fastest LOGOS dial is ≤ every competitor on `axis`, total fair) —
1318/// the scorecard's "fastest encode / decode on N/N" stats, computed from the baked data.
1319fn codec_axis_wins(d: &CodecData, axis: CodecAxis) -> (usize, usize) {
1320    let v = |r: &CodecRow| -> Option<f64> {
1321        match axis {
1322            CodecAxis::Size => Some(r.size as f64),
1323            CodecAxis::Encode => Some(r.enc_ns),
1324            CodecAxis::Decode => Some(r.dec_ns),
1325            CodecAxis::ReadOne => r.read_one_ns,
1326        }
1327    };
1328    let fair: Vec<&CodecScenario> = d.scenarios.iter().filter(|s| s.kind == "fair").collect();
1329    let wins = fair
1330        .iter()
1331        .filter(|s| {
1332            let lo = s.rows.iter().filter(|r| is_logos_codec(&r.codec)).filter_map(&v).fold(f64::INFINITY, f64::min);
1333            let co = s.rows.iter().filter(|r| !is_logos_codec(&r.codec)).filter_map(&v).fold(f64::INFINITY, f64::min);
1334            lo.is_finite() && co.is_finite() && lo <= co
1335        })
1336        .count();
1337    (wins, fair.len())
1338}
1339
1340/// The biggest structural showcase win (best competitor ÷ smallest LOGOS, by size).
1341fn codec_top_showcase(d: &CodecData) -> Option<f64> {
1342    d.scenarios
1343        .iter()
1344        .filter(|s| s.kind == "showcase")
1345        .filter_map(|s| codec_best_vs_competitor(s).map(|(ours, _, rival)| rival as f64 / ours.max(1) as f64))
1346        .fold(None, |acc, r| Some(acc.map_or(r, |m: f64| m.max(r))))
1347}
1348
1349/// Geometric-mean size advantage over the best competitor across the fair workloads (×).
1350fn codec_geomean_size(d: &CodecData) -> f64 {
1351    let ratios: Vec<f64> = d
1352        .scenarios
1353        .iter()
1354        .filter(|s| s.kind == "fair")
1355        .filter_map(|s| codec_best_vs_competitor(s).map(|(ours, _, rival)| rival as f64 / ours.max(1) as f64))
1356        .collect();
1357    if ratios.is_empty() {
1358        return 1.0;
1359    }
1360    (ratios.iter().map(|r| r.ln()).sum::<f64>() / ratios.len() as f64).exp()
1361}
1362
1363/// The all-knobs winner row for a scenario (the size-optimal config, whose `chosen` names the
1364/// dials that won). `None` for a scenario that has no all-knobs row (e.g. random-access).
1365fn codec_best_row(s: &CodecScenario) -> Option<&CodecRow> {
1366    s.rows.iter().find(|r| r.codec == "logos (BEST: all knobs)")
1367}
1368
1369/// A one-line, real-world "what this data shape is for" — so every example reads as a use case,
1370/// not just a bar chart. Covers every scenario id the harness emits (asserted by a test), so a
1371/// new scenario can't ship without its copy.
1372fn codec_good_for(id: &str) -> Option<&'static str> {
1373    Some(match id {
1374        "ints" => "ID columns, counters, quantities, foreign keys",
1375        "floats" => "measurements, prices, scientific readings",
1376        "timeseries" => "sensor / financial streams that vary slowly — xor-delta shines",
1377        "points" => "coordinates, vectors, spatial data",
1378        "records" => "row / struct lists — API payloads, database rows, events",
1379        "strings" => "text-heavy payloads — names, labels, log lines",
1380        "bools" => "flag columns, feature toggles, bitsets",
1381        "adv_negative" => "signed data that trips formats without zig-zag",
1382        "adv_repetitive" => "columns with long runs — status codes, repeated defaults",
1383        "adv_huge" => "wide 64-bit values — hashes, ids, nanosecond timestamps",
1384        "random_access" => "reading ONE field of a big message without decoding the rest",
1385        "affine_showcase" => "arithmetic progressions — row ids, ramps, fixed offsets",
1386        "poly_showcase" => "polynomial columns — accumulators, quadratic ramps",
1387        "categorical" => "low-cardinality labels — enums, tags, country codes",
1388        "int_set" => "membership sets — id sets, allow-lists",
1389        "int_map" => "int-keyed maps — lookup tables, adjacency lists",
1390        _ => return None,
1391    })
1392}
1393
1394/// The other end of the size↔speed dial: the fastest-to-decode LOGOS dial that ISN'T the size
1395/// winner, when it decodes meaningfully faster (a real speed-for-size trade). This is what the
1396/// card surfaces as "prioritize speed?", answering "if I don't take the smallest, what do I get?".
1397fn codec_speed_pick(s: &CodecScenario) -> Option<(String, usize, f64)> {
1398    let best = codec_best_row(s)?;
1399    let pick = s
1400        .rows
1401        .iter()
1402        .filter(|r| is_logos_codec(&r.codec) && r.codec != "logos (BEST: all knobs)" && r.dec_ns > 0.0)
1403        .min_by(|a, b| a.dec_ns.partial_cmp(&b.dec_ns).unwrap_or(std::cmp::Ordering::Equal))?;
1404    (pick.dec_ns < best.dec_ns * 0.9).then(|| (codec_label(&pick.codec).to_string(), pick.size, pick.dec_ns))
1405}
1406
1407/// The FAIR-FIGHT size comparison for a scenario: (LOGOS best-compressed size, best competitor's
1408/// fair-compressed size, its label). LOGOS bakes compression into the codec; here every competitor
1409/// is granted the SAME compression, so this is an honest compressed-vs-compressed comparison — not
1410/// LOGOS-compressed-vs-competitor-raw. `None` if no all-knobs winner or no competitor `fair_size`.
1411fn codec_fair_fight(s: &CodecScenario) -> Option<(usize, usize, String)> {
1412    let logos = codec_best_row(s)?.size; // the BEST row already shops compression
1413    let rival = s
1414        .rows
1415        .iter()
1416        .filter(|r| !is_logos_codec(&r.codec))
1417        .filter_map(|r| r.fair_size.map(|f| (f, r.codec.clone())))
1418        .min_by_key(|(f, _)| *f)?;
1419    Some((logos, rival.0, codec_label(&rival.1).to_string()))
1420}
1421
1422/// (#fair workloads where LOGOS is no larger than every competitor IN THE FAIR FIGHT, total fair) —
1423/// the honest "even when everyone compresses" size count for the scorecard.
1424fn codec_fair_size_wins(d: &CodecData) -> (usize, usize) {
1425    let fair: Vec<&CodecScenario> = d.scenarios.iter().filter(|s| s.kind == "fair").collect();
1426    let wins = fair.iter().filter(|s| matches!(codec_fair_fight(s), Some((lo, co, _)) if lo <= co)).count();
1427    (wins, fair.len())
1428}
1429
1430/// The winner card shown above each example's bar charts: what config won, its size AND encode
1431/// AND decode together (the trio the three separate charts never connect), what the shape is good
1432/// for, and the speed-pick alternative. `rsx!{}` (nothing) for a scenario with no all-knobs winner.
1433fn codec_winner_card(s: &CodecScenario) -> Element {
1434    let Some(best) = codec_best_row(s) else { return rsx! {} };
1435    let Some(chosen) = best.chosen.as_ref() else { return rsx! {} };
1436    let headline = match codec_best_vs_competitor(s) {
1437        Some((ours, rival, rsize)) => format!(
1438            "\u{2714} LOGOS ships {} \u{2014} {:.2}\u{00d7} smaller than {}",
1439            format_bytes(ours as f64),
1440            rsize as f64 / ours.max(1) as f64,
1441            rival
1442        ),
1443        None => format!("\u{2714} LOGOS ships {}", format_bytes(best.size as f64)),
1444    };
1445    let config_line = format!("won with: {}", chosen.summary);
1446    let speed_line = format!("encode {} \u{00b7} decode {}", format_ns(best.enc_ns), format_ns(best.dec_ns));
1447    let good = codec_good_for(&s.id);
1448    // The honest compressed-vs-compressed line: when the headline win used compression, this shows
1449    // whether LOGOS still wins (or ties) once every rival is given the same compression.
1450    let fair = codec_fair_fight(s).map(|(lo, co, rlabel)| {
1451        let verdict = if lo < co { "still smaller" } else if lo == co { "tie" } else { "rival smaller" };
1452        format!(
1453            "Fair fight (all compressed): LOGOS {} vs {} {} \u{2014} {}",
1454            format_bytes(lo as f64),
1455            rlabel,
1456            format_bytes(co as f64),
1457            verdict
1458        )
1459    });
1460    let speed_pick = codec_speed_pick(s).map(|(label, size, dec)| {
1461        format!("Prioritize speed? {} \u{2014} {} \u{00b7} decode {}", label, format_bytes(size as f64), format_ns(dec))
1462    });
1463    rsx! {
1464        div {
1465            style: "background: linear-gradient(135deg, rgba(34,211,238,0.10), rgba(167,139,250,0.08)); border: 1px solid rgba(34,211,238,0.28); border-radius: 12px; padding: 12px 14px; margin: 6px 0 12px;",
1466            div { style: "font-size: 13px; font-weight: 700; color: #67e8f9;", "{headline}" }
1467            div { style: "font-size: 12px; color: rgba(229,231,235,0.85); margin-top: 4px;", "{config_line}" }
1468            div { style: "font-size: 12px; color: rgba(229,231,235,0.6); margin-top: 2px;", "{speed_line}" }
1469            if let Some(g) = good {
1470                div { style: "font-size: 12px; color: rgba(167,139,250,0.9); margin-top: 4px;", "Good for: {g}" }
1471            }
1472            if let Some(f) = fair {
1473                div { style: "font-size: 11px; color: rgba(229,231,235,0.55); margin-top: 4px;", "{f}" }
1474            }
1475            if let Some(sp) = speed_pick {
1476                div { style: "font-size: 11px; color: rgba(229,231,235,0.5); margin-top: 5px; border-top: 1px solid rgba(255,255,255,0.06); padding-top: 5px;", "{sp}" }
1477            }
1478        }
1479    }
1480}
1481
1482/// The dial glossary: every knob the codec exposes, in plain words, with what it's *for* — so the
1483/// section reads as a menu of trade-offs, not an unexplained pile of bars. The top group is the
1484/// dials these benchmarks actually exercise; the second is the rest of the codec's capability
1485/// surface, so the reader sees the whole instrument. Copy tracks the marshal.rs doc comments.
1486fn codec_dial_glossary() -> Element {
1487    let benched: &[(&str, &str)] = &[
1488        ("varint", "LEB128 — smallest bytes; the default for a bandwidth-bound network link"),
1489        ("fixed (memcpy)", "raw 8-byte i64 — fastest decode on a datacenter / RDMA link, ~4\u{00d7} the size"),
1490        ("group-varint", "varint-class size, SIMD-decoded several ints at once — small AND fast"),
1491        ("auto structure", "per-column bake-off (delta \u{00b7} delta-of-delta \u{00b7} FOR bit-pack \u{00b7} run-length \u{00b7} dictionary \u{00b7} affine \u{00b7} polynomial) — ships the smallest, never larger than varint"),
1492        ("xor-delta floats", "Gorilla-style — slowly-varying float streams shrink; high-entropy data falls back to memcpy"),
1493        ("struct-view", "an offset table per field so any ONE field reads in O(1) — Cap'n Proto's game; larger on the wire"),
1494        ("compression", "deflate / lz4 / zstd over the whole frame, kept only when smaller — for bulky or redundant payloads"),
1495    ];
1496    let also: &[(&str, &str)] = &[
1497        ("checksum", "an FNV tag so the receiver rejects a corrupted frame (Raw \u{2194} Checked)"),
1498        ("type-id", "elide struct / enum names on a Logos\u{2194}Logos link once both peers know the schema"),
1499        ("FEC", "Reed-Solomon shards — reconstruct the message from any K of N (lossy links, multicast)"),
1500        ("dedup", "a subtree reached by the same reference ships once + backrefs; the decoder rebuilds the sharing"),
1501    ];
1502    let item = |name: &'static str, desc: &'static str| {
1503        rsx! {
1504            div { style: "margin: 3px 0;",
1505                span { style: "color: #67e8f9; font-weight: 600;", "{name}" }
1506                span { style: "color: rgba(229,231,235,0.6);", " \u{2014} {desc}" }
1507            }
1508        }
1509    };
1510    rsx! {
1511        div {
1512            style: "background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; padding: 14px 16px; margin: 6px 0 18px; font-size: 12px; line-height: 1.5;",
1513            div { style: "font-size: 13px; font-weight: 700; color: #fff; margin-bottom: 4px;", "The dials \u{2014} every form is self-describing, so the decoder needs no hint" }
1514            div { style: "color: rgba(229,231,235,0.5); margin-bottom: 6px;", "In these benchmarks:" }
1515            for (name, desc) in benched.iter().copied() { {item(name, desc)} }
1516            div { style: "color: rgba(229,231,235,0.5); margin: 10px 0 6px;", "Also available (not exercised by the charts below):" }
1517            for (name, desc) in also.iter().copied() { {item(name, desc)} }
1518        }
1519    }
1520}
1521
1522/// The "Serialization — the wire codec" section: the LOGOS wire codec head-to-head against
1523/// the industry serializers across wire size, encode, decode and single-field random access.
1524/// Every figure is measured by the wirebench harness on the same logical data; the headline
1525/// ("smallest wire on N/N workloads") is provable, and the structured/affine showcase is
1526/// fenced off from the fair results so the math-hack is never conflated with general data.
1527#[component]
1528pub fn CodecSection() -> Element {
1529    let d = codec_data().expect("rendered only inside the loaded Benchmarks page");
1530    let (wins, total) = codec_size_wins(d);
1531    let fair: Vec<&CodecScenario> = d.scenarios.iter().filter(|s| s.kind == "fair").collect();
1532    let adversarial: Vec<&CodecScenario> = d.scenarios.iter().filter(|s| s.kind == "adversarial").collect();
1533    let random: Vec<&CodecScenario> = d.scenarios.iter().filter(|s| s.kind == "random_access").collect();
1534    let structural: Vec<&CodecScenario> = d.scenarios.iter().filter(|s| s.kind == "structural").collect();
1535    let showcase: Vec<&CodecScenario> = d.scenarios.iter().filter(|s| s.kind == "showcase").collect();
1536
1537    let mut comp_names = vec!["bincode", "postcard", "MessagePack", "CBOR", "JSON"];
1538    if d.metadata.features.iter().any(|f| f == "arrow-bench") {
1539        comp_names.push("Apache Arrow");
1540    }
1541    if d.metadata.features.iter().any(|f| f == "protobuf") {
1542        comp_names.push("Protobuf/gRPC");
1543    }
1544    if d.metadata.features.iter().any(|f| f == "capnproto") {
1545        comp_names.push("Cap'n Proto");
1546    }
1547    let comp_list = comp_names.join(", ");
1548
1549    let hint = "font-size: 12px; color: rgba(229,231,235,0.55); margin: 10px 0 4px;";
1550    let title = "font-size: 15px; font-weight: 700; color: #fff;";
1551    let cap = "font-size: 12px; color: rgba(34,211,238,0.85); margin: 2px 0 6px;";
1552
1553    rsx! {
1554        div { class: "bench-section", id: "serialization",
1555            div { class: "bench-section-title", "Serialization \u{2014} the wire codec" }
1556            div { class: "bench-section-desc",
1557                "Speed of code is one axis; bytes on the wire are another. The LOGOS wire codec is benched head-to-head against {comp_list} \u{2014} the same logical data through every codec, on the same machine, with seeded-random payloads (never a tidy 0..n sequence that would hand a structural codec a free win). LOGOS wins encode AND decode on every fair workload and is competitive-to-smaller on size; the honest details are on each card."
1558            }
1559
1560            // ---- Dial glossary: what each knob does and what it's for ----
1561            { codec_dial_glossary() }
1562
1563            // ---- Scorecard: the whole head-to-head at a glance, computed from the baked data ----
1564            {
1565                let (enc_wins, _) = codec_axis_wins(d, CodecAxis::Encode);
1566                let (dec_wins, _) = codec_axis_wins(d, CodecAxis::Decode);
1567                let (fair_wins, fair_total) = codec_fair_size_wins(d);
1568                let geo = format!("{:.1}\u{00d7}", codec_geomean_size(d));
1569                let ra = random.first().and_then(|s| codec_random_access_vs_capnp(s));
1570                let ra_str = ra.map(|(o, c)| format!("{:.1}\u{00d7}", c / o.max(1.0)));
1571                let top_str = codec_top_showcase(d).map(|r| format!("{:.0}\u{00d7}", r));
1572                rsx! {
1573                    div { class: "bench-summary",
1574                        div { class: "bench-summary-card",
1575                            div { class: "bench-summary-value green", "{enc_wins}/{total}" }
1576                            div { class: "bench-summary-label", "fastest encode (fair workloads)" }
1577                        }
1578                        div { class: "bench-summary-card",
1579                            div { class: "bench-summary-value green", "{dec_wins}/{total}" }
1580                            div { class: "bench-summary-label", "fastest decode (fair workloads)" }
1581                        }
1582                        div { class: "bench-summary-card",
1583                            div { class: "bench-summary-value cyan", "{wins}/{total}" }
1584                            div { class: "bench-summary-label", "smallest out-of-the-box (we auto-compress; rivals raw)" }
1585                        }
1586                        div { class: "bench-summary-card",
1587                            div { class: "bench-summary-value cyan", "{fair_wins}/{fair_total}" }
1588                            div { class: "bench-summary-label", "smallest in a fair fight (everyone compressed)" }
1589                        }
1590                        if let Some(ra_str) = ra_str {
1591                            div { class: "bench-summary-card",
1592                                div { class: "bench-summary-value cyan", "{ra_str}" }
1593                                div { class: "bench-summary-label", "faster random-access read vs Cap'n Proto" }
1594                            }
1595                        }
1596                        if let Some(top_str) = top_str {
1597                            div { class: "bench-summary-card",
1598                                div { class: "bench-summary-value purple", "up to {top_str}" }
1599                                div { class: "bench-summary-label", "structural showcases (smaller)" }
1600                            }
1601                        }
1602                        div { class: "bench-summary-card",
1603                            div { class: "bench-summary-value cyan", "{geo}" }
1604                            div { class: "bench-summary-label", "geo-mean smaller, out of the box" }
1605                        }
1606                    }
1607                    div {
1608                        style: "background: linear-gradient(135deg, rgba(34,211,238,0.10), rgba(167,139,250,0.10)); border: 1px solid rgba(34,211,238,0.25); border-radius: 12px; padding: 16px 18px; margin: 4px 0 20px;",
1609                        div { style: "font-size: 13px; color: rgba(229,231,235,0.7); line-height: 1.5;",
1610                            "Every figure is measured on the same logical data, same machine, seeded-random. LOGOS wins encode AND decode on every fair workload \u{2014} the default dial is a pure memcpy that never searches at send time (you pick the shape ahead of time), so it beats even bincode's raw copy; decode is faster because the format is columnar and typed. On SIZE we\u{2019}re honest two ways: \u{201c}out of the box\u{201d} LOGOS auto-compresses and rivals ship raw (a real transport advantage), and the \u{201c}fair fight\u{201d} gives every rival the SAME compression \u{2014} there LOGOS wins on structured data and ties on random primitive arrays (a memcpy is a memcpy). The all-knobs winner\u{2019}s exact dials, and both size comparisons, are on each card. Decode is timed \u{201c}to usable\u{201d} (every value touched). The contrived generator showcases (a pure 0,1,2\u{2026} ramp) are fenced off from the fair results."
1611                        }
1612                    }
1613                }
1614            }
1615
1616            // ---- Fair workloads: size / encode / decode ----
1617            for s in fair.iter() {
1618                div { style: "margin-bottom: 26px;",
1619                    div { style: "{title}", "{s.title}  \u{00b7}  n = {s.n}" }
1620                    { codec_winner_card(s) }
1621                    if let Some(c) = codec_size_caption(s) {
1622                        div { style: "{cap}", "{c}" }
1623                    }
1624                    div { style: "{hint}", "Wire size \u{2014} smaller is better, bars proportional" }
1625                    { codec_axis_chart(s, CodecAxis::Size) }
1626                    div { style: "{hint}", "Encode (ns/op) \u{2014} smaller is better, bars proportional" }
1627                    { codec_axis_chart(s, CodecAxis::Encode) }
1628                    div { style: "{hint}", "Decode to usable (ns/op) \u{2014} smaller is better, bars proportional" }
1629                    { codec_axis_chart(s, CodecAxis::Decode) }
1630                }
1631            }
1632
1633            // ---- Random access: Cap'n Proto's home turf ----
1634            for s in random.iter() {
1635                div { style: "margin-bottom: 26px;",
1636                    div { style: "{title}", "{s.title}  \u{00b7}  n = {s.n}" }
1637                    div { style: "font-size: 12px; color: rgba(229,231,235,0.6); margin: 4px 0 6px; line-height: 1.5;",
1638                        "A message arrives; you open it and read ONE field. This is exactly what Cap'n Proto is built for. LOGOS opens its record-list view (row + field offset tables) in O(1); the self-describing codecs must decode the whole message to index it."
1639                    }
1640                    if let Some(c) = codec_ra_caption(s) {
1641                        div { style: "{cap}", "{c}" }
1642                    }
1643                    div { style: "{hint}", "Open + read one field (ns/op) \u{2014} smaller is better, bars proportional" }
1644                    { codec_axis_chart(s, CodecAxis::ReadOne) }
1645                }
1646            }
1647
1648            // ---- Adversarial shapes ----
1649            if !adversarial.is_empty() {
1650                div { style: "font-size: 15px; font-weight: 700; color: #fff; margin-top: 28px;", "Adversarial shapes" }
1651                div { style: "font-size: 12px; color: rgba(229,231,235,0.55); margin: 4px 0 12px; line-height: 1.5;",
1652                    "The data shapes that wreck fixed-format codecs \u{2014} all dials on."
1653                }
1654                for s in adversarial.iter() {
1655                    div { style: "margin-bottom: 20px;",
1656                        div { style: "{title}", "{s.title}  \u{00b7}  n = {s.n}" }
1657                        { codec_winner_card(s) }
1658                        if let Some(c) = codec_size_caption(s) {
1659                            div { style: "{cap}", "{c}" }
1660                        }
1661                        div { style: "{hint}", "Wire size \u{2014} smaller is better, bars proportional" }
1662                        { codec_axis_chart(s, CodecAxis::Size) }
1663                    }
1664                }
1665            }
1666
1667            // ---- Structural wins on REAL data: general columnar techniques, not contrived ----
1668            if !structural.is_empty() {
1669                div { style: "font-size: 15px; font-weight: 700; color: #fff; margin-top: 28px;", "Structural wins on real data" }
1670                div { style: "font-size: 12px; color: rgba(229,231,235,0.6); margin: 4px 0 12px; line-height: 1.5;",
1671                    "Not math tricks \u{2014} the standard columnar techniques (dictionary encoding for low-cardinality labels, bit-packing for booleans) that Parquet and Arrow are built on, applied automatically. Common shapes in real payloads, and LOGOS ships them by default when they win."
1672                }
1673                for s in structural.iter() {
1674                    div { style: "margin-bottom: 22px;",
1675                        div { style: "{title}", "{s.title}  \u{00b7}  n = {s.n}" }
1676                        { codec_winner_card(s) }
1677                        if let Some(c) = codec_size_caption(s) {
1678                            div { style: "{cap}", "{c}" }
1679                        }
1680                        div { style: "{hint}", "Wire size \u{2014} smaller is better, bars proportional" }
1681                        { codec_axis_chart(s, CodecAxis::Size) }
1682                    }
1683                }
1684            }
1685
1686            // ---- Showcases, explicitly fenced off from the fair results ----
1687            if !showcase.is_empty() {
1688                div {
1689                    style: "background: linear-gradient(135deg, rgba(167,139,250,0.10), rgba(34,211,238,0.06)); border: 1px solid rgba(167,139,250,0.25); border-radius: 12px; padding: 14px 16px; margin: 18px 0 12px;",
1690                    div { style: "font-size: 13px; color: rgba(229,231,235,0.8); line-height: 1.5;",
1691                        "\u{26a1} Showcases, kept separate from the fair results: contrived columns where the codec ships the GENERATING RULE instead of the data \u{2014} an affine progression as (base, stride, n), a polynomial as its finite-difference seeds, a consecutive set as base+stride+count \u{2014} winning by orders of magnitude. Not general-data results; they show the ceiling when structure is perfect."
1692                    }
1693                }
1694                for s in showcase.iter() {
1695                    div { style: "margin-bottom: 22px;",
1696                        div { style: "{title}", "{s.title}  \u{00b7}  n = {s.n}" }
1697                        { codec_winner_card(s) }
1698                        if let Some(c) = codec_size_caption(s) {
1699                            div { style: "{cap}", "{c}" }
1700                        }
1701                        div { style: "{hint}", "Wire size \u{2014} smaller is better, bars proportional" }
1702                        { codec_axis_chart(s, CodecAxis::Size) }
1703                    }
1704                }
1705            }
1706
1707            div { style: "font-size: 11px; color: rgba(229,231,235,0.4); line-height: 1.5; border-top: 1px solid rgba(255,255,255,0.08); padding-top: 12px;",
1708                "Method: each value space (int/float arrays, point & record lists, strings) is encoded by every codec from the same seeded-random data; size is exact bytes (no envelope), encode/decode are ns per whole-message op, taken with a warm-up. Cap'n Proto is read zero-copy (its best). Bars are linear within each chart — every length is its exact fraction of the slowest, so the gap you see is the true ratio. Measured on {d.metadata.cpu}, {d.metadata.os}."
1709            }
1710        }
1711    }
1712}
1713
1714// The LOGOS interpreter (bytecode VM + JIT) vs Node/V8 — a separate peer-to-peer
1715// comparison at interpreter-calibrated sizes (so neither engine sits on V8's
1716// startup floor). Produced by benchmarks/run-interp-vs-js.sh.
1717#[derive(Deserialize)]
1718struct InterpData {
1719    #[serde(default)]
1720    metadata: InterpMetadata,
1721    #[serde(default)]
1722    benchmarks: Vec<InterpBenchmark>,
1723    #[serde(default)]
1724    summary: InterpSummary,
1725    #[serde(default)]
1726    startup: InterpStartup,
1727    /// Engine footprint (bytes): the largo VM+JIT binary vs the host language runtimes,
1728    /// plus the browser WASM bundle. Absent in older result files.
1729    #[serde(default)]
1730    interpreter_sizes: Option<InterpreterSizes>,
1731}
1732
1733#[derive(Deserialize, Clone)]
1734struct InterpreterSizes {
1735    #[allow(dead_code)]
1736    method: String,
1737    /// engine id (logos, node, python, ruby, …) → on-disk size in bytes.
1738    engines: HashMap<String, BinSizes>,
1739    /// Largest `.wasm` in the release web bundle — the in-browser interpreter footprint.
1740    /// `null` when no `dx` release build was present at measurement time.
1741    #[serde(default)]
1742    wasm_bundle_bytes: Option<f64>,
1743}
1744
1745#[derive(Deserialize, Default)]
1746struct InterpStartup {
1747    #[serde(default)]
1748    runs: u32,
1749    #[serde(default)]
1750    engines: HashMap<String, StartupTiming>,
1751}
1752
1753#[derive(Deserialize, Default, Clone)]
1754struct StartupTiming {
1755    #[serde(default)]
1756    mean_ms: f64,
1757    #[serde(default)]
1758    min_ms: f64,
1759    #[serde(default)]
1760    median_ms: f64,
1761}
1762
1763#[derive(Deserialize, Default)]
1764struct InterpMetadata {
1765    #[serde(default)]
1766    node: String,
1767    #[serde(default)]
1768    date: String,
1769}
1770
1771#[derive(Deserialize, Default)]
1772struct InterpSummary {
1773    #[serde(default)]
1774    geometric_mean_logos_interp_over_node: f64,
1775    /// The TIERED engine's geomean (HOTSWAP §12) — the A/B counterpart to the eager
1776    /// `_interp_` figure. `#[serde(default)]` so the pre-tiered JSON still loads.
1777    #[serde(default)]
1778    geometric_mean_logos_tiered_over_node: f64,
1779    /// The AOT-NATIVE tier's geomean (HOTSWAP §Axis-3) — present only when a native
1780    /// bundle was built for the run. `#[serde(default)]` so non-bundled JSON still loads.
1781    #[serde(default)]
1782    geometric_mean_logos_aot_over_node: f64,
1783}
1784
1785#[derive(Deserialize)]
1786struct InterpBenchmark {
1787    id: String,
1788    name: String,
1789    #[serde(default)]
1790    reference_size: String,
1791    #[serde(default)]
1792    interpreter_engine: String,
1793    #[serde(default)]
1794    scaling: HashMap<String, HashMap<String, TimingResult>>,
1795}
1796
1797#[cfg(not(target_arch = "wasm32"))]
1798static INTERP_DATA: LazyLock<InterpData> = LazyLock::new(|| {
1799    serde_json::from_str(include_str!("../../../../../benchmarks/results/latest-interp.json")).unwrap()
1800});
1801#[cfg(target_arch = "wasm32")]
1802static INTERP_DATA: OnceLock<InterpData> = OnceLock::new();
1803
1804/// The interpreter-tier feed — same gating contract as [`bench_data`].
1805fn interp_data() -> Option<&'static InterpData> {
1806    #[cfg(not(target_arch = "wasm32"))]
1807    {
1808        Some(&INTERP_DATA)
1809    }
1810    #[cfg(target_arch = "wasm32")]
1811    {
1812        INTERP_DATA.get()
1813    }
1814}
1815
1816struct BenchSources {
1817    c: &'static str,
1818    cpp: &'static str,
1819    rust: &'static str,
1820    zig: &'static str,
1821    go: &'static str,
1822    java: &'static str,
1823    js: &'static str,
1824    python: &'static str,
1825    ruby: &'static str,
1826    nim: &'static str,
1827    logos: &'static str,
1828}
1829
1830#[cfg(not(target_arch = "wasm32"))]
1831macro_rules! bench_sources {
1832    ($name:literal) => {
1833        ($name, BenchSources {
1834            c: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.c")),
1835            cpp: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.cpp")),
1836            rust: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.rs")),
1837            zig: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.zig")),
1838            go: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.go")),
1839            java: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/Main.java")),
1840            js: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.js")),
1841            python: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.py")),
1842            ruby: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.rb")),
1843            nim: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.nim")),
1844            logos: include_str!(concat!("../../../../../benchmarks/programs/", $name, "/main.lg")),
1845        })
1846    };
1847}
1848
1849#[cfg(not(target_arch = "wasm32"))]
1850static SOURCES: LazyLock<[(&'static str, BenchSources); 32]> = LazyLock::new(|| [
1851    // Recursion & Function Calls
1852    bench_sources!("fib"),
1853    bench_sources!("ackermann"),
1854    bench_sources!("nqueens"),
1855    // Sorting
1856    bench_sources!("bubble_sort"),
1857    bench_sources!("mergesort"),
1858    bench_sources!("quicksort"),
1859    bench_sources!("counting_sort"),
1860    bench_sources!("heap_sort"),
1861    // Floating Point
1862    bench_sources!("nbody"),
1863    bench_sources!("mandelbrot"),
1864    bench_sources!("spectral_norm"),
1865    bench_sources!("pi_leibniz"),
1866    // Integer Mathematics
1867    bench_sources!("gcd"),
1868    bench_sources!("collatz"),
1869    bench_sources!("primes"),
1870    // Array Patterns
1871    bench_sources!("sieve"),
1872    bench_sources!("matrix_mult"),
1873    bench_sources!("prefix_sum"),
1874    bench_sources!("array_reverse"),
1875    bench_sources!("array_fill"),
1876    // Hash Maps & Lookup
1877    bench_sources!("collect"),
1878    bench_sources!("two_sum"),
1879    bench_sources!("histogram"),
1880    // Dynamic Programming
1881    bench_sources!("knapsack"),
1882    bench_sources!("coins"),
1883    // Combinatorial
1884    bench_sources!("fannkuch"),
1885    // Memory & Allocation
1886    bench_sources!("strings"),
1887    bench_sources!("binary_trees"),
1888    // Loop Overhead & Control Flow
1889    bench_sources!("loop_sum"),
1890    bench_sources!("fib_iterative"),
1891    bench_sources!("graph_bfs"),
1892    bench_sources!("string_search"),
1893]);
1894#[cfg(target_arch = "wasm32")]
1895static SOURCES: OnceLock<HashMap<String, BenchSources>> = OnceLock::new();
1896
1897/// The 11-language sources for one benchmark, looked up by its `latest.json` id —
1898/// same gating contract as [`bench_data`].
1899fn bench_sources_for(id: &str) -> Option<&'static BenchSources> {
1900    #[cfg(not(target_arch = "wasm32"))]
1901    {
1902        SOURCES.iter().find(|(name, _)| *name == id).map(|(_, s)| s)
1903    }
1904    #[cfg(target_arch = "wasm32")]
1905    {
1906        SOURCES.get()?.get(id)
1907    }
1908}
1909
1910/// Owned mirror of [`BenchSources`] for deserializing the staged `bench-sources.json`;
1911/// pinned via `Box::leak` so the page keeps its `&'static str` shape on both targets.
1912#[cfg(target_arch = "wasm32")]
1913#[derive(Deserialize)]
1914struct BenchSourcesOwned {
1915    c: String,
1916    cpp: String,
1917    rust: String,
1918    zig: String,
1919    go: String,
1920    java: String,
1921    js: String,
1922    python: String,
1923    ruby: String,
1924    nim: String,
1925    logos: String,
1926}
1927
1928#[cfg(target_arch = "wasm32")]
1929impl BenchSourcesOwned {
1930    fn pin(self) -> BenchSources {
1931        fn pin(s: String) -> &'static str {
1932            Box::leak(s.into_boxed_str())
1933        }
1934        BenchSources {
1935            c: pin(self.c),
1936            cpp: pin(self.cpp),
1937            rust: pin(self.rust),
1938            zig: pin(self.zig),
1939            go: pin(self.go),
1940            java: pin(self.java),
1941            js: pin(self.js),
1942            python: pin(self.python),
1943            ruby: pin(self.ruby),
1944            nim: pin(self.nim),
1945            logos: pin(self.logos),
1946        }
1947    }
1948}
1949
1950/// Fetches the staged `/data` bundle once and pins it for the app's lifetime; repeat
1951/// visits to the page re-run the (now instant) loads and keep the first pinned value.
1952#[cfg(target_arch = "wasm32")]
1953async fn load_bench_bundle() -> Result<(), String> {
1954    use crate::ui::data_fetch::fetch_static_json;
1955    let bench: BenchmarkData = fetch_static_json("/data/latest.json").await?;
1956    let solver: SolverData = fetch_static_json("/data/solvers.json").await?;
1957    let codec: CodecData = fetch_static_json("/data/latest-codec.json").await?;
1958    let interp: InterpData = fetch_static_json("/data/latest-interp.json").await?;
1959    let sources: HashMap<String, BenchSourcesOwned> =
1960        fetch_static_json("/data/bench-sources.json").await?;
1961    let _ = BENCH_DATA.set(bench);
1962    let _ = SOLVER_DATA.set(solver);
1963    let _ = CODEC_DATA.set(codec);
1964    let _ = INTERP_DATA.set(interp);
1965    let _ = SOURCES.set(sources.into_iter().map(|(id, s)| (id, s.pin())).collect());
1966    Ok(())
1967}
1968
1969const GITHUB_REPO: &str = "https://github.com/Brahmastra-Labs/logicaffeine";
1970
1971fn format_time(ms: f64) -> String {
1972    if ms >= 1000.0 {
1973        format!("{:.2}s", ms / 1000.0)
1974    } else if ms >= 1.0 {
1975        format!("{:.1}ms", ms)
1976    } else {
1977        format!("{:.0}\u{00b5}s", ms * 1000.0)
1978    }
1979}
1980
1981fn format_timeout(timeout_ms: f64) -> String {
1982    let mins = timeout_ms / 60_000.0;
1983    if mins >= 1.0 {
1984        format!(">{:.0}min", mins)
1985    } else {
1986        format!(">{:.0}s", timeout_ms / 1000.0)
1987    }
1988}
1989
1990fn tier_label(tier: &str) -> &'static str {
1991    match tier {
1992        "systems" => "Systems",
1993        "managed" => "Managed",
1994        "interpreted" => "Interpreted",
1995        "transpiled" => "Transpiled",
1996        _ => "Other",
1997    }
1998}
1999
2000fn lang_color(lang_id: &str) -> &'static str {
2001    match lang_id {
2002        "c" => "#555555",
2003        "cpp" => "#f34b7d",
2004        "rust" => "#dea584",
2005        "zig" => "#f7a41d",
2006        "logos_release" => "#00d4ff",
2007        "go" => "#3fb950",
2008        "java" => "#b07219",
2009        "js" => "#f7df1e",
2010        "logos_interp" => "#ff8c00",
2011        "logos_tiered" => "#ffb84d",
2012        "logos_aot" => "#00d4ff",
2013        "python" => "#3776ab",
2014        "ruby" => "#cc342d",
2015        "nim" => "#ffe953",
2016        _ => "#94a3b8",
2017    }
2018}
2019
2020fn lang_label(lang_id: &str) -> &'static str {
2021    match lang_id {
2022        "c" => "C",
2023        "cpp" => "C++",
2024        "rust" => "Rust",
2025        "zig" => "Zig",
2026        "logos_release" => "LOGOS",
2027        "go" => "Go",
2028        "java" => "Java",
2029        "js" => "JavaScript",
2030        "logos_interp" => "LOGOS (eager)",
2031        "logos_tiered" => "LOGOS (tiered)",
2032        "logos_aot" => "LOGOS (AOT-native)",
2033        "python" => "Python",
2034        "ruby" => "Ruby",
2035        "nim" => "Nim",
2036        _ => "Other",
2037    }
2038}
2039
2040fn lang_ext(lang_id: &str) -> &'static str {
2041    match lang_id {
2042        "c" => "main.c",
2043        "cpp" => "main.cpp",
2044        "rust" => "main.rs",
2045        "zig" => "main.zig",
2046        "go" => "main.go",
2047        "java" => "Main.java",
2048        "js" => "main.js",
2049        "python" => "main.py",
2050        "ruby" => "main.rb",
2051        "nim" => "main.nim",
2052        _ => "main",
2053    }
2054}
2055
2056fn compiler_label(key: &str) -> &'static str {
2057    match key {
2058        "gcc_-o3" => "gcc -O3 -march=native -flto",
2059        "g++_-o3" => "g++ -O3 -march=native -flto",
2060        "rustc_-o3" => "rustc -O3 -C lto=fat -C target-cpu=native",
2061        // legacy keys from older result files
2062        "gcc_-o2" => "gcc -O2",
2063        "g++_-o2" => "g++ -O2",
2064        "rustc_-o" => "rustc -O",
2065        "go_build" => "go build (release)",
2066        "javac" => "javac",
2067        "nim_c" => "nim c -d:release -march=native",
2068        "zig_build-exe" => "zig build-exe -O ReleaseFast -mcpu native",
2069        "largo_build" => "largo build (debug)",
2070        "largo_build_--release" => "largo build --release \u{2192} rustc -O3 -C lto=fat -C codegen-units=1 -C target-cpu=native",
2071        _ => "unknown",
2072    }
2073}
2074
2075fn get_source(sources: &BenchSources, lang_id: &str) -> &'static str {
2076    match lang_id {
2077        "c" => sources.c,
2078        "cpp" => sources.cpp,
2079        "rust" => sources.rust,
2080        "zig" => sources.zig,
2081        "go" => sources.go,
2082        "java" => sources.java,
2083        "js" => sources.js,
2084        "python" => sources.python,
2085        "ruby" => sources.ruby,
2086        "nim" => sources.nim,
2087        _ => "",
2088    }
2089}
2090
2091// Benchmarks where the LOGOS optimizer collapses the kernel — it does
2092// asymptotically less work than the naive algorithm the other languages run
2093// (tail-call / closed-form / loop folding), so the speedup reflects a compiler
2094// transform, not like-for-like codegen. These are excluded from the
2095// apples-to-apples geomean and carry a per-benchmark note. The set is curated
2096// from the measured results; the generated Rust shown on each benchmark makes
2097// every claim auditable.
2098fn collapse_note(id: &str) -> Option<&'static str> {
2099    match id {
2100        "fib" => Some("This one collapsed. The LOGOS optimizer folds the naive recursion to a closed form, so it does far less work than the runtime recursion the other languages execute — a compiler transform, not like-for-like codegen. See the generated Rust below."),
2101        "ackermann" => Some("This one collapsed. Deep recursion is folded by the optimizer instead of being executed call-by-call — a compiler transform, not like-for-like codegen. See the generated Rust below."),
2102        "binary_trees" => Some("This one collapsed. The allocate-and-checksum tree is reduced by the optimizer rather than built at runtime — a compiler transform, not like-for-like codegen. See the generated Rust below."),
2103        "loop_sum" => Some("This one collapsed. The accumulation loop is replaced with its closed-form sum (O(n) becomes O(1)) — a compiler transform, not like-for-like codegen. See the generated Rust below."),
2104        "collect" => Some("This one collapsed. The LOGOS optimizer folds the collection-building loop, doing far less work than inserting each element into a hash map at runtime — a compiler transform, not like-for-like codegen. See the generated Rust below."),
2105        _ => None,
2106    }
2107}
2108
2109// Timings at a benchmark's effective reference size (reference_size if it has
2110// data, else the largest benchmarked size).
2111fn effective_ref(b: &Benchmark) -> Option<&HashMap<String, TimingResult>> {
2112    if let Some(t) = b.scaling.get(b.reference_size.as_str()) {
2113        return Some(t);
2114    }
2115    b.sizes.iter().rev().find_map(|s| b.scaling.get(s))
2116}
2117
2118// LOGOS apples-to-apples geomean speedup vs C (C time / LOGOS time), over the
2119// benchmarks that did NOT collapse. Higher = faster.
2120fn logos_apples_geomean(data: &BenchmarkData) -> f64 {
2121    let mut log_sum = 0.0_f64;
2122    let mut n = 0u32;
2123    for b in &data.benchmarks {
2124        if collapse_note(&b.id).is_some() {
2125            continue;
2126        }
2127        if let Some(t) = effective_ref(b) {
2128            if let (Some(c), Some(l)) = (t.get("c"), t.get("logos_release")) {
2129                if c.mean_ms > 0.0 && l.mean_ms > 0.0 {
2130                    log_sum += (c.mean_ms / l.mean_ms).ln();
2131                    n += 1;
2132                }
2133            }
2134        }
2135    }
2136    if n > 0 { (log_sum / n as f64).exp() } else { 0.0 }
2137}
2138
2139// Node sits near its ~30ms V8 startup floor when its time is dominated by
2140// process startup rather than compute; such interpreter benchmarks are flagged
2141// and kept out of the headline so they don't flatter the interpreter.
2142fn node_floored(t: &TimingResult) -> bool {
2143    t.mean_ms < 60.0
2144}
2145
2146fn interp_ref<'a>(b: &'a InterpBenchmark) -> Option<&'a HashMap<String, TimingResult>> {
2147    b.scaling.get(b.reference_size.as_str()).or_else(|| b.scaling.values().next())
2148}
2149
2150// LOGOS interpreter speed vs V8 (Node time / interpreter time), geomean over
2151// interpreter benchmarks where Node was off its startup floor. Higher = faster.
2152fn interp_speed_vs_v8(data: &InterpData) -> f64 {
2153    let mut log_sum = 0.0_f64;
2154    let mut n = 0u32;
2155    for b in &data.benchmarks {
2156        if let Some(t) = interp_ref(b) {
2157            if let (Some(js), Some(lg)) = (t.get("js"), t.get("logos_interp")) {
2158                if js.mean_ms > 0.0 && lg.mean_ms > 0.0 && !node_floored(js) {
2159                    log_sum += (js.mean_ms / lg.mean_ms).ln();
2160                    n += 1;
2161                }
2162            }
2163        }
2164    }
2165    if n > 0 { (log_sum / n as f64).exp() } else { 0.0 }
2166}
2167
2168// LOGOS AOT-native (warm) speed vs V8 (Node time / AOT-native time), geomean over
2169// the benchmarks that carry a `logos_aot` row. Higher = faster. Returns 0 when no
2170// run has emitted the AOT-native tier yet, so the headline card stays hidden until
2171// a real AOT-native run regenerates the data.
2172fn aot_speed_vs_v8(data: &InterpData) -> f64 {
2173    let mut log_sum = 0.0_f64;
2174    let mut n = 0u32;
2175    for b in &data.benchmarks {
2176        if let Some(t) = interp_ref(b) {
2177            if let (Some(js), Some(lg)) = (t.get("js"), t.get("logos_aot")) {
2178                if js.mean_ms > 0.0 && lg.mean_ms > 0.0 && !node_floored(js) {
2179                    log_sum += (js.mean_ms / lg.mean_ms).ln();
2180                    n += 1;
2181                }
2182            }
2183        }
2184    }
2185    if n > 0 { (log_sum / n as f64).exp() } else { 0.0 }
2186}
2187
2188fn fmt_n(n: f64) -> String {
2189    if n >= 1.0e9 { format!("{:.0}B", n / 1.0e9) }
2190    else if n >= 1.0e6 { format!("{:.0}M", n / 1.0e6) }
2191    else if n >= 1.0e3 { format!("{:.0}k", n / 1.0e3) }
2192    else { format!("{:.0}", n) }
2193}
2194
2195// Per-benchmark scaling curve: wall-clock time vs problem size N, log-log, one
2196// line per language. Shows each language's scaling behaviour across the sizes
2197// already in the data (and where the LOGOS curve flattens out on a collapse).
2198fn scaling_chart(bench: &Benchmark, languages: &[Language]) -> Element {
2199    let mut sizes: Vec<(String, f64)> = bench.sizes.iter()
2200        .filter(|s| bench.scaling.contains_key(s.as_str()))
2201        .filter_map(|s| s.parse::<f64>().ok().map(|n| (s.clone(), n)))
2202        .collect();
2203    sizes.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
2204    if sizes.len() < 2 {
2205        return rsx! {};
2206    }
2207
2208    let mut t_min = f64::INFINITY;
2209    let mut t_max = 0.0_f64;
2210    for (s, _) in &sizes {
2211        if let Some(m) = bench.scaling.get(s) {
2212            for l in languages {
2213                if let Some(t) = m.get(&l.id) {
2214                    if t.median_ms > 0.0 {
2215                        t_min = t_min.min(t.median_ms);
2216                        t_max = t_max.max(t.median_ms);
2217                    }
2218                }
2219            }
2220        }
2221    }
2222    if !t_min.is_finite() || t_max <= 0.0 {
2223        return rsx! {};
2224    }
2225
2226    let nx_min = sizes.first().unwrap().1.ln();
2227    let nx_max = sizes.last().unwrap().1.ln();
2228    let x_span = (nx_max - nx_min).max(1e-9);
2229    let y_span = (t_max.ln() - t_min.ln()).max(1e-9);
2230
2231    let (x0, y0, pw, ph) = (54.0_f64, 14.0_f64, 572.0_f64, 220.0_f64);
2232    let px = |n: f64| x0 + (n.ln() - nx_min) / x_span * pw;
2233    let py = |t: f64| y0 + (1.0 - (t.ln() - t_min.ln()) / y_span) * ph;
2234
2235    // (color, label, vertex coords)
2236    let mut series: Vec<(String, String, Vec<(f64, f64)>)> = Vec::new();
2237    for l in languages {
2238        let mut coords: Vec<(f64, f64)> = Vec::new();
2239        for (s, n) in &sizes {
2240            if let Some(t) = bench.scaling.get(s).and_then(|m| m.get(&l.id)) {
2241                if t.median_ms > 0.0 {
2242                    coords.push((px(*n), py(t.median_ms)));
2243                }
2244            }
2245        }
2246        if !coords.is_empty() {
2247            series.push((l.color.clone(), l.label.clone(), coords));
2248        }
2249    }
2250    if series.is_empty() {
2251        return rsx! {};
2252    }
2253
2254    let y_bottom = y0 + ph;
2255    let x_right = x0 + pw;
2256
2257    // Build the SVG inner markup as a string and set it via dangerous_inner_html
2258    // (the pattern the app's icons already use) so the chart never depends on
2259    // which individual SVG child attributes the rsx macro happens to expose.
2260    let mut svg_inner = String::new();
2261    svg_inner.push_str(&format!(
2262        "<line x1='{x0:.1}' y1='{y0:.1}' x2='{x0:.1}' y2='{y_bottom:.1}' stroke='rgba(255,255,255,0.15)' stroke-width='1'/>"
2263    ));
2264    svg_inner.push_str(&format!(
2265        "<line x1='{x0:.1}' y1='{y_bottom:.1}' x2='{x_right:.1}' y2='{y_bottom:.1}' stroke='rgba(255,255,255,0.15)' stroke-width='1'/>"
2266    ));
2267    svg_inner.push_str(&format!(
2268        "<text x='{:.1}' y='{:.1}' text-anchor='end' fill='rgba(229,231,235,0.45)' font-size='10'>{}</text>",
2269        x0 - 6.0, y0 + 4.0, format_time(t_max)
2270    ));
2271    svg_inner.push_str(&format!(
2272        "<text x='{:.1}' y='{:.1}' text-anchor='end' fill='rgba(229,231,235,0.45)' font-size='10'>{}</text>",
2273        x0 - 6.0, y_bottom, format_time(t_min)
2274    ));
2275    for (_, n) in &sizes {
2276        svg_inner.push_str(&format!(
2277            "<text x='{:.1}' y='{:.1}' text-anchor='middle' fill='rgba(229,231,235,0.45)' font-size='10'>n={}</text>",
2278            px(*n), y_bottom + 16.0, fmt_n(*n)
2279        ));
2280    }
2281    for (color, _label, coords) in &series {
2282        let pts = coords.iter().map(|(x, y)| format!("{x:.1},{y:.1}")).collect::<Vec<_>>().join(" ");
2283        svg_inner.push_str(&format!(
2284            "<polyline points='{pts}' fill='none' stroke='{color}' stroke-width='2' stroke-linejoin='round' stroke-linecap='round'/>"
2285        ));
2286        for (x, y) in coords {
2287            svg_inner.push_str(&format!("<circle cx='{x:.1}' cy='{y:.1}' r='2.5' fill='{color}'/>"));
2288        }
2289    }
2290
2291    rsx! {
2292        div { class: "bench-scaling",
2293            svg {
2294                view_box: "0 0 640 266",
2295                width: "100%",
2296                dangerous_inner_html: "{svg_inner}",
2297            }
2298            div { class: "bench-scaling-legend",
2299                for (color, label, _coords) in series.iter() {
2300                    div { class: "bench-scaling-legend-item",
2301                        span { class: "bench-scaling-legend-dot", style: "background: {color};" }
2302                        "{label}"
2303                    }
2304                }
2305            }
2306        }
2307    }
2308}
2309
2310/// kB → a human byte size for the memory bars.
2311fn format_mem(kb: f64) -> String {
2312    if kb >= 1024.0 * 1024.0 {
2313        format!("{:.1} GB", kb / 1024.0 / 1024.0)
2314    } else if kb >= 1024.0 {
2315        format!("{:.1} MB", kb / 1024.0)
2316    } else {
2317        format!("{kb:.0} KB")
2318    }
2319}
2320
2321/// bytes → a human size for the footprint bars (the byte-input sibling of `format_mem`).
2322fn format_bytes(bytes: f64) -> String {
2323    if bytes >= 1024.0 * 1024.0 * 1024.0 {
2324        format!("{:.1} GB", bytes / 1024.0 / 1024.0 / 1024.0)
2325    } else if bytes >= 1024.0 * 1024.0 {
2326        format!("{:.1} MB", bytes / 1024.0 / 1024.0)
2327    } else {
2328        format!("{:.0} KB", bytes / 1024.0)
2329    }
2330}
2331
2332/// Bar label for a footprint: the as-built size, plus a `(… stripped)` tag only when the
2333/// stripped size is smaller AND renders differently at display resolution (so an
2334/// already-minimal binary never reads as the redundant "327 KB (327 KB stripped)").
2335fn footprint_label(bytes: f64, stripped: Option<f64>) -> String {
2336    let main = format_bytes(bytes);
2337    match stripped {
2338        Some(st) if st > 0.0 && st < bytes => {
2339            let s = format_bytes(st);
2340            if s != main { format!("{main} ({s} stripped)") } else { main }
2341        }
2342        _ => main,
2343    }
2344}
2345
2346/// The shipped footprint: the stripped, code-only binary you actually deploy — or the
2347/// as-built size when no stripped figure exists (e.g. a JVM class directory). This is the
2348/// honest, apples-to-apples number: some toolchains strip by default (`largo build
2349/// --release`) while others leave a symbol table on the as-built artifact, so comparing
2350/// as-built sizes would pit an already-stripped binary against unstripped ones.
2351fn shipped_bytes(as_built: f64, stripped: Option<f64>) -> f64 {
2352    match stripped {
2353        Some(s) if s > 0.0 && s <= as_built => s,
2354        _ => as_built,
2355    }
2356}
2357
2358/// Bar label for the binary-size chart: the shipped (stripped) size is the headline, and
2359/// the as-built size is ALWAYS shown in parentheses so every row reads the same way. When a
2360/// binary already ships stripped (`largo build --release` strips by default) the two numbers
2361/// are equal — that identity is the honest story, not a reason to hide the second figure.
2362fn shipped_footprint_label(as_built: f64, stripped: Option<f64>) -> String {
2363    let shipped = format_bytes(shipped_bytes(as_built, stripped));
2364    let built = format_bytes(as_built);
2365    format!("{shipped} ({built} as-built)")
2366}
2367
2368/// Compiled-artifact footprint — the size analogue of the memory bars, same visual style.
2369/// Each bar is the SHIPPED (stripped, code-only) binary you actually deploy, so every
2370/// toolchain is compared on the same basis; the as-built size (with symbols) rides along
2371/// in the label. Renders nothing until a size run populates `binary_sizes` (older files
2372/// have `binary_sizes: None`).
2373fn binary_size_bar_chart(bench: &Benchmark, languages: &[Language]) -> Element {
2374    let sizes = match &bench.binary_sizes {
2375        Some(s) => s,
2376        None => return rsx! {},
2377    };
2378    // (label, color, shipped, as_built, stripped, is_logos)
2379    let mut bars: Vec<(String, String, f64, f64, Option<f64>, bool)> = languages.iter()
2380        .filter_map(|l| sizes.by_language.get(&l.id)
2381            .filter(|s| s.as_built > 0.0)
2382            .map(|s| (l.label.clone(), l.color.clone(), shipped_bytes(s.as_built, s.stripped), s.as_built, s.stripped, l.id == "logos_release")))
2383        .collect();
2384    if bars.is_empty() {
2385        return rsx! {};
2386    }
2387    bars.sort_by(|a, b| a.2.partial_cmp(&b.2).unwrap_or(std::cmp::Ordering::Equal));
2388    let max = bars.iter().map(|b| b.2).fold(0.0_f64, f64::max).max(1.0);
2389
2390    rsx! {
2391        div { class: "bench-mem",
2392            div { class: "bench-chart-hint", "Shipped size of the compiled program \u{2014} the stripped, code-only binary you actually deploy, so every language is compared on the same basis. Shorter bar ships less; the as-built size (with symbols) is in parentheses." }
2393            div { class: "bench-chart",
2394                for (label, color, shipped, as_built, stripped, is_logos) in bars.iter() {
2395                    {
2396                        let pct = linear_bar_pct(*shipped, max);
2397                        let s = shipped_footprint_label(*as_built, *stripped);
2398                        let show_inside = pct > 32.0;
2399                        let bar_class = if *is_logos { "bench-bar-fill logos-highlight" } else { "bench-bar-fill" };
2400                        rsx! {
2401                            div { class: "bench-bar-row",
2402                                div { class: "bench-bar-label", "{label}" }
2403                                div { class: "bench-bar-track",
2404                                    div { class: "{bar_class}", style: "width: {pct:.1}%; background: {color};",
2405                                        if show_inside {
2406                                            span { class: "bench-bar-time", "{s}" }
2407                                        }
2408                                    }
2409                                }
2410                                if !show_inside {
2411                                    span { class: "bench-bar-time-outside", "{s}" }
2412                                }
2413                            }
2414                        }
2415                    }
2416                }
2417            }
2418        }
2419    }
2420}
2421
2422/// Peak-RSS bar chart at the reference size — the memory analogue of the runtime
2423/// bars, in the same visual style. Renders nothing until a `MEASURE_MEM=1` run
2424/// populates `memory` in the result file (older files have `memory: None`).
2425fn memory_bar_chart(bench: &Benchmark, languages: &[Language]) -> Element {
2426    let mem = match &bench.memory {
2427        Some(m) => m,
2428        None => return rsx! {},
2429    };
2430    let size = if mem.by_size.contains_key(bench.reference_size.as_str()) {
2431        bench.reference_size.clone()
2432    } else {
2433        let mut ks: Vec<(String, f64)> = mem.by_size.keys()
2434            .filter_map(|s| s.parse::<f64>().ok().map(|n| (s.clone(), n)))
2435            .collect();
2436        ks.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
2437        match ks.last() {
2438            Some((s, _)) => s.clone(),
2439            None => return rsx! {},
2440        }
2441    };
2442    let row = match mem.by_size.get(&size) {
2443        Some(r) => r,
2444        None => return rsx! {},
2445    };
2446    let mut bars: Vec<(String, String, f64)> = languages.iter()
2447        .filter_map(|l| row.get(&l.id).and_then(|v| *v)
2448            .filter(|kb| *kb > 0.0)
2449            .map(|kb| (l.label.clone(), l.color.clone(), kb)))
2450        .collect();
2451    if bars.is_empty() {
2452        return rsx! {};
2453    }
2454    bars.sort_by(|a, b| a.2.partial_cmp(&b.2).unwrap_or(std::cmp::Ordering::Equal));
2455    let max = bars.iter().map(|b| b.2).fold(0.0_f64, f64::max);
2456
2457    rsx! {
2458        div { class: "bench-mem",
2459            div { class: "bench-chart-hint", "Peak resident memory at n = {size} \u{2014} shorter bar uses less." }
2460            div { class: "bench-chart",
2461                for (label, color, kb) in bars.iter() {
2462                    {
2463                        let pct = (kb / max * 100.0).min(100.0);
2464                        let s = format_mem(*kb);
2465                        let show_inside = pct > 18.0;
2466                        rsx! {
2467                            div { class: "bench-bar-row",
2468                                div { class: "bench-bar-label", "{label}" }
2469                                div { class: "bench-bar-track",
2470                                    div { class: "bench-bar-fill", style: "width: {pct:.1}%; background: {color};",
2471                                        if show_inside {
2472                                            span { class: "bench-bar-time", "{s}" }
2473                                        }
2474                                    }
2475                                }
2476                                if !show_inside {
2477                                    span { class: "bench-bar-time-outside", "{s}" }
2478                                }
2479                            }
2480                        }
2481                    }
2482                }
2483            }
2484        }
2485    }
2486}
2487
2488/// Declared time/space complexity plus the EMPIRICAL growth exponent fit from the
2489/// measured points: time from the scaling timings (present today), space from the
2490/// multi-size memory data (present after a `MEASURE_MEM=1` run). Renders nothing
2491/// when there is neither a declared complexity nor a fittable series.
2492fn complexity_panel(bench: &Benchmark, languages: &[Language]) -> Element {
2493    let mut sizes: Vec<(String, f64)> = bench.sizes.iter()
2494        .filter(|s| bench.scaling.contains_key(s.as_str()))
2495        .filter_map(|s| s.parse::<f64>().ok().map(|n| (s.clone(), n)))
2496        .collect();
2497    sizes.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
2498
2499    let time_rows: Vec<(String, String, f64)> = languages.iter().filter_map(|l| {
2500        let pts: Vec<(f64, f64)> = sizes.iter().filter_map(|(s, n)| {
2501            bench.scaling.get(s).and_then(|m| m.get(&l.id))
2502                .filter(|t| t.median_ms > 0.0)
2503                .map(|t| (*n, t.median_ms))
2504        }).collect();
2505        empirical_exponent(&pts).map(|e| (l.color.clone(), l.label.clone(), e))
2506    }).collect();
2507
2508    let space_rows: Vec<(String, String, f64)> = match &bench.memory {
2509        Some(mem) => {
2510            let mut ms: Vec<(String, f64)> = mem.by_size.keys()
2511                .filter_map(|s| s.parse::<f64>().ok().map(|n| (s.clone(), n)))
2512                .collect();
2513            ms.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
2514            languages.iter().filter_map(|l| {
2515                let pts: Vec<(f64, f64)> = ms.iter().filter_map(|(s, n)| {
2516                    mem.by_size.get(s).and_then(|m| m.get(&l.id)).and_then(|v| *v)
2517                        .filter(|kb| *kb > 0.0).map(|kb| (*n, kb))
2518                }).collect();
2519                empirical_exponent(&pts).map(|e| (l.color.clone(), l.label.clone(), e))
2520            }).collect()
2521        }
2522        None => Vec::new(),
2523    };
2524
2525    if bench.complexity.is_none() && time_rows.is_empty() && space_rows.is_empty() {
2526        return rsx! {};
2527    }
2528
2529    rsx! {
2530        div { class: "bench-complexity",
2531            div { class: "bench-complexity-title", "Complexity" }
2532            if let Some(c) = &bench.complexity {
2533                div { class: "bench-complexity-declared",
2534                    span { class: "bench-complexity-chip",
2535                        "time " strong { "{c.time}" }
2536                    }
2537                    span { class: "bench-complexity-chip",
2538                        "space " strong { "{c.space}" }
2539                    }
2540                }
2541            }
2542            if !time_rows.is_empty() {
2543                div { class: "bench-complexity-grid",
2544                    div { class: "bench-complexity-col-title", "Measured time growth" }
2545                    for (color, label, e) in time_rows.iter() {
2546                        div { class: "bench-complexity-row",
2547                            span { class: "bench-scaling-legend-dot", style: "background: {color};" }
2548                            span { class: "bench-complexity-lang", "{label}" }
2549                            span { class: "bench-complexity-exp", "t \u{2248} n^{e:.2}" }
2550                        }
2551                    }
2552                }
2553            }
2554            if !space_rows.is_empty() {
2555                div { class: "bench-complexity-grid",
2556                    div { class: "bench-complexity-col-title", "Measured space growth" }
2557                    for (color, label, e) in space_rows.iter() {
2558                        div { class: "bench-complexity-row",
2559                            span { class: "bench-scaling-legend-dot", style: "background: {color};" }
2560                            span { class: "bench-complexity-lang", "{label}" }
2561                            span { class: "bench-complexity-exp", "rss \u{2248} n^{e:.2}" }
2562                        }
2563                    }
2564                }
2565            }
2566        }
2567    }
2568}
2569
2570const BENCHMARKS_STYLE: &str = r#"
2571.bench-opt-toggles {
2572    display: flex;
2573    flex-direction: column;
2574    align-items: flex-start;
2575    gap: 6px;
2576    margin: 16px 0 4px;
2577}
2578.bench-opt-toggle {
2579    display: inline-flex;
2580    align-items: center;
2581    gap: 6px;
2582    padding: 4px 10px;
2583    border: 1px solid rgba(255,255,255,0.12);
2584    border-radius: 6px;
2585    font-size: 12px;
2586    cursor: pointer;
2587    user-select: none;
2588    background: rgba(255,255,255,0.04);
2589    color: #cdd3e0;
2590    transition: border-color .15s, color .15s;
2591}
2592.bench-opt-toggle.off {
2593    border-color: rgba(255,120,120,0.55);
2594    color: #ff9a9a;
2595    background: rgba(255,90,90,0.06);
2596}
2597.bench-opt-toggle input { cursor: pointer; margin: 0; }
2598.bench-opt-toggle.on.firing {
2599    border-color: rgba(0,212,255,0.6);
2600    color: #00d4ff;
2601    background: rgba(0,212,255,0.08);
2602    box-shadow: 0 0 10px rgba(0,212,255,0.18);
2603}
2604.bench-opt-toggle.on.enabling {
2605    border-style: dashed;
2606    border-color: rgba(167,139,250,0.45);
2607    color: rgba(205,211,224,0.75);
2608}
2609.bench-opt-toggle.on.preempted {
2610    border-style: dashed;
2611    border-color: rgba(247,164,29,0.35);
2612    color: rgba(205,211,224,0.55);
2613    background: rgba(247,164,29,0.04);
2614}
2615.bench-tree-row {
2616    display: flex;
2617    align-items: center;
2618    gap: 4px;
2619}
2620.bench-tree-chevron {
2621    display: inline-block;
2622    width: 12px;
2623    flex: 0 0 12px;
2624    font-size: 9px;
2625    color: rgba(229,231,235,0.5);
2626    cursor: pointer;
2627    transition: transform 0.2s ease, color 0.15s;
2628    text-align: center;
2629}
2630.bench-tree-chevron:hover { color: #e5e7eb; }
2631.bench-tree-chevron.open { transform: rotate(90deg); }
2632.bench-tree-spacer {
2633    display: inline-block;
2634    width: 12px;
2635    flex: 0 0 12px;
2636}
2637.bench-opt-master {
2638    display: flex;
2639    align-items: center;
2640    gap: 12px;
2641    flex-wrap: wrap;
2642    margin: 16px 0 6px;
2643}
2644.bench-opt-hint {
2645    font-size: 12px;
2646    color: rgba(229,231,235,0.5);
2647}
2648.bench-opt-rel {
2649    font-size: 10px;
2650    margin-left: 5px;
2651    padding: 1px 5px;
2652    border-radius: 4px;
2653    background: rgba(255,255,255,0.05);
2654    white-space: nowrap;
2655}
2656.bench-opt-rel.needs { color: #a78bfa; }
2657.bench-opt-rel.beats { color: #f7a41d; }
2658.bench-opt-rel.enables { color: #a78bfa; font-style: italic; }
2659.bench-opt-rel.depends { color: #6ee7b7; }
2660.bench-opt-rel.beaten { color: #f7a41d; font-style: italic; }
2661.bench-opt-rel.beats-now {
2662    color: #1a1410;
2663    background: rgba(247,164,29,0.85);
2664    font-weight: 700;
2665}
2666.bench-compiling {
2667    display: inline-flex;
2668    align-items: center;
2669    gap: 8px;
2670    color: #00d4ff;
2671    font-size: 12px;
2672    font-weight: 500;
2673}
2674.bench-compiling::before {
2675    content: "";
2676    width: 11px;
2677    height: 11px;
2678    border: 2px solid rgba(0,212,255,0.25);
2679    border-top-color: #00d4ff;
2680    border-radius: 50%;
2681    animation: bench-spin 0.6s linear infinite;
2682}
2683@keyframes bench-spin {
2684    to { transform: rotate(360deg); }
2685}
2686.bench-container {
2687    min-height: 100vh;
2688    background: linear-gradient(135deg, #070a12 0%, #0b1022 50%, #070a12 100%);
2689    color: #e5e7eb;
2690    font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
2691}
2692
2693.bench-hero {
2694    text-align: center;
2695    padding: 60px 20px 20px;
2696    max-width: 800px;
2697    margin: 0 auto;
2698}
2699
2700.bench-hero h1 {
2701    font-size: 42px;
2702    font-weight: 800;
2703    letter-spacing: -1px;
2704    background: linear-gradient(180deg, #ffffff 0%, rgba(229,231,235,0.78) 100%);
2705    -webkit-background-clip: text;
2706    -webkit-text-fill-color: transparent;
2707    margin-bottom: 12px;
2708}
2709
2710.bench-hero p {
2711    color: rgba(229,231,235,0.72);
2712    font-size: 18px;
2713    line-height: 1.6;
2714    margin-bottom: 20px;
2715}
2716
2717.bench-gate-status {
2718    color: rgba(229,231,235,0.72);
2719    font-size: 18px;
2720    padding: 40px 0 12px;
2721}
2722
2723.bench-gate-status.error {
2724    color: #fca5a5;
2725}
2726
2727.bench-gate-retry {
2728    padding: 10px 28px;
2729    border-radius: 10px;
2730    border: 1px solid rgba(255,255,255,0.2);
2731    background: rgba(255,255,255,0.08);
2732    color: #e8e8e8;
2733    font-size: 15px;
2734    cursor: pointer;
2735}
2736
2737.bench-gate-retry:hover {
2738    background: rgba(255,255,255,0.16);
2739}
2740
2741.bench-pills {
2742    display: flex;
2743    flex-wrap: wrap;
2744    gap: 8px;
2745    justify-content: center;
2746    margin-bottom: 16px;
2747}
2748
2749.bench-pill {
2750    display: inline-flex;
2751    align-items: center;
2752    gap: 4px;
2753    font-size: 12px;
2754    padding: 5px 12px;
2755    border-radius: 16px;
2756    background: rgba(255,255,255,0.05);
2757    border: 1px solid rgba(255,255,255,0.10);
2758    color: rgba(229,231,235,0.72);
2759    text-decoration: none;
2760    transition: all 0.2s ease;
2761}
2762
2763.bench-pill:hover {
2764    background: rgba(255,255,255,0.08);
2765    border-color: rgba(255,255,255,0.15);
2766}
2767
2768.bench-pill strong {
2769    color: #e5e7eb;
2770}
2771
2772.bench-pill.link {
2773    cursor: pointer;
2774    color: #00d4ff;
2775}
2776
2777.bench-section-nav {
2778    display: flex;
2779    justify-content: center;
2780    gap: 6px;
2781    padding: 12px 20px;
2782    margin-bottom: 24px;
2783    flex-wrap: wrap;
2784}
2785
2786.bench-section-nav a {
2787    font-size: 12px;
2788    font-weight: 500;
2789    padding: 5px 14px;
2790    border-radius: 16px;
2791    background: rgba(255,255,255,0.04);
2792    border: 1px solid rgba(255,255,255,0.08);
2793    color: rgba(229,231,235,0.6);
2794    text-decoration: none;
2795    transition: all 0.2s ease;
2796    backdrop-filter: blur(12px);
2797}
2798
2799.bench-section-nav a:hover {
2800    background: rgba(255,255,255,0.08);
2801    color: #e5e7eb;
2802    border-color: rgba(255,255,255,0.15);
2803}
2804
2805.bench-tabbar {
2806    display: flex;
2807    justify-content: center;
2808    gap: 4px;
2809    max-width: 1000px;
2810    margin: 0 auto 28px;
2811    padding: 4px;
2812    background: rgba(255,255,255,0.03);
2813    border: 1px solid rgba(255,255,255,0.08);
2814    border-radius: 14px;
2815    width: fit-content;
2816    flex-wrap: wrap;
2817}
2818
2819.bench-tabbar-btn {
2820    padding: 10px 22px;
2821    border: none;
2822    border-radius: 10px;
2823    background: transparent;
2824    color: rgba(229,231,235,0.55);
2825    font-size: 14px;
2826    font-weight: 600;
2827    letter-spacing: 0.2px;
2828    cursor: pointer;
2829    transition: all 0.2s ease;
2830}
2831
2832.bench-tabbar-btn:hover {
2833    color: #e5e7eb;
2834    background: rgba(255,255,255,0.05);
2835}
2836
2837.bench-tabbar-btn.active {
2838    background: linear-gradient(135deg, rgba(0,212,255,0.18), rgba(167,139,250,0.18));
2839    color: #e5e7eb;
2840    box-shadow: 0 2px 10px rgba(0,212,255,0.12);
2841}
2842
2843.bench-content {
2844    max-width: 1000px;
2845    margin: 0 auto;
2846    padding: 0 20px 80px;
2847}
2848
2849.bench-summary {
2850    display: grid;
2851    grid-template-columns: repeat(3, 1fr);
2852    gap: 16px;
2853    margin-bottom: 40px;
2854}
2855
2856.bench-summary-card {
2857    background: rgba(255,255,255,0.03);
2858    border: 1px solid rgba(255,255,255,0.08);
2859    border-radius: 16px;
2860    padding: 24px;
2861    text-align: center;
2862    transition: all 0.2s ease;
2863}
2864
2865.bench-summary-card:hover {
2866    background: rgba(255,255,255,0.05);
2867    border-color: rgba(255,255,255,0.12);
2868}
2869
2870.bench-summary-value {
2871    font-size: 36px;
2872    font-weight: 800;
2873    letter-spacing: -1px;
2874    margin-bottom: 4px;
2875}
2876
2877.bench-summary-eyebrow {
2878    font-size: 11px;
2879    font-weight: 600;
2880    text-transform: uppercase;
2881    letter-spacing: 0.5px;
2882    color: rgba(229,231,235,0.5);
2883    margin-bottom: 8px;
2884}
2885
2886.bench-summary-value.cyan { color: #00d4ff; }
2887.bench-summary-value.green { color: #22c55e; }
2888.bench-summary-value.purple { color: #a78bfa; }
2889
2890.bench-summary-label {
2891    font-size: 13px;
2892    color: rgba(229,231,235,0.56);
2893}
2894
2895.bench-tabs {
2896    display: flex;
2897    gap: 6px;
2898    margin-bottom: 24px;
2899    flex-wrap: wrap;
2900}
2901
2902.bench-tab {
2903    padding: 8px 16px;
2904    border-radius: 8px;
2905    border: 1px solid rgba(255,255,255,0.1);
2906    background: rgba(255,255,255,0.03);
2907    color: #94a3b8;
2908    cursor: pointer;
2909    font-size: 13px;
2910    font-weight: 500;
2911    transition: all 0.2s ease;
2912}
2913
2914.bench-tab:hover {
2915    background: rgba(255,255,255,0.08);
2916    color: #e8e8e8;
2917}
2918
2919.bench-tab.active {
2920    background: linear-gradient(135deg, rgba(0,212,255,0.25), rgba(129,140,248,0.25));
2921    color: #00d4ff;
2922    border-color: rgba(0,212,255,0.4);
2923}
2924
2925.bench-section {
2926    background: rgba(255,255,255,0.03);
2927    border: 1px solid rgba(255,255,255,0.08);
2928    border-radius: 16px;
2929    padding: 24px;
2930    margin-bottom: 24px;
2931}
2932
2933.bench-section-title {
2934    font-size: 18px;
2935    font-weight: 700;
2936    color: #fff;
2937    margin-bottom: 6px;
2938}
2939
2940.bench-section-desc {
2941    font-size: 13px;
2942    color: rgba(229,231,235,0.56);
2943    margin-bottom: 20px;
2944}
2945
2946.bench-chart {
2947    display: flex;
2948    flex-direction: column;
2949    gap: 6px;
2950}
2951
2952.bench-tier-label {
2953    font-size: 10px;
2954    font-weight: 600;
2955    text-transform: uppercase;
2956    letter-spacing: 0.5px;
2957    color: rgba(229,231,235,0.4);
2958    margin-top: 10px;
2959    margin-bottom: 2px;
2960}
2961
2962.bench-bar-row {
2963    display: flex;
2964    align-items: center;
2965    gap: 12px;
2966}
2967
2968.bench-bar-label {
2969    width: 130px;
2970    text-align: right;
2971    font-size: 13px;
2972    font-weight: 500;
2973    color: rgba(229,231,235,0.8);
2974    flex-shrink: 0;
2975}
2976
2977.bench-bar-track {
2978    flex: 1;
2979    min-width: 0;
2980    height: 28px;
2981    background: rgba(255,255,255,0.02);
2982    border-radius: 6px;
2983    overflow: hidden;
2984    position: relative;
2985}
2986
2987.bench-bar-fill {
2988    height: 100%;
2989    border-radius: 6px;
2990    display: flex;
2991    align-items: center;
2992    justify-content: flex-end;
2993    padding-right: 8px;
2994    min-width: 2px;
2995    transition: width 0.4s ease;
2996}
2997
2998.bench-bar-fill.logos-highlight {
2999    box-shadow: 0 0 16px rgba(0,212,255,0.35);
3000}
3001
3002.bench-bar-time {
3003    font-size: 11px;
3004    font-weight: 600;
3005    color: rgba(0,0,0,0.8);
3006    white-space: nowrap;
3007}
3008
3009.bench-bar-time-outside {
3010    font-size: 11px;
3011    font-weight: 600;
3012    color: rgba(229,231,235,0.6);
3013    white-space: nowrap;
3014    margin-left: 8px;
3015    flex-shrink: 0;
3016}
3017
3018/* Codec charts: the bar shows magnitude only; the exact value lives in its own
3019   always-visible right column, so even the smallest (winning) bar never hides its number. */
3020.bench-codec-track {
3021    flex: 1;
3022    height: 22px;
3023    background: rgba(255,255,255,0.04);
3024    border-radius: 6px;
3025    position: relative;
3026}
3027
3028.bench-codec-fill {
3029    height: 100%;
3030    border-radius: 6px;
3031    min-width: 3px;
3032    transition: width 0.4s ease;
3033}
3034
3035.bench-codec-fill.logos-highlight {
3036    box-shadow: 0 0 14px rgba(0,212,255,0.5);
3037}
3038
3039.bench-codec-val {
3040    width: 92px;
3041    text-align: right;
3042    font-size: 12px;
3043    font-weight: 600;
3044    color: rgba(229,231,235,0.75);
3045    flex-shrink: 0;
3046    font-variant-numeric: tabular-nums;
3047}
3048
3049.bench-codec-val.logos-val {
3050    color: #38e1ff;
3051}
3052
3053.bench-source {
3054    display: grid;
3055    grid-template-columns: 1fr 1fr;
3056    gap: 16px;
3057}
3058
3059.bench-source-panel {
3060    display: flex;
3061    flex-direction: column;
3062}
3063
3064.bench-source-header {
3065    font-size: 11px;
3066    font-weight: 600;
3067    text-transform: uppercase;
3068    letter-spacing: 0.5px;
3069    padding: 8px 12px;
3070    border-radius: 8px 8px 0 0;
3071    border: 1px solid rgba(255,255,255,0.08);
3072    border-bottom: none;
3073}
3074
3075.bench-source-header.logos {
3076    background: rgba(0,212,255,0.1);
3077    color: #00d4ff;
3078}
3079
3080.bench-source-header.rust {
3081    background: rgba(222,165,132,0.1);
3082    color: #dea584;
3083}
3084
3085.bench-source-code {
3086    background: rgba(0,0,0,0.3);
3087    border: 1px solid rgba(255,255,255,0.08);
3088    border-radius: 0 0 8px 8px;
3089    padding: 16px;
3090    font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
3091    font-size: 12px;
3092    line-height: 1.5;
3093    color: #e8e8e8;
3094    white-space: pre-wrap;
3095    overflow-x: auto;
3096    flex: 1;
3097}
3098
3099/* Collapsible pattern */
3100.bench-collapsible-btn {
3101    display: flex;
3102    align-items: center;
3103    gap: 8px;
3104    width: 100%;
3105    padding: 10px 0;
3106    background: none;
3107    border: none;
3108    border-top: 1px solid rgba(255,255,255,0.06);
3109    color: rgba(229,231,235,0.6);
3110    font-size: 13px;
3111    font-weight: 500;
3112    cursor: pointer;
3113    transition: color 0.2s ease;
3114    margin-top: 16px;
3115    text-align: left;
3116}
3117
3118.bench-collapsible-btn:hover {
3119    color: #e5e7eb;
3120}
3121
3122.bench-collapsible-chevron {
3123    display: inline-block;
3124    font-size: 10px;
3125    transition: transform 0.2s ease;
3126}
3127
3128.bench-collapsible-chevron.open {
3129    transform: rotate(90deg);
3130}
3131
3132.bench-collapsible-body {
3133    overflow: hidden;
3134    max-height: 0;
3135    transition: max-height 0.3s ease;
3136}
3137
3138.bench-collapsible-body.open {
3139    max-height: 8000px;
3140}
3141
3142/* Stats table */
3143.bench-stats-table {
3144    width: 100%;
3145    border-collapse: collapse;
3146    font-size: 12px;
3147    margin-top: 12px;
3148}
3149
3150.bench-stats-table th {
3151    text-align: left;
3152    font-size: 10px;
3153    font-weight: 600;
3154    text-transform: uppercase;
3155    letter-spacing: 0.5px;
3156    color: rgba(229,231,235,0.5);
3157    padding: 6px 8px;
3158    border-bottom: 1px solid rgba(255,255,255,0.08);
3159}
3160
3161.bench-stats-table td {
3162    padding: 6px 8px;
3163    color: rgba(229,231,235,0.7);
3164    border-bottom: 1px solid rgba(255,255,255,0.04);
3165    font-family: 'SF Mono', 'Fira Code', monospace;
3166    font-size: 11px;
3167}
3168
3169.bench-stats-table tr.highlight td {
3170    color: #00d4ff;
3171    background: rgba(0,212,255,0.05);
3172}
3173
3174/* Language source collapsible */
3175.bench-lang-collapsible {
3176    border: 1px solid rgba(255,255,255,0.06);
3177    border-radius: 8px;
3178    margin-bottom: 8px;
3179    overflow: hidden;
3180}
3181
3182.bench-lang-header {
3183    display: flex;
3184    align-items: center;
3185    gap: 10px;
3186    padding: 10px 14px;
3187    background: rgba(255,255,255,0.02);
3188    cursor: pointer;
3189    transition: background 0.2s ease;
3190}
3191
3192.bench-lang-header:hover {
3193    background: rgba(255,255,255,0.05);
3194}
3195
3196.bench-lang-dot {
3197    width: 8px;
3198    height: 8px;
3199    border-radius: 50%;
3200    flex-shrink: 0;
3201}
3202
3203.bench-lang-name {
3204    font-size: 13px;
3205    font-weight: 500;
3206    color: #e5e7eb;
3207    flex: 1;
3208}
3209
3210.bench-lang-version {
3211    font-size: 11px;
3212    color: rgba(229,231,235,0.4);
3213}
3214
3215.bench-lang-link {
3216    font-size: 11px;
3217    color: #00d4ff;
3218    text-decoration: none;
3219    opacity: 0.7;
3220    transition: opacity 0.2s ease;
3221}
3222
3223.bench-lang-link:hover {
3224    opacity: 1;
3225    text-decoration: underline;
3226}
3227
3228.bench-lang-code {
3229    background: rgba(0,0,0,0.3);
3230    padding: 16px;
3231    font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
3232    font-size: 12px;
3233    line-height: 1.5;
3234    color: #e8e8e8;
3235    white-space: pre-wrap;
3236    overflow-x: auto;
3237    max-height: 0;
3238    transition: max-height 0.3s ease, padding 0.3s ease;
3239    padding-top: 0;
3240    padding-bottom: 0;
3241}
3242
3243.bench-lang-code.open {
3244    max-height: 4000px;
3245    padding-top: 16px;
3246    padding-bottom: 16px;
3247}
3248
3249/* Compile chart */
3250.bench-compile-table {
3251    width: 100%;
3252    border-collapse: collapse;
3253}
3254
3255.bench-compile-table th {
3256    text-align: left;
3257    font-size: 11px;
3258    font-weight: 600;
3259    text-transform: uppercase;
3260    letter-spacing: 0.5px;
3261    color: rgba(229,231,235,0.5);
3262    padding: 8px 12px;
3263    border-bottom: 1px solid rgba(255,255,255,0.08);
3264}
3265
3266.bench-compile-table td {
3267    padding: 8px 12px;
3268    font-size: 13px;
3269    color: rgba(229,231,235,0.8);
3270    border-bottom: 1px solid rgba(255,255,255,0.04);
3271}
3272
3273.bench-compile-table tr:last-child td {
3274    border-bottom: none;
3275}
3276
3277.bench-compile-table .compiler-name {
3278    font-weight: 500;
3279    color: #e5e7eb;
3280}
3281
3282.bench-compile-table tr.highlight td {
3283    color: #00d4ff;
3284}
3285
3286/* Methodology */
3287.bench-methodology {
3288    color: rgba(229,231,235,0.56);
3289    font-size: 13px;
3290    line-height: 1.7;
3291}
3292
3293.bench-methodology ul {
3294    padding-left: 20px;
3295    margin: 8px 0;
3296}
3297
3298.bench-methodology li {
3299    margin-bottom: 4px;
3300}
3301
3302.bench-methodology a {
3303    color: #00d4ff;
3304    text-decoration: none;
3305}
3306
3307.bench-methodology a:hover {
3308    text-decoration: underline;
3309}
3310
3311.bench-methodology h3 {
3312    font-size: 14px;
3313    font-weight: 600;
3314    color: #e5e7eb;
3315    margin: 16px 0 8px;
3316}
3317
3318.bench-version-table {
3319    width: 100%;
3320    border-collapse: collapse;
3321    margin: 8px 0 16px;
3322}
3323
3324.bench-version-table th {
3325    text-align: left;
3326    font-size: 11px;
3327    font-weight: 600;
3328    text-transform: uppercase;
3329    letter-spacing: 0.5px;
3330    color: rgba(229,231,235,0.5);
3331    padding: 6px 10px;
3332    border-bottom: 1px solid rgba(255,255,255,0.08);
3333}
3334
3335.bench-version-table td {
3336    padding: 6px 10px;
3337    font-size: 12px;
3338    color: rgba(229,231,235,0.7);
3339    border-bottom: 1px solid rgba(255,255,255,0.04);
3340}
3341
3342/* Algorithmic-collapse note + badges */
3343.bench-summary-value sup {
3344    font-size: 18px;
3345    color: rgba(0,212,255,0.7);
3346    font-weight: 700;
3347}
3348
3349.bench-note {
3350    background: rgba(0,212,255,0.04);
3351    border: 1px solid rgba(0,212,255,0.15);
3352    border-radius: 12px;
3353    padding: 14px 18px;
3354    margin-bottom: 32px;
3355    font-size: 13px;
3356    line-height: 1.6;
3357    color: rgba(229,231,235,0.7);
3358}
3359
3360.bench-note strong { color: #00d4ff; }
3361
3362.bench-tab-badge {
3363    display: inline-block;
3364    margin-left: 6px;
3365    font-size: 10px;
3366}
3367
3368.bench-callout {
3369    display: flex;
3370    gap: 10px;
3371    align-items: flex-start;
3372    background: rgba(0,212,255,0.05);
3373    border: 1px solid rgba(0,212,255,0.18);
3374    border-radius: 10px;
3375    padding: 12px 14px;
3376    margin-bottom: 18px;
3377    font-size: 13px;
3378    line-height: 1.55;
3379    color: rgba(229,231,235,0.8);
3380}
3381
3382.bench-callout-icon {
3383    flex-shrink: 0;
3384    font-size: 15px;
3385    line-height: 1.4;
3386}
3387
3388.bench-chart-hint {
3389    font-size: 11px;
3390    color: rgba(229,231,235,0.4);
3391    margin-bottom: 10px;
3392}
3393
3394/* Scaling curve (inline SVG) */
3395.bench-scaling {
3396    margin-top: 8px;
3397}
3398
3399.bench-scaling svg {
3400    width: 100%;
3401    height: auto;
3402    display: block;
3403}
3404
3405.bench-scaling-legend {
3406    display: flex;
3407    flex-wrap: wrap;
3408    gap: 10px 16px;
3409    margin-top: 10px;
3410}
3411
3412.bench-scaling-legend-item {
3413    display: inline-flex;
3414    align-items: center;
3415    gap: 6px;
3416    font-size: 11px;
3417    color: rgba(229,231,235,0.6);
3418}
3419
3420.bench-scaling-legend-dot {
3421    width: 10px;
3422    height: 3px;
3423    border-radius: 2px;
3424}
3425
3426/* Complexity panel + memory bars */
3427.bench-complexity {
3428    margin: 20px 0 4px;
3429    padding: 14px 16px;
3430    border: 1px solid rgba(255,255,255,0.08);
3431    border-radius: 8px;
3432    background: rgba(255,255,255,0.02);
3433}
3434.bench-complexity-title {
3435    font-size: 11px;
3436    font-weight: 700;
3437    text-transform: uppercase;
3438    letter-spacing: 0.5px;
3439    color: rgba(229,231,235,0.45);
3440    margin-bottom: 10px;
3441}
3442.bench-complexity-declared {
3443    display: flex;
3444    gap: 10px;
3445    flex-wrap: wrap;
3446    margin-bottom: 12px;
3447}
3448.bench-complexity-chip {
3449    font-size: 12px;
3450    color: rgba(229,231,235,0.6);
3451    padding: 4px 10px;
3452    border-radius: 6px;
3453    background: rgba(255,255,255,0.04);
3454    border: 1px solid rgba(255,255,255,0.08);
3455}
3456.bench-complexity-chip strong { color: #93c5fd; font-weight: 700; margin-left: 4px; }
3457.bench-complexity-grid {
3458    display: flex;
3459    flex-direction: column;
3460    gap: 4px;
3461    margin-top: 8px;
3462}
3463.bench-complexity-col-title {
3464    font-size: 10px;
3465    text-transform: uppercase;
3466    letter-spacing: 0.4px;
3467    color: rgba(229,231,235,0.35);
3468    margin-bottom: 2px;
3469}
3470.bench-complexity-row {
3471    display: flex;
3472    align-items: center;
3473    gap: 8px;
3474    font-size: 12px;
3475}
3476.bench-complexity-lang { color: rgba(229,231,235,0.7); min-width: 90px; }
3477.bench-complexity-exp { color: rgba(229,231,235,0.5); font-family: ui-monospace, monospace; }
3478.bench-mem { margin-top: 8px; }
3479
3480/* Interpreter-vs-V8 section bits */
3481.bench-engine-pill {
3482    display: inline-flex;
3483    align-items: center;
3484    gap: 4px;
3485    font-size: 11px;
3486    padding: 3px 10px;
3487    border-radius: 12px;
3488    background: rgba(255,140,0,0.1);
3489    border: 1px solid rgba(255,140,0,0.25);
3490    color: #ff8c00;
3491    margin-left: 8px;
3492}
3493
3494.bench-floor-badge {
3495    font-size: 10px;
3496    color: #fbbf24;
3497    margin-left: 8px;
3498    white-space: nowrap;
3499}
3500
3501.bench-bar-n {
3502    font-size: 10px;
3503    color: rgba(229,231,235,0.4);
3504    margin-left: 6px;
3505}
3506
3507@media (max-width: 768px) {
3508    .bench-hero h1 { font-size: 32px; }
3509    .bench-summary { grid-template-columns: 1fr; }
3510    .bench-source { grid-template-columns: 1fr; }
3511    .bench-bar-label { width: 80px; font-size: 11px; }
3512    .bench-summary-value { font-size: 28px; }
3513    .bench-section-nav { gap: 4px; }
3514    .bench-section-nav a { font-size: 11px; padding: 4px 10px; }
3515    .bench-tabbar { width: auto; }
3516    .bench-tabbar-btn { padding: 9px 14px; font-size: 12.5px; }
3517}
3518
3519@media (max-width: 480px) {
3520    .bench-hero h1 { font-size: 26px; }
3521    .bench-hero p { font-size: 15px; }
3522    .bench-content { padding: 0 12px 60px; }
3523}
3524"#;
3525
3526/// The three top-level benchmark stories, shown as tabs: the programming
3527/// language itself, the SAT solver, and the transport wire codec.
3528#[derive(Clone, Copy, PartialEq, Eq)]
3529enum BenchTab {
3530    Language,
3531    Solver,
3532    Codec,
3533}
3534
3535impl BenchTab {
3536    fn label(self) -> &'static str {
3537        match self {
3538            BenchTab::Language => "Programming Language",
3539            BenchTab::Solver => "SAT Solver",
3540            BenchTab::Codec => "Transport Codec",
3541        }
3542    }
3543
3544    fn all() -> [BenchTab; 3] {
3545        [BenchTab::Language, BenchTab::Solver, BenchTab::Codec]
3546    }
3547}
3548
3549/// Gate component: guarantees the data feeds are pinned before the page proper
3550/// renders, so every accessor inside `BenchmarksLoaded` can `expect` its feed.
3551/// Native builds (tests, SSG prerender) compile the data in and render directly;
3552/// wasm fetches the staged `/data` bundle first, behind a lightweight shell.
3553#[component(lazy)]
3554pub fn Benchmarks() -> Element {
3555    #[cfg(not(target_arch = "wasm32"))]
3556    return rsx! { BenchmarksLoaded {} };
3557
3558    #[cfg(target_arch = "wasm32")]
3559    {
3560        let mut bundle = use_resource(load_bench_bundle);
3561        let state = bundle.read_unchecked();
3562        match &*state {
3563            Some(Ok(())) => rsx! { BenchmarksLoaded {} },
3564            Some(Err(e)) => rsx! {
3565                BenchShell {
3566                    p { class: "bench-gate-status error", "Benchmark data failed to load: {e}" }
3567                    button {
3568                        class: "bench-gate-retry",
3569                        onclick: move |_| bundle.restart(),
3570                        "Retry"
3571                    }
3572                }
3573            },
3574            None => rsx! {
3575                BenchShell {
3576                    p { class: "bench-gate-status", "Loading benchmark data\u{2026}" }
3577                }
3578            },
3579        }
3580    }
3581}
3582
3583/// The nav/meta shell shown while the wasm data bundle is in flight (or failed):
3584/// full PageHead + nav + footer, so the page keeps its meta and chrome either way.
3585#[cfg(target_arch = "wasm32")]
3586#[component]
3587fn BenchShell(children: Element) -> Element {
3588    rsx! {
3589        PageHead {
3590            title: seo_pages::BENCHMARKS.title,
3591            description: seo_pages::BENCHMARKS.description,
3592            canonical_path: seo_pages::BENCHMARKS.canonical_path,
3593        }
3594        style { "{BENCHMARKS_STYLE}" }
3595        div { class: "bench-container",
3596            MainNav { active: ActivePage::Benchmarks, subtitle: Some("Performance") }
3597            section { class: "bench-hero",
3598                h1 { "Benchmarks" }
3599                {children}
3600            }
3601            Footer {}
3602        }
3603    }
3604}
3605
3606#[component]
3607fn BenchmarksLoaded() -> Element {
3608    let data = bench_data().expect("gated: the Benchmarks shell loads the bundle first");
3609    let mut active_bench = use_signal(|| 0usize);
3610    let mut bench_tab = use_signal(|| BenchTab::Language);
3611    // Optimization-toggle showcase state: one on/off per registry optimization
3612    // (all on by default = the normal optimized build). Flipping one inserts a
3613    // `## No <X>` decorator and recompiles the Rust live, in the browser.
3614    let mut opt_toggles = use_signal(|| vec![true; logicaffeine_compile::optimization::REGISTRY.len()]);
3615    // Live-compile state for the toggle showcase. `live_rust` holds the last
3616    // in-browser compile (None = show the pre-baked cached Rust), `compiling`
3617    // drives the spinner, and `compile_gen` lets a newer toggle supersede an
3618    // in-flight compile.
3619    let mut live_rust = use_signal(|| Option::<String>::None);
3620    let mut compiling = use_signal(|| false);
3621    let mut compile_gen = use_signal(|| 0u64);
3622    // The all-on optimization graph for the current benchmark — the STABLE tree
3623    // structure. `base_fired` (what fires), `base_preempted` (blockers), and
3624    // `base_dependencies` (emergent per-program dependencies) are seeded instantly
3625    // from the baked benchmark data so switching benchmarks pops the tree in with no
3626    // compile; `fired_now`/`preempted_now` reflect the CURRENT toggle state (what is
3627    // firing right now), updated by the live re-trace when an optimization is off.
3628    let mut base_fired = use_signal(Vec::<&'static str>::new);
3629    let mut fired_now = use_signal(Vec::<&'static str>::new);
3630    let mut preempted_now = use_signal(Vec::<(&'static str, &'static str)>::new);
3631    let mut base_preempted = use_signal(Vec::<(&'static str, &'static str)>::new);
3632    let mut base_dependencies = use_signal(Vec::<(&'static str, &'static str)>::new);
3633    // Tree expand/collapse state, one bool per registry optimization (default
3634    // expanded). A collapsed parent hides its requires-descendants.
3635    let mut expanded = use_signal(|| vec![true; logicaffeine_compile::optimization::REGISTRY.len()]);
3636    let mut stats_open = use_signal(|| false);
3637    let mut compile_detail_open = use_signal(|| false);
3638    let mut methodology_open = use_signal(|| false);
3639    let mut source_open: Signal<[bool; 10]> = use_signal(|| [false; 10]);
3640
3641    // Seed the stable all-on graph from the BAKED benchmark data and re-trace the
3642    // showcase Rust on toggle changes. The DEFAULT all-on view never compiles in the
3643    // browser — the optimization graph is embedded in `latest.json` (baked by the
3644    // benchmark run / `scripts/bake-opt-graph.sh`, exactly like the timing results)
3645    // and the Rust is the pre-baked `generated_rust`, so switching benchmarks is
3646    // instant. ONLY turning an optimization OFF triggers a browser compile, and only
3647    // to show that toggled state's Rust + which opts then fire — the one thing that
3648    // cannot be pre-computed (it is combinatorial). Tracks `active_bench` +
3649    // `opt_toggles`; `compile_gen` is read via peek so the effect never re-triggers
3650    // itself.
3651    use_effect(move || {
3652        let idx = active_bench();
3653        let toggles = opt_toggles();
3654        let b = &data.benchmarks[idx];
3655        let kw = |s: &str| logicaffeine_compile::optimization::by_keyword(s).map(|o| o.meta().keyword);
3656        // The baked all-on graph (keywords → interned &'static str). Always seeds the
3657        // stable tree structure — no analysis in the browser.
3658        let baked_fired: Vec<&'static str> = b.fired.iter().filter_map(|s| kw(s)).collect();
3659        let baked_blockers: Vec<(&'static str, &'static str)> =
3660            b.blockers.iter().filter_map(|(w, l)| Some((kw(w)?, kw(l)?))).collect();
3661        let baked_deps: Vec<(&'static str, &'static str)> =
3662            b.dependencies.iter().filter_map(|(d, x)| Some((kw(d)?, kw(x)?))).collect();
3663        base_fired.set(baked_fired.clone());
3664        base_preempted.set(baked_blockers.clone());
3665        base_dependencies.set(baked_deps);
3666
3667        let disabled: Vec<&'static str> = logicaffeine_compile::optimization::REGISTRY
3668            .iter()
3669            .enumerate()
3670            .filter(|(i, _)| !toggles[*i])
3671            .map(|(_, m)| m.keyword)
3672            .collect();
3673        let cache_present = !b.generated_rust.trim().is_empty();
3674
3675        // Default view (every optimization on): fully served from baked data — the
3676        // baked fired set, the baked blockers, and the cached Rust. No compile, ever.
3677        if disabled.is_empty() {
3678            fired_now.set(baked_fired);
3679            preempted_now.set(baked_blockers);
3680            live_rust.set(if cache_present { None } else { Some(b.generated_rust.clone()) });
3681            compiling.set(false);
3682            return;
3683        }
3684
3685        // An optimization is OFF — compile just this toggled state to show its Rust
3686        // and which optimizations now fire.
3687        let decorated =
3688            logicaffeine_compile::optimization::decorate_source(&b.logos_source, &disabled);
3689        let gen = *compile_gen.peek() + 1;
3690        compile_gen.set(gen);
3691        compiling.set(true);
3692        spawn(async move {
3693            gloo_timers::future::TimeoutFuture::new(30).await;
3694            if *compile_gen.peek() != gen {
3695                return;
3696            }
3697            let (rust, fired, preempted) =
3698                logicaffeine_compile::compile::compile_to_rust_traced(&decorated)
3699                    .unwrap_or_else(|e| (format!("// compile error: {e:?}"), Vec::new(), Vec::new()));
3700            if *compile_gen.peek() != gen {
3701                return;
3702            }
3703            fired_now.set(fired);
3704            preempted_now.set(preempted);
3705            live_rust.set(Some(rust));
3706            compiling.set(false);
3707        });
3708    });
3709
3710    let breadcrumbs = vec![
3711        BreadcrumbItem { name: "Home", path: "/" },
3712        BreadcrumbItem { name: "Benchmarks", path: "/benchmarks" },
3713    ];
3714    let schemas = vec![
3715        organization_schema(),
3716        webpage_schema("LOGOS Benchmarks", seo_pages::BENCHMARKS.description, "/benchmarks"),
3717        breadcrumb_schema(&breadcrumbs),
3718    ];
3719
3720    let logos_vs_c = data.summary.geometric_mean_speedup_vs_c
3721        .get("logos_release").copied().unwrap_or(0.0);
3722
3723    let interp = interp_data().expect("gated: the Benchmarks shell loads the bundle first");
3724    // Headline numbers, all framed as "x the speed of <baseline>" (higher = faster).
3725    let logos_apples = logos_apples_geomean(data);
3726    let interp_speed = interp_speed_vs_v8(interp);
3727    let aot_speed = aot_speed_vs_v8(interp);
3728    let collapse_count = data.benchmarks.iter().filter(|b| collapse_note(&b.id).is_some()).count();
3729    let apples_count = data.benchmarks.len().saturating_sub(collapse_count);
3730
3731    let bench = &data.benchmarks[active_bench()];
3732    let bench_sources = bench_sources_for(&bench.id)
3733        .expect("sources_cover_every_benchmark locks every benchmark id to a sources entry");
3734
3735    // Toggle showcase — cheap, render-safe derived state only. The decorated
3736    // LOGOS source is a string op; the expensive Rust compile is NOT run here
3737    // (doing it on every render froze the page). With every optimization on we
3738    // show the pre-baked cached Rust (`bench.generated_rust`) for an instant,
3739    // no-compile view; any optimization off shows the live-compiled `live_rust`
3740    // produced asynchronously by the use_effect above, with a spinner in between.
3741    let opt_tog = opt_toggles();
3742    let opt_disabled: Vec<&'static str> = logicaffeine_compile::optimization::REGISTRY
3743        .iter()
3744        .enumerate()
3745        .filter(|(i, _)| !opt_tog[*i])
3746        .map(|(_, m)| m.keyword)
3747        .collect();
3748    let opt_decorated =
3749        logicaffeine_compile::optimization::decorate_source(&bench.logos_source, &opt_disabled);
3750    let all_opts_on = opt_disabled.is_empty();
3751
3752    // The program's optimization chain as a tree, derived by the crate's
3753    // `relationship_tree` from the baked all-on graph: the fired opts and the
3754    // `requires` enablers they hang under (so `coins`' fired `unchecked`/
3755    // `oraclehints`/`elemtype` show under `oracle`), the BLOCKERS they skipped, and
3756    // the per-program DEPENDENCIES that nest one opt under another it only fired
3757    // because of (dead-code under scalarization, symmetry under partial eval). Map
3758    // the keyword signals back to `Opt` and hand them to the deterministic O(n²)
3759    // derivation — the single source of truth for the menu-tree.
3760    let opt_tree: Vec<logicaffeine_compile::optimization::OptNode> = {
3761        use logicaffeine_compile::optimization::by_keyword;
3762        let fired: Vec<_> = base_fired().iter().filter_map(|kw| by_keyword(kw)).collect();
3763        let preempted: Vec<_> = base_preempted()
3764            .iter()
3765            .filter_map(|(w, l)| Some((by_keyword(w)?, by_keyword(l)?)))
3766            .collect();
3767        let dependencies: Vec<_> = base_dependencies()
3768            .iter()
3769            .filter_map(|(d, x)| Some((by_keyword(d)?, by_keyword(x)?)))
3770            .collect();
3771        logicaffeine_compile::optimization::relationship_tree(&fired, &preempted, &dependencies)
3772    };
3773
3774    // Collapse visibility, parallel to `opt_tree`: walking the pre-order DFS, once
3775    // a collapsed parent is seen every deeper node is hidden until depth returns to
3776    // the parent's level. A single threshold suffices because the order is DFS.
3777    let tree_visible: Vec<bool> = {
3778        let exp = expanded();
3779        let mut vis = Vec::with_capacity(opt_tree.len());
3780        let mut hide_from: Option<usize> = None;
3781        for node in &opt_tree {
3782            if let Some(d) = hide_from {
3783                if node.depth <= d {
3784                    hide_from = None;
3785                }
3786            }
3787            let visible = hide_from.is_none();
3788            if visible && node.has_children && !exp.get(node.opt as usize).copied().unwrap_or(true) {
3789                hide_from = Some(node.depth);
3790            }
3791            vis.push(visible);
3792        }
3793        vis
3794    };
3795
3796    let cache_ok = !bench.generated_rust.trim().is_empty();
3797    let rust_loading = (!all_opts_on || !cache_ok) && (compiling() || live_rust().is_none());
3798    let rust_text: String = if all_opts_on && cache_ok {
3799        bench.generated_rust.clone()
3800    } else {
3801        live_rust().unwrap_or_default()
3802    };
3803    // Use reference_size if it has data, otherwise fall back to the largest benchmarked size
3804    let ref_size = if bench.scaling.contains_key(bench.reference_size.as_str()) {
3805        bench.reference_size.clone()
3806    } else {
3807        bench.sizes.last().cloned().unwrap_or_else(|| bench.reference_size.clone())
3808    };
3809    let ref_timings = bench.scaling.get(ref_size.as_str());
3810
3811    // (label, color, median_ms, tier, is_logos, is_timeout)
3812    let mut chart_entries: Vec<(&str, &str, f64, &str, bool, bool)> = Vec::new();
3813    let ref_timeout = bench.timeouts.get(ref_size.as_str());
3814    if let Some(timings) = ref_timings {
3815        for lang in &data.languages {
3816            // Node/V8 lives in the dedicated interpreter section below, not in the
3817            // compiled-vs-systems-languages charts at the top.
3818            if lang.id == "js" { continue; }
3819            if let Some(t) = timings.get(&lang.id) {
3820                chart_entries.push((
3821                    &lang.label,
3822                    &lang.color,
3823                    t.median_ms,
3824                    &lang.tier,
3825                    lang.id == "logos_release",
3826                    false,
3827                ));
3828            } else if ref_timeout.is_some() {
3829                // Language missing from results at a size that had a timeout — it timed out
3830                chart_entries.push((
3831                    &lang.label,
3832                    &lang.color,
3833                    ref_timeout.unwrap() + 1.0, // sort after everything else
3834                    &lang.tier,
3835                    lang.id == "logos_release",
3836                    true,
3837                ));
3838            }
3839        }
3840    }
3841
3842    chart_entries.sort_by(|a, b| a.2.partial_cmp(&b.2).unwrap_or(std::cmp::Ordering::Equal));
3843
3844    // Split into compiled and interpreted with independent scales (exclude timeouts from max calculation)
3845    let compiled_max = chart_entries.iter()
3846        .filter(|e| e.3 != "interpreted" && !e.5)
3847        .map(|e| e.2)
3848        .max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
3849        .unwrap_or(1.0);
3850
3851    let interpreted_max = chart_entries.iter()
3852        .filter(|e| e.3 == "interpreted" && !e.5)
3853        .map(|e| e.2)
3854        .max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
3855        .unwrap_or(1.0);
3856
3857    let compiled_tier_order = ["systems", "managed", "transpiled"];
3858    let mut compiled_grouped: Vec<(&str, Vec<(&str, &str, f64, bool, bool)>)> = Vec::new();
3859    for &tier in &compiled_tier_order {
3860        let entries: Vec<_> = chart_entries.iter()
3861            .filter(|e| e.3 == tier)
3862            .map(|e| (e.0, e.1, e.2, e.4, e.5))
3863            .collect();
3864        if !entries.is_empty() {
3865            compiled_grouped.push((tier, entries));
3866        }
3867    }
3868
3869    let interpreted_flat: Vec<(&str, &str, f64, bool, bool)> = chart_entries.iter()
3870        .filter(|e| e.3 == "interpreted")
3871        .map(|e| (e.0, e.1, e.2, e.4, e.5))
3872        .collect();
3873
3874    // Stats table entries (all fields, sorted by median; timed-out langs appended at end)
3875    let mut stats_entries: Vec<(&str, &str, Option<&TimingResult>)> = Vec::new();
3876    if let Some(timings) = ref_timings {
3877        for lang in &data.languages {
3878            if lang.id == "js" { continue; }
3879            if let Some(t) = timings.get(&lang.id) {
3880                stats_entries.push((&lang.label, &lang.id, Some(t)));
3881            } else if ref_timeout.is_some() {
3882                stats_entries.push((&lang.label, &lang.id, None));
3883            }
3884        }
3885    }
3886    stats_entries.sort_by(|a, b| {
3887        match (a.2, b.2) {
3888            (Some(ta), Some(tb)) => ta.median_ms.partial_cmp(&tb.median_ms).unwrap_or(std::cmp::Ordering::Equal),
3889            (Some(_), None) => std::cmp::Ordering::Less,
3890            (None, Some(_)) => std::cmp::Ordering::Greater,
3891            (None, None) => std::cmp::Ordering::Equal,
3892        }
3893    });
3894
3895    // Compilation entries sorted by mean_ms
3896    let mut compile_entries: Vec<(&str, f64, f64, bool)> = bench.compilation.iter()
3897        .map(|(name, r)| (name.as_str(), r.mean_ms, r.stddev_ms, name.starts_with("largo")))
3898        .collect();
3899    compile_entries.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
3900
3901    let compile_max = compile_entries.last().map(|e| e.1).unwrap_or(1.0);
3902
3903    // Summary chart entries (geometric mean) sorted by value descending
3904    let mut summary_entries: Vec<(&str, f64, &str, bool)> = Vec::new();
3905    for lang in &data.languages {
3906        if lang.id == "js" { continue; }
3907        if let Some(&val) = data.summary.geometric_mean_speedup_vs_c.get(&lang.id) {
3908            summary_entries.push((&lang.label, val, &lang.color, lang.id == "logos_release"));
3909        }
3910    }
3911    summary_entries.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
3912    let summary_max = summary_entries.first().map(|e| e.1).unwrap_or(1.0);
3913
3914    // Interpreter vs V8, for the active benchmark (at its own calibrated N)
3915    let interp_bench = interp.benchmarks.iter().find(|ib| ib.id == bench.id);
3916    // (label, color, median_ms, is_logos, node_floored)
3917    let mut interp_bars: Vec<(&'static str, &'static str, f64, bool, bool)> = Vec::new();
3918    let mut interp_n = String::new();
3919    let mut interp_engine = String::new();
3920    let mut interp_active_speed: Option<f64> = None;
3921    if let Some(ib) = interp_bench {
3922        interp_n = ib.reference_size.clone();
3923        interp_engine = ib.interpreter_engine.clone();
3924        if let Some(t) = interp_ref(ib) {
3925            // The LOGOS tier ladder (eager VM → tiered VM+JIT → AOT-native, HOTSWAP
3926            // §12/§Axis-3) then the peer runtimes. Data-driven: a tier renders only
3927            // when its row is present, so tiered/AOT appear once the run emits them.
3928            for id in ["logos_interp", "logos_tiered", "logos_aot", "js"] {
3929                if let Some(tr) = t.get(id) {
3930                    let lbl = if id == "js" { "Node / V8" } else { lang_label(id) };
3931                    let col = lang_color(id);
3932                    let is_logos = id.starts_with("logos");
3933                    interp_bars.push((lbl, col, tr.median_ms, is_logos, id == "js" && node_floored(tr)));
3934                }
3935            }
3936            if let (Some(j), Some(l)) = (t.get("js"), t.get("logos_interp")) {
3937                if l.median_ms > 0.0 {
3938                    interp_active_speed = Some(j.median_ms / l.median_ms);
3939                }
3940            }
3941        }
3942    }
3943    interp_bars.sort_by(|a, b| a.2.partial_cmp(&b.2).unwrap_or(std::cmp::Ordering::Equal));
3944    let interp_max = interp_bars.iter().map(|e| e.2).fold(0.0_f64, f64::max).max(1e-9);
3945    if interp_engine.is_empty() { interp_engine = "\u{2014}".to_string(); }
3946    let interp_offfloor = interp.benchmarks.iter().filter(|ib| {
3947        interp_ref(ib).and_then(|t| {
3948            let j = t.get("js")?;
3949            t.get("logos_interp")?;
3950            Some(!node_floored(j))
3951        }).unwrap_or(false)
3952    }).count();
3953    let interp_node_ver = if interp.metadata.node.is_empty() { "Node".to_string() } else { format!("Node {}", interp.metadata.node) };
3954
3955    // Cold-start floor (serverless / CLI): time to launch the engine and run a
3956    // trivial program. Smaller is faster. (label, color, mean_ms, is_logos)
3957    let mut startup_bars: Vec<(&'static str, &'static str, f64, bool)> = Vec::new();
3958    for id in ["logos_interp", "js"] {
3959        if let Some(t) = interp.startup.engines.get(id) {
3960            if t.mean_ms > 0.0 {
3961                let lbl = match id { "logos_interp" => "LOGOS interp", "js" => "Node / V8", _ => id };
3962                let col = match id { "logos_interp" => "#ff8c00", "js" => "#f7df1e", _ => "#94a3b8" };
3963                startup_bars.push((lbl, col, t.mean_ms, id == "logos_interp"));
3964            }
3965        }
3966    }
3967    startup_bars.sort_by(|a, b| a.2.partial_cmp(&b.2).unwrap_or(std::cmp::Ordering::Equal));
3968    let startup_max = startup_bars.iter().map(|e| e.2).fold(0.0_f64, f64::max).max(1e-9);
3969    let startup_logos = interp.startup.engines.get("logos_interp").map(|t| t.mean_ms).unwrap_or(0.0);
3970    let startup_node = interp.startup.engines.get("js").map(|t| t.mean_ms).unwrap_or(0.0);
3971    let startup_vs_v8 = if startup_logos > 0.0 { startup_node / startup_logos } else { 0.0 };
3972
3973    // Engine footprint — what you ship to run a program. (label, color, as_built, stripped, is_logos)
3974    let mut engine_size_bars: Vec<(&'static str, &'static str, f64, Option<f64>, bool)> = Vec::new();
3975    let mut wasm_bundle_bytes = 0.0_f64;
3976    if let Some(es) = &interp.interpreter_sizes {
3977        for id in ["logos", "node", "deno", "bun"] {
3978            if let Some(s) = es.engines.get(id) {
3979                if s.as_built > 0.0 {
3980                    let lbl = match id {
3981                        "logos" => "largo (LOGOS VM+JIT)",
3982                        "node" => "Node / V8",
3983                        "deno" => "Deno",
3984                        "bun" => "Bun",
3985                        _ => id,
3986                    };
3987                    let col = match id { "logos" => "#ff8c00", "node" => "#f7df1e", _ => "#94a3b8" };
3988                    engine_size_bars.push((lbl, col, s.as_built, s.stripped, id == "logos"));
3989                }
3990            }
3991        }
3992        wasm_bundle_bytes = es.wasm_bundle_bytes.unwrap_or(0.0);
3993    }
3994    engine_size_bars.sort_by(|a, b| a.2.partial_cmp(&b.2).unwrap_or(std::cmp::Ordering::Equal));
3995    let engine_size_max = engine_size_bars.iter().map(|e| e.2).fold(0.0_f64, f64::max).max(1.0);
3996    let wasm_bundle_str = if wasm_bundle_bytes > 0.0 { format_bytes(wasm_bundle_bytes) } else { String::new() };
3997
3998    // Source code languages to show (not LOGOS — that's always visible)
3999    let source_langs = ["c", "cpp", "rust", "zig", "go", "java", "js", "python", "ruby", "nim"];
4000
4001    let commit_url = format!("{}/commit/{}", GITHUB_REPO, data.metadata.commit);
4002    let release_url = format!("{}/releases/tag/v{}", GITHUB_REPO, data.metadata.logos_version);
4003    let raw_json_url = format!("{}/blob/main/benchmarks/results/latest.json", GITHUB_REPO);
4004    // Per-tab hero metadata: each section has its own baked measurement provenance.
4005    let solver_meta = &solver_data().expect("gated: the Benchmarks shell loads the bundle first").metadata;
4006    let codec_meta = &codec_data().expect("gated: the Benchmarks shell loads the bundle first").metadata;
4007    let solver_json_url = format!("{}/blob/main/benchmarks/results/solvers.json", GITHUB_REPO);
4008    let codec_json_url = format!("{}/blob/main/benchmarks/results/latest-codec.json", GITHUB_REPO);
4009    let solver_date = solver_meta.date.get(..10).unwrap_or(solver_meta.date.as_str());
4010    let codec_date = codec_meta.date.get(..10).unwrap_or(codec_meta.date.as_str());
4011    let history_url = format!("{}/tree/main/benchmarks/results/history", GITHUB_REPO);
4012    let runsh_url = format!("{}/blob/main/benchmarks/run.sh", GITHUB_REPO);
4013    let bench_dir_url = format!("{}/tree/main/benchmarks", GITHUB_REPO);
4014
4015    rsx! {
4016        PageHead {
4017            title: seo_pages::BENCHMARKS.title,
4018            description: seo_pages::BENCHMARKS.description,
4019            canonical_path: seo_pages::BENCHMARKS.canonical_path,
4020        }
4021        style { "{BENCHMARKS_STYLE}" }
4022        JsonLdMultiple { schemas }
4023
4024        div { class: "bench-container",
4025            MainNav { active: ActivePage::Benchmarks, subtitle: Some("Performance") }
4026
4027            // Hero + Overview
4028            section { class: "bench-hero", id: "overview",
4029                h1 { "Benchmarks" }
4030                if bench_tab() == BenchTab::Language {
4031                    p { "LOGOS compiles to Rust. Rust-level performance, English-level readability." }
4032                    div { class: "bench-pills",
4033                        a { class: "bench-pill", href: "{release_url}", target: "_blank",
4034                            strong { "v{data.metadata.logos_version}" }
4035                        }
4036                        a { class: "bench-pill", href: "{commit_url}", target: "_blank",
4037                            "{data.metadata.commit}"
4038                        }
4039                        span { class: "bench-pill", "{data.metadata.cpu}" }
4040                        span { class: "bench-pill", "{data.metadata.os}" }
4041                        span { class: "bench-pill", "{&data.metadata.date[..10]}" }
4042                        a { class: "bench-pill link", href: "{raw_json_url}", target: "_blank",
4043                            "Raw JSON"
4044                        }
4045                    }
4046                }
4047                if bench_tab() == BenchTab::Solver {
4048                    p { "Certified proofs in milliseconds \u{2014} the same pure-Rust prover that runs in your browser, with no Z3." }
4049                    div { class: "bench-pills",
4050                        if !solver_meta.cpu.is_empty() {
4051                            span { class: "bench-pill", "{solver_meta.cpu}" }
4052                        }
4053                        if !solver_meta.kissat.is_empty() {
4054                            span { class: "bench-pill", "Kissat {solver_meta.kissat}" }
4055                        }
4056                        if !solver_meta.date.is_empty() {
4057                            span { class: "bench-pill", "{solver_date}" }
4058                        }
4059                        a { class: "bench-pill link", href: "{solver_json_url}", target: "_blank",
4060                            "Raw JSON"
4061                        }
4062                    }
4063                }
4064                if bench_tab() == BenchTab::Codec {
4065                    p { "Smallest bytes on the wire \u{2014} the LOGOS codec, head-to-head against the industry serializers." }
4066                    div { class: "bench-pills",
4067                        if !codec_meta.cpu.is_empty() {
4068                            span { class: "bench-pill", "{codec_meta.cpu}" }
4069                        }
4070                        if !codec_meta.os.is_empty() {
4071                            span { class: "bench-pill", "{codec_meta.os}" }
4072                        }
4073                        if !codec_meta.date.is_empty() {
4074                            span { class: "bench-pill", "{codec_date}" }
4075                        }
4076                        a { class: "bench-pill link", href: "{codec_json_url}", target: "_blank",
4077                            "Raw JSON"
4078                        }
4079                    }
4080                }
4081            }
4082
4083            // Top-level tabs: the three benchmark stories.
4084            nav { class: "bench-tabbar",
4085                for t in BenchTab::all() {
4086                    button {
4087                        key: "{t.label()}",
4088                        class: if bench_tab() == t { "bench-tabbar-btn active" } else { "bench-tabbar-btn" },
4089                        onclick: move |_| bench_tab.set(t),
4090                        "{t.label()}"
4091                    }
4092                }
4093            }
4094
4095            // In-page anchor nav for the programming-language sub-sections.
4096            if bench_tab() == BenchTab::Language {
4097                nav { class: "bench-section-nav",
4098                    a { href: "#overview", "Overview" }
4099                    a { href: "#performance", "Performance" }
4100                    a { href: "#interpreter", "Interpreter" }
4101                    a { href: "#source", "Source Code" }
4102                    a { href: "#compilation", "Compilation" }
4103                    a { href: "#summary", "Summary" }
4104                    a { href: "#methodology", "Methodology" }
4105                }
4106            }
4107
4108            if bench_tab() == BenchTab::Language {
4109                div { class: "bench-content",
4110                    // Summary cards — each eyebrow states what is being compared
4111                    div { class: "bench-summary",
4112                        div { class: "bench-summary-card",
4113                            div { class: "bench-summary-eyebrow", "LOGOS compiled vs C" }
4114                            div { class: "bench-summary-value cyan",
4115                                "{logos_vs_c:.2}x"
4116                                sup { "*" }
4117                            }
4118                            div { class: "bench-summary-label", "the speed of C (geomean)" }
4119                        }
4120                        div { class: "bench-summary-card",
4121                            div { class: "bench-summary-eyebrow", "Same algorithm as C" }
4122                            div { class: "bench-summary-value green", "{logos_apples:.2}x" }
4123                            div { class: "bench-summary-label", "the speed of C (geomean)" }
4124                        }
4125                        div { class: "bench-summary-card",
4126                            div { class: "bench-summary-eyebrow", "Interpreted LOGOS vs V8" }
4127                            div { class: "bench-summary-value purple", "{interp_speed:.2}x" }
4128                            div { class: "bench-summary-label", "the speed of V8 (geomean)" }
4129                        }
4130                        if aot_speed > 0.0 {
4131                            div { class: "bench-summary-card",
4132                                div { class: "bench-summary-eyebrow", "AOT-native vs V8" }
4133                                div { class: "bench-summary-value", style: "color:#00d4ff;", "{aot_speed:.2}x" }
4134                                div { class: "bench-summary-label", "the speed of V8, warm (geomean)" }
4135                            }
4136                        }
4137                    }
4138
4139                    div { class: "bench-note",
4140                        "The headline covers all {data.benchmarks.len()} benchmarks. On {collapse_count} of them the LOGOS "
4141                        "compiler reduces the work itself, for example by folding a recursive function into a closed form, so "
4142                        "it runs a faster algorithm than the C version rather than just faster machine code. Those wins are "
4143                        "real, and the generated Rust for each is shown in the Source Code section below. The second number is "
4144                        "the geometric mean over the remaining {apples_count} benchmarks, where LOGOS and C compile the same "
4145                        "algorithm. Both numbers are \u{201c}x the speed of C\u{201d}, so higher is faster."
4146                    }
4147
4148                    // Benchmark tabs (shared across performance, source, compilation)
4149                    div { class: "bench-tabs",
4150                        for (i, b) in data.benchmarks.iter().enumerate() {
4151                            button {
4152                                key: "{i}",
4153                                class: if active_bench() == i { "bench-tab active" } else { "bench-tab" },
4154                                onclick: move |_| {
4155                                    active_bench.set(i);
4156                                    stats_open.set(false);
4157                                    compile_detail_open.set(false);
4158                                    source_open.set([false; 10]);
4159                                    // Reset optimizations to all-on so the new benchmark
4160                                    // shows its cached Rust instantly (no compile on switch).
4161                                    opt_toggles.set(vec![true; logicaffeine_compile::optimization::REGISTRY.len()]);
4162                                    live_rust.set(None);
4163                                    compiling.set(false);
4164                                    base_fired.set(Vec::new());
4165                                    fired_now.set(Vec::new());
4166                                    preempted_now.set(Vec::new());
4167                                    base_preempted.set(Vec::new());
4168                                    base_dependencies.set(Vec::new());
4169                                    expanded.set(vec![true; logicaffeine_compile::optimization::REGISTRY.len()]);
4170                                },
4171                                "{b.name}"
4172                                if collapse_note(&b.id).is_some() {
4173                                    span { class: "bench-tab-badge", title: "Algorithm collapsed by the LOGOS compiler", "\u{26a1}" }
4174                                }
4175                            }
4176                        }
4177                    }
4178
4179                    // =============== PERFORMANCE ===============
4180                    div { class: "bench-section", id: "performance",
4181                        div { class: "bench-section-title", "{bench.name}" }
4182                        div { class: "bench-section-desc",
4183                            "{bench.description} (n = {ref_size})"
4184                        }
4185
4186                        if let Some(note) = collapse_note(&bench.id) {
4187                            div { class: "bench-callout",
4188                                span { class: "bench-callout-icon", "\u{26a1}" }
4189                                span { "{note}" }
4190                            }
4191                        }
4192
4193                        div { class: "bench-chart-hint", "Wall-clock time at n = {ref_size} \u{2014} shorter bar is faster." }
4194
4195                        div { class: "bench-chart",
4196                            for (tier, entries) in compiled_grouped.iter() {
4197                                div { class: "bench-tier-label", "{tier_label(tier)}" }
4198                                for (label, color, median, is_logos, is_timeout) in entries.iter() {
4199                                    {
4200                                        if *is_timeout {
4201                                            let timeout_str = ref_timeout.map(|t| format_timeout(*t)).unwrap_or_else(|| ">timeout".to_string());
4202                                            rsx! {
4203                                                div { class: "bench-bar-row",
4204                                                    div { class: "bench-bar-label", "{label}" }
4205                                                    div { class: "bench-bar-track",
4206                                                        div {
4207                                                            class: "bench-bar-fill",
4208                                                            style: "width: 100%; background: repeating-linear-gradient(45deg, {color}33, {color}33 10px, {color}11 10px, {color}11 20px);",
4209                                                        }
4210                                                    }
4211                                                    span { class: "bench-bar-time-outside", "{timeout_str}" }
4212                                                }
4213                                            }
4214                                        } else {
4215                                            let pct = (*median / compiled_max * 100.0).min(100.0);
4216                                            let time_str = format_time(*median);
4217                                            let show_inside = pct > 15.0;
4218                                            let bar_class = if *is_logos { "bench-bar-fill logos-highlight" } else { "bench-bar-fill" };
4219                                            rsx! {
4220                                                div { class: "bench-bar-row",
4221                                                    div { class: "bench-bar-label", "{label}" }
4222                                                    div { class: "bench-bar-track",
4223                                                        div {
4224                                                            class: "{bar_class}",
4225                                                            style: "width: {pct:.1}%; background: {color};",
4226                                                            if show_inside {
4227                                                                span { class: "bench-bar-time", "{time_str}" }
4228                                                            }
4229                                                        }
4230                                                    }
4231                                                    if !show_inside {
4232                                                        span { class: "bench-bar-time-outside", "{time_str}" }
4233                                                    }
4234                                                }
4235                                            }
4236                                        }
4237                                    }
4238                                }
4239                            }
4240
4241                            if !interpreted_flat.is_empty() {
4242                                div {
4243                                    style: "border-top: 1px solid rgba(255,255,255,0.08); margin: 16px 0 8px; padding-top: 8px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: rgba(229,231,235,0.3);",
4244                                    "Interpreted"
4245                                }
4246                                for (label, color, median, is_logos, is_timeout) in interpreted_flat.iter() {
4247                                    {
4248                                        if *is_timeout {
4249                                            let timeout_str = ref_timeout.map(|t| format_timeout(*t)).unwrap_or_else(|| ">timeout".to_string());
4250                                            rsx! {
4251                                                div { class: "bench-bar-row",
4252                                                    div { class: "bench-bar-label", "{label}" }
4253                                                    div { class: "bench-bar-track",
4254                                                        div {
4255                                                            class: "bench-bar-fill",
4256                                                            style: "width: 100%; background: repeating-linear-gradient(45deg, {color}33, {color}33 10px, {color}11 10px, {color}11 20px);",
4257                                                        }
4258                                                    }
4259                                                    span { class: "bench-bar-time-outside", "{timeout_str}" }
4260                                                }
4261                                            }
4262                                        } else {
4263                                            let pct = (*median / interpreted_max * 100.0).min(100.0);
4264                                            let time_str = format_time(*median);
4265                                            let show_inside = pct > 15.0;
4266                                            let bar_class = if *is_logos { "bench-bar-fill logos-highlight" } else { "bench-bar-fill" };
4267                                            rsx! {
4268                                                div { class: "bench-bar-row",
4269                                                    div { class: "bench-bar-label", "{label}" }
4270                                                    div { class: "bench-bar-track",
4271                                                        div {
4272                                                            class: "{bar_class}",
4273                                                            style: "width: {pct:.1}%; background: {color};",
4274                                                            if show_inside {
4275                                                                span { class: "bench-bar-time", "{time_str}" }
4276                                                            }
4277                                                        }
4278                                                    }
4279                                                    if !show_inside {
4280                                                        span { class: "bench-bar-time-outside", "{time_str}" }
4281                                                    }
4282                                                }
4283                                            }
4284                                        }
4285                                    }
4286                                }
4287                            }
4288                        }
4289
4290                        // Scaling curve — time vs problem size across the benchmarked sizes
4291                        div {
4292                            class: "bench-section-desc",
4293                            style: "margin: 24px 0 6px; color: rgba(229,231,235,0.72); font-weight: 600;",
4294                            "Scaling \u{2014} time vs problem size (log\u{2013}log)"
4295                        }
4296                        {scaling_chart(bench, &data.languages)}
4297
4298                        {complexity_panel(bench, &data.languages)}
4299
4300                        // Peak memory — same style as the runtime bars (lights up after a MEASURE_MEM run)
4301                        if bench.memory.is_some() {
4302                            div {
4303                                class: "bench-section-desc",
4304                                style: "margin: 24px 0 6px; color: rgba(229,231,235,0.72); font-weight: 600;",
4305                                "Memory \u{2014} peak resident set size"
4306                            }
4307                            {memory_bar_chart(bench, &data.languages)}
4308                        }
4309
4310                        // Binary size — compiled-artifact footprint (lights up after a size run)
4311                        if bench.binary_sizes.is_some() {
4312                            div {
4313                                class: "bench-section-desc",
4314                                style: "margin: 24px 0 6px; color: rgba(229,231,235,0.72); font-weight: 600;",
4315                                "Binary size \u{2014} compiled-artifact footprint"
4316                            }
4317                            {binary_size_bar_chart(bench, &data.languages)}
4318                            div { class: "bench-note", style: "margin-top:12px;",
4319                                "The size of the program you actually ship. C and C++ stay tiny because the runtime lives in the system libc; Rust and Go statically link their runtimes; LOGOS compiles to a compact self-contained binary in between. "
4320                                "Java\u{2019}s figure is its bytecode alone \u{2014} it still needs the JVM to run \u{2014} and JavaScript has no compiled artifact at all (its footprint is the V8 engine, in the Interpreter section). "
4321                                "As-built is the real shipped file; stripped removes debug symbols for a code-only comparison."
4322                            }
4323                        }
4324
4325                        // Collapsible: Detailed Statistics
4326                        button {
4327                            class: "bench-collapsible-btn",
4328                            onclick: move |_| stats_open.set(!stats_open()),
4329                            span {
4330                                class: if stats_open() { "bench-collapsible-chevron open" } else { "bench-collapsible-chevron" },
4331                                "\u{25b6}"
4332                            }
4333                            "Detailed Statistics"
4334                        }
4335                        div {
4336                            class: if stats_open() { "bench-collapsible-body open" } else { "bench-collapsible-body" },
4337                            table { class: "bench-stats-table",
4338                                thead {
4339                                    tr {
4340                                        th { "Language" }
4341                                        th { "Mean" }
4342                                        th { "Median" }
4343                                        th { "StdDev" }
4344                                        th { "Min" }
4345                                        th { "Max" }
4346                                        th { "User" }
4347                                        th { "System" }
4348                                        th { "CV" }
4349                                        th { "Runs" }
4350                                    }
4351                                }
4352                                tbody {
4353                                    for (label, lid, maybe_t) in stats_entries.iter() {
4354                                        if let Some(t) = maybe_t {
4355                                            tr {
4356                                                class: if *lid == "logos_release" { "highlight" } else { "" },
4357                                                td { "{label}" }
4358                                                td { "{format_time(t.mean_ms)}" }
4359                                                td { "{format_time(t.median_ms)}" }
4360                                                td { "\u{00b1}{format_time(t.stddev_ms)}" }
4361                                                td { "{format_time(t.min_ms)}" }
4362                                                td { "{format_time(t.max_ms)}" }
4363                                                td { "{t.user_ms.map(|v| format_time(v)).unwrap_or_else(|| \"\u{2014}\".to_string())}" }
4364                                                td { "{t.system_ms.map(|v| format_time(v)).unwrap_or_else(|| \"\u{2014}\".to_string())}" }
4365                                                td { "{t.cv:.3}" }
4366                                                td { "{t.runs}" }
4367                                            }
4368                                        } else {
4369                                            {
4370                                                let timeout_str = ref_timeout.map(|t| format_timeout(*t)).unwrap_or_else(|| ">timeout".to_string());
4371                                                rsx! {
4372                                                    tr {
4373                                                        class: if *lid == "logos_release" { "highlight" } else { "" },
4374                                                        td { "{label}" }
4375                                                        td { "{timeout_str}" }
4376                                                        td { "{timeout_str}" }
4377                                                        td { "\u{2014}" }
4378                                                        td { "\u{2014}" }
4379                                                        td { "\u{2014}" }
4380                                                        td { "\u{2014}" }
4381                                                        td { "\u{2014}" }
4382                                                        td { "\u{2014}" }
4383                                                        td { "\u{2014}" }
4384                                                    }
4385                                                }
4386                                            }
4387                                        }
4388                                    }
4389                                }
4390                            }
4391                        }
4392                    }
4393
4394                    // =============== INTERPRETER vs V8 ===============
4395                    div { class: "bench-section", id: "interpreter",
4396                        div { class: "bench-section-title", "LOGOS vs JavaScript / V8" }
4397                        div { class: "bench-section-desc",
4398                            "The LOGOS engine ladder \u{2014} bytecode VM, copy-and-patch JIT, and the warm AOT-native tier \u{2014} against {interp_node_ver} / V8."
4399                        }
4400
4401                        div { class: "bench-summary", style: "margin-bottom: 20px;",
4402                            div { class: "bench-summary-card",
4403                                div { class: "bench-summary-value cyan", "{startup_vs_v8:.1}x" }
4404                                div { class: "bench-summary-label", "faster cold start than V8" }
4405                            }
4406                            div { class: "bench-summary-card",
4407                                div { class: "bench-summary-value", style: "color:#ff8c00;", "{startup_logos:.1}ms" }
4408                                div { class: "bench-summary-label", "LOGOS interpreter cold start" }
4409                            }
4410                            div { class: "bench-summary-card",
4411                                div { class: "bench-summary-value purple", "{interp_speed:.2}x" }
4412                                div { class: "bench-summary-label", "the speed of V8 on compute (geomean)" }
4413                            }
4414                            if aot_speed > 0.0 {
4415                                div { class: "bench-summary-card",
4416                                    div { class: "bench-summary-value", style: "color:#00d4ff;", "{aot_speed:.2}x" }
4417                                    div { class: "bench-summary-label", "the speed of V8, AOT-native warm (geomean)" }
4418                                }
4419                            }
4420                        }
4421
4422                        // Cold-start chart (serverless / CLI win)
4423                        if !startup_bars.is_empty() {
4424                            div { class: "bench-chart-hint", style: "font-weight:600;color:rgba(229,231,235,0.72);margin-top:4px;",
4425                                "Cold start \u{2014} launch the engine and run a trivial program ({interp.startup.runs} runs, shorter is faster)"
4426                            }
4427                            div { class: "bench-chart",
4428                                for (label, color, mean, is_logos) in startup_bars.iter() {
4429                                    {
4430                                        let pct = (*mean / startup_max * 100.0).min(100.0);
4431                                        let time_str = format_time(*mean);
4432                                        let show_inside = pct > 18.0;
4433                                        let bar_class = if *is_logos { "bench-bar-fill logos-highlight" } else { "bench-bar-fill" };
4434                                        rsx! {
4435                                            div { class: "bench-bar-row",
4436                                                div { class: "bench-bar-label", "{label}" }
4437                                                div { class: "bench-bar-track",
4438                                                    div { class: "{bar_class}", style: "width: {pct:.1}%; background: {color};",
4439                                                        if show_inside { span { class: "bench-bar-time", "{time_str}" } }
4440                                                    }
4441                                                }
4442                                                if !show_inside { span { class: "bench-bar-time-outside", "{time_str}" } }
4443                                            }
4444                                        }
4445                                    }
4446                                }
4447                            }
4448                            div { class: "bench-note", style: "margin-top:14px;margin-bottom:0;",
4449                                "A native binary has no VM to warm up, so the LOGOS interpreter reaches first output in "
4450                                strong { "{startup_logos:.1}ms" }
4451                                " versus V8\u{2019}s {startup_node:.0}ms, about "
4452                                strong { "{startup_vs_v8:.1}x quicker" }
4453                                ", which is what matters for short-lived work like cloud functions, CLI tools, and scripts. "
4454                                "On long-running loops V8\u{2019}s optimizing JIT pulls ahead: the interpreter is competitive on "
4455                                "memory-bound work and behind on heavy compute, a geometric mean of {interp_speed:.2}x the "
4456                                "speed of V8 across {interp_offfloor} benchmarks."
4457                            }
4458                        }
4459
4460                        // Engine size — what you ship to run a program (benchmark-independent, like cold start)
4461                        if !engine_size_bars.is_empty() {
4462                            div { class: "bench-chart-hint", style: "font-weight:600;color:rgba(229,231,235,0.72);margin-top:22px;",
4463                                "Engine size \u{2014} the runtime you ship to execute a program (shorter ships less; stripped, code-only size in parentheses)"
4464                            }
4465                            div { class: "bench-chart",
4466                                for (label, color, bytes, stripped, is_logos) in engine_size_bars.iter() {
4467                                    {
4468                                        let pct = (*bytes / engine_size_max * 100.0).min(100.0);
4469                                        let s = footprint_label(*bytes, *stripped);
4470                                        let show_inside = pct > 32.0;
4471                                        let bar_class = if *is_logos { "bench-bar-fill logos-highlight" } else { "bench-bar-fill" };
4472                                        rsx! {
4473                                            div { class: "bench-bar-row",
4474                                                div { class: "bench-bar-label", "{label}" }
4475                                                div { class: "bench-bar-track",
4476                                                    div { class: "{bar_class}", style: "width: {pct:.1}%; background: {color};",
4477                                                        if show_inside { span { class: "bench-bar-time", "{s}" } }
4478                                                    }
4479                                                }
4480                                                if !show_inside { span { class: "bench-bar-time-outside", "{s}" } }
4481                                            }
4482                                        }
4483                                    }
4484                                }
4485                            }
4486                            div { class: "bench-note", style: "margin-top:14px;",
4487                                if !wasm_bundle_str.is_empty() {
4488                                    "In the browser the whole LOGOS engine ships as a "
4489                                    strong { "{wasm_bundle_str}" }
4490                                    " WebAssembly bundle \u{2014} the same VM+JIT, no native install. "
4491                                }
4492                                "Node\u{2019}s binary bundles V8, libuv, and ICU; largo bundles the transpiler, bytecode VM, and copy-and-patch JIT \u{2014} each is the whole engine you ship to run a program. As-built is the real file; stripped removes debug symbols."
4493                            }
4494                        }
4495
4496                        div { class: "bench-chart-hint", style: "font-weight:600;color:rgba(229,231,235,0.72);margin-top:22px;",
4497                            "{bench.name} (engine: {interp_engine})"
4498                        }
4499
4500                        if bench.id == "ackermann" {
4501                            div { class: "bench-callout",
4502                                span { class: "bench-callout-icon", "\u{26a1}" }
4503                                span { "Interpreted recursion is capped at the shared MAX_CALL_DEPTH (2,500 frames); ackermann\u{2019}s deep self-recursion blows past it, so the interpreter runs it at a reduced m. Deep recursion only completes in compiled mode, where the optimizer collapses it." }
4504                            }
4505                        }
4506
4507                        if interp_bars.is_empty() {
4508                            div { class: "bench-chart-hint", "No interpreter result for {bench.name} (skipped, or not yet supported by the interpreter)." }
4509                        } else {
4510                            div { class: "bench-chart-hint",
4511                                "Wall-clock time at n = {interp_n} \u{2014} shorter is faster."
4512                                if let Some(s) = interp_active_speed {
4513                                    " The interpreter runs at {s:.2}x the speed of V8 here."
4514                                }
4515                            }
4516                            div { class: "bench-chart",
4517                                for (label, color, median, is_logos, _floored) in interp_bars.iter() {
4518                                    {
4519                                        let pct = (*median / interp_max * 100.0).min(100.0);
4520                                        let time_str = format_time(*median);
4521                                        let show_inside = pct > 15.0;
4522                                        let bar_class = if *is_logos { "bench-bar-fill logos-highlight" } else { "bench-bar-fill" };
4523                                        rsx! {
4524                                            div { class: "bench-bar-row",
4525                                                div { class: "bench-bar-label", "{label}" }
4526                                                div { class: "bench-bar-track",
4527                                                    div {
4528                                                        class: "{bar_class}",
4529                                                        style: "width: {pct:.1}%; background: {color};",
4530                                                        if show_inside {
4531                                                            span { class: "bench-bar-time", "{time_str}" }
4532                                                        }
4533                                                    }
4534                                                }
4535                                                if !show_inside {
4536                                                    span { class: "bench-bar-time-outside", "{time_str}" }
4537                                                }
4538                                            }
4539                                        }
4540                                    }
4541                                }
4542                            }
4543                        }
4544                    }
4545
4546                    // =============== SOURCE CODE ===============
4547                    div { class: "bench-section", id: "source",
4548                        div { class: "bench-section-title", "Source Code" }
4549                        div { class: "bench-section-desc",
4550                            "The LOGOS source and the Rust it compiles to. Switch an optimization off and watch its \u{201c}## No <X>\u{201d} decorator appear on the LOGOS source — and the generated Rust recompile live in your browser. With every optimization on you see the cached release build; disabling them all yields plain, boring Rust."
4551                        }
4552
4553                        // Master switch: all optimizations on (cached release Rust) ↔ all
4554                        // off (plain, un-optimized Rust). Both are instant.
4555                        div { class: "bench-opt-master",
4556                            label {
4557                                class: if all_opts_on { "bench-opt-toggle on" } else { "bench-opt-toggle off" },
4558                                input {
4559                                    r#type: "checkbox",
4560                                    checked: all_opts_on,
4561                                    onchange: move |_| {
4562                                        let n = logicaffeine_compile::optimization::REGISTRY.len();
4563                                        let v = if opt_toggles().iter().all(|&b| b) { vec![false; n] } else { vec![true; n] };
4564                                        opt_toggles.set(v);
4565                                        live_rust.set(None);
4566                                    },
4567                                }
4568                                span { "All Optimizations" }
4569                            }
4570                            span { class: "bench-opt-hint",
4571                                if base_fired().is_empty() {
4572                                    "analyzing which optimizations this program uses\u{2026}"
4573                                } else {
4574                                    "{base_fired().len()} of {logicaffeine_compile::optimization::REGISTRY.len()} optimizations fire for this program"
4575                                }
4576                            }
4577                        }
4578
4579                        // The optimization graph for this program, as a collapsible tree:
4580                        // every opt that fires, the `requires`-parents they depend on
4581                        // (an "enabler" that does not itself fire, dashed), and the opts
4582                        // that were SKIPPED because a higher-precedence one claimed them
4583                        // (a greyed "preempted" node — it fires if its winner is turned
4584                        // off). Nested by `requires` depth; turning a parent off cascades
4585                        // its children off, turning a child on pulls its parents on (the
4586                        // registry's own rule, via the compiler's `normalize`). Cyan =
4587                        // firing right now.
4588                        div { class: "bench-opt-toggles",
4589                            for (node, visible) in opt_tree.iter().zip(tree_visible.iter().copied()) {
4590                                if visible {
4591                                    {
4592                                        use logicaffeine_compile::optimization::OptRole;
4593                                        let opt = node.opt;
4594                                        let ri = opt as usize;
4595                                        let m = &logicaffeine_compile::optimization::REGISTRY[ri];
4596                                        let firing = fired_now().contains(&m.keyword);
4597                                        let needs = node.requires.iter().map(|o| o.meta().keyword).collect::<Vec<_>>().join(", ");
4598                                        let depends = node.depends_on.iter().map(|o| o.meta().keyword).collect::<Vec<_>>().join(", ");
4599                                        let blocks = node.preempts.iter().map(|o| o.meta().keyword).collect::<Vec<_>>().join(", ");
4600                                        let blocked_by = node.preempted_by.iter().map(|o| o.meta().keyword).collect::<Vec<_>>().join(", ");
4601                                        let blocks_now = preempted_now().iter()
4602                                            .filter(|(w, _)| *w == m.keyword)
4603                                            .map(|(_, l)| *l)
4604                                            .collect::<Vec<_>>()
4605                                            .join(", ");
4606                                        let cls = if !opt_tog[ri] { "bench-opt-toggle off" }
4607                                                  else if firing { "bench-opt-toggle on firing" }
4608                                                  else { match node.role {
4609                                                      OptRole::Preempted => "bench-opt-toggle on preempted",
4610                                                      OptRole::Enabler => "bench-opt-toggle on enabling",
4611                                                      OptRole::Fired => "bench-opt-toggle on",
4612                                                  } };
4613                                        let row_style = format!("padding-left: {}px;", node.depth * 22);
4614                                        let has_children = node.has_children;
4615                                        let is_expanded = expanded().get(ri).copied().unwrap_or(true);
4616                                        let chevron_cls = if is_expanded { "bench-tree-chevron open" } else { "bench-tree-chevron" };
4617                                        rsx! {
4618                                            div { class: "bench-tree-row", style: "{row_style}",
4619                                                if has_children {
4620                                                    span {
4621                                                        class: "{chevron_cls}",
4622                                                        onclick: move |_| {
4623                                                            let mut e = expanded();
4624                                                            if ri < e.len() { e[ri] = !e[ri]; }
4625                                                            expanded.set(e);
4626                                                        },
4627                                                        "\u{25b6}"
4628                                                    }
4629                                                } else {
4630                                                    span { class: "bench-tree-spacer" }
4631                                                }
4632                                                label { class: "{cls}", title: "{m.group}",
4633                                                    input { r#type: "checkbox", checked: opt_tog[ri],
4634                                                        onchange: move |_| {
4635                                                            let toggles = opt_toggles();
4636                                                            let turning_on = !toggles.get(ri).copied().unwrap_or(false);
4637                                                            let mut cfg = config_from_toggles(&toggles);
4638                                                            if turning_on {
4639                                                                cfg.enable_with_requires(opt);
4640                                                            } else {
4641                                                                cfg.set(opt, false);
4642                                                            }
4643                                                            cfg.normalize();
4644                                                            opt_toggles.set(toggles_from_config(&cfg));
4645                                                            live_rust.set(None);
4646                                                        },
4647                                                    }
4648                                                    span { "{m.label}" }
4649                                                    if node.role == OptRole::Enabler {
4650                                                        span { class: "bench-opt-rel enables", "enabler" }
4651                                                    }
4652                                                    if node.role == OptRole::Preempted && !blocked_by.is_empty() {
4653                                                        span { class: "bench-opt-rel beaten", "blocked by {blocked_by} \u{00b7} fires if off" }
4654                                                    }
4655                                                    if !needs.is_empty() {
4656                                                        span { class: "bench-opt-rel needs", "needs {needs}" }
4657                                                    }
4658                                                    if !depends.is_empty() {
4659                                                        span { class: "bench-opt-rel depends", "depends on {depends}" }
4660                                                    }
4661                                                    if !blocks.is_empty() {
4662                                                        span { class: "bench-opt-rel beats", "blocks {blocks}" }
4663                                                    }
4664                                                    if !blocks_now.is_empty() {
4665                                                        span { class: "bench-opt-rel beats-now", "blocks {blocks_now} now" }
4666                                                    }
4667                                                }
4668                                            }
4669                                        }
4670                                    }
4671                                }
4672                            }
4673                        }
4674
4675                        // LOGOS (with the toggles applied) + Generated Rust side-by-side.
4676                        // All-on shows the cached release Rust instantly; a toggle off
4677                        // shows a spinner while the browser recompiles.
4678                        div { class: "bench-source",
4679                            div { class: "bench-source-panel",
4680                                div { class: "bench-source-header logos", "LOGOS" }
4681                                div { class: "bench-source-code", "{opt_decorated}" }
4682                            }
4683                            div { class: "bench-source-panel",
4684                                div { class: "bench-source-header rust", "Generated Rust" }
4685                                if rust_loading {
4686                                    div { class: "bench-source-code",
4687                                        span { class: "bench-compiling", "Compiling\u{2026}" }
4688                                    }
4689                                } else {
4690                                    div { class: "bench-source-code", "{rust_text}" }
4691                                }
4692                            }
4693                        }
4694
4695                        // Collapsible language source sections
4696                        for (idx, lang_id) in source_langs.iter().enumerate() {
4697                            {
4698                                let src = get_source(bench_sources, lang_id);
4699                                let color = lang_color(lang_id);
4700                                let label = lang_label(lang_id);
4701                                let version = data.metadata.versions.get(*lang_id).map(|s| s.as_str()).unwrap_or("");
4702                                let ext = lang_ext(lang_id);
4703                                let file_url = format!("{}/blob/main/benchmarks/programs/{}/{}", GITHUB_REPO, bench.id, ext);
4704                                let is_open = source_open()[idx];
4705                                rsx! {
4706                                    div { class: "bench-lang-collapsible",
4707                                        div {
4708                                            class: "bench-lang-header",
4709                                            onclick: move |_| {
4710                                                let mut arr = source_open();
4711                                                arr[idx] = !arr[idx];
4712                                                source_open.set(arr);
4713                                            },
4714                                            span {
4715                                                class: "bench-lang-dot",
4716                                                style: "background: {color};",
4717                                            }
4718                                            span { class: "bench-lang-name", "{label}" }
4719                                            span { class: "bench-lang-version", "{version}" }
4720                                            a {
4721                                                class: "bench-lang-link",
4722                                                href: "{file_url}",
4723                                                target: "_blank",
4724                                                onclick: move |e: Event<MouseData>| e.stop_propagation(),
4725                                                "View on GitHub \u{2192}"
4726                                            }
4727                                            span {
4728                                                class: if is_open { "bench-collapsible-chevron open" } else { "bench-collapsible-chevron" },
4729                                                "\u{25b6}"
4730                                            }
4731                                        }
4732                                        div {
4733                                            class: if is_open { "bench-lang-code open" } else { "bench-lang-code" },
4734                                            "{src}"
4735                                        }
4736                                    }
4737                                }
4738                            }
4739                        }
4740                    }
4741
4742                    // =============== COMPILATION ===============
4743                    div { class: "bench-section", id: "compilation",
4744                        div { class: "bench-section-title", "Compilation Times" }
4745                        div { class: "bench-section-desc",
4746                            "Time to compile each benchmark from source, at the same flags used for the runtime numbers. "
4747                            "LOGOS compiles English to Rust, then invokes rustc at full optimization (-O3, fat LTO, "
4748                            "target-cpu=native) \u{2014} so its bar includes the Rust compile."
4749                        }
4750
4751                        div { class: "bench-chart",
4752                            for (name, mean, _stddev, is_largo) in compile_entries.iter() {
4753                                {
4754                                    let pct = (*mean / compile_max * 100.0).min(100.0);
4755                                    let time_str = format_time(*mean);
4756                                    let show_inside = pct > 15.0;
4757                                    let bar_class = if *is_largo { "bench-bar-fill logos-highlight" } else { "bench-bar-fill" };
4758                                    let color = if *is_largo { "#00d4ff" } else { "#6b7280" };
4759                                    let display_name = compiler_label(name);
4760                                    rsx! {
4761                                        div { class: "bench-bar-row",
4762                                            div { class: "bench-bar-label", "{display_name}" }
4763                                            div { class: "bench-bar-track",
4764                                                div {
4765                                                    class: "{bar_class}",
4766                                                    style: "width: {pct:.1}%; background: {color};",
4767                                                    if show_inside {
4768                                                        span { class: "bench-bar-time", "{time_str}" }
4769                                                    }
4770                                                }
4771                                            }
4772                                            if !show_inside {
4773                                                span { class: "bench-bar-time-outside", "{time_str}" }
4774                                            }
4775                                        }
4776                                    }
4777                                }
4778                            }
4779                        }
4780
4781                        // Collapsible: Detailed Compilation Data
4782                        button {
4783                            class: "bench-collapsible-btn",
4784                            onclick: move |_| compile_detail_open.set(!compile_detail_open()),
4785                            span {
4786                                class: if compile_detail_open() { "bench-collapsible-chevron open" } else { "bench-collapsible-chevron" },
4787                                "\u{25b6}"
4788                            }
4789                            "Detailed Compilation Data"
4790                        }
4791                        div {
4792                            class: if compile_detail_open() { "bench-collapsible-body open" } else { "bench-collapsible-body" },
4793                            table { class: "bench-compile-table",
4794                                thead {
4795                                    tr {
4796                                        th { "Compiler" }
4797                                        th { "Mean" }
4798                                        th { "StdDev" }
4799                                    }
4800                                }
4801                                tbody {
4802                                    for (name, mean, stddev, is_largo) in compile_entries.iter() {
4803                                        tr {
4804                                            class: if *is_largo { "highlight" } else { "" },
4805                                            td { class: "compiler-name", "{compiler_label(name)}" }
4806                                            td { "{format_time(*mean)}" }
4807                                            td { "\u{00b1}{format_time(*stddev)}" }
4808                                        }
4809                                    }
4810                                }
4811                            }
4812                        }
4813                    }
4814
4815                    // =============== SUMMARY ===============
4816                    div { class: "bench-section", id: "summary",
4817                        div { class: "bench-section-title", "Cross-Benchmark Summary" }
4818                        div { class: "bench-section-desc", "Geometric-mean speed vs C across all {data.benchmarks.len()} benchmarks (bars proportional to speed; higher is faster)." }
4819
4820                        div { class: "bench-chart",
4821                            for (label, val, color, is_logos) in summary_entries.iter() {
4822                                {
4823                                    // Linear and proportional: the fastest fills the track and every
4824                                    // other bar is its true fraction — 2.5x reads as ~2x the 1.21x bar.
4825                                    let pct = linear_bar_pct(*val, summary_max);
4826
4827                                    let display = if *val >= 0.01 {
4828                                        format!("{:.2}x", val)
4829                                    } else {
4830                                        format!("{:.4}x", val)
4831                                    };
4832                                    let show_inside = pct > 20.0;
4833                                    let bar_class = if *is_logos { "bench-bar-fill logos-highlight" } else { "bench-bar-fill" };
4834                                    rsx! {
4835                                        div { class: "bench-bar-row",
4836                                            div { class: "bench-bar-label", "{label}" }
4837                                            div { class: "bench-bar-track",
4838                                                div {
4839                                                    class: "{bar_class}",
4840                                                    style: "width: {pct:.1}%; background: {color};",
4841                                                    if show_inside {
4842                                                        span { class: "bench-bar-time", "{display}" }
4843                                                    }
4844                                                }
4845                                            }
4846                                            if !show_inside {
4847                                                span { class: "bench-bar-time-outside", "{display}" }
4848                                            }
4849                                        }
4850                                    }
4851                                }
4852                            }
4853                        }
4854                    }
4855
4856                    // =============== METHODOLOGY ===============
4857                    div { class: "bench-section", id: "methodology",
4858                        button {
4859                            class: "bench-collapsible-btn",
4860                            style: "margin-top: 0; border-top: none; padding-top: 0;",
4861                            onclick: move |_| methodology_open.set(!methodology_open()),
4862                            span {
4863                                class: if methodology_open() { "bench-collapsible-chevron open" } else { "bench-collapsible-chevron" },
4864                                "\u{25b6}"
4865                            }
4866                            span { style: "font-size: 18px; font-weight: 700; color: #fff;",
4867                                "Methodology"
4868                            }
4869                        }
4870                        div {
4871                            class: if methodology_open() { "bench-collapsible-body open" } else { "bench-collapsible-body" },
4872                            div { class: "bench-methodology",
4873                                ul {
4874                                    li { "Each benchmark measured with hyperfine ({data.metadata.runs.unwrap_or(20)} runs, {data.metadata.warmup.unwrap_or(5)} warmup); the bars show the median." }
4875                                    li { "CPU: {data.metadata.cpu}." }
4876                                    li { "OS: {data.metadata.os}." }
4877                                    li { "Every implementation runs the same algorithm and produces identical, verified output." }
4878                                    li { "All compiled languages are built at full, matched optimization (see flags below) \u{2014} no language is handicapped relative to LOGOS." }
4879                                    li { "Two geometric means are reported vs C: the headline keeps all {data.benchmarks.len()} benchmarks; the apples-to-apples figure removes the {collapse_count} where the LOGOS compiler collapses the algorithm (\u{26a1}). Every collapse is auditable in the generated Rust per benchmark." }
4880                                    li { "The Interpreter-vs-V8 section is a separate peer comparison (LOGOS bytecode VM + JIT against Node/V8) at interpreter-calibrated sizes, so its n differs from the compiled section." }
4881                                }
4882
4883                                h3 { "Compiler Versions" }
4884                                table { class: "bench-version-table",
4885                                    thead {
4886                                        tr {
4887                                            th { "Language" }
4888                                            th { "Version" }
4889                                        }
4890                                    }
4891                                    tbody {
4892                                        for (lang_id, version) in data.metadata.versions.iter() {
4893                                            tr {
4894                                                td { "{lang_label(lang_id)}" }
4895                                                td { "{version}" }
4896                                            }
4897                                        }
4898                                    }
4899                                }
4900
4901                                h3 { "Compiler Flags" }
4902                                table { class: "bench-version-table",
4903                                    thead {
4904                                        tr {
4905                                            th { "Language" }
4906                                            th { "Flags" }
4907                                        }
4908                                    }
4909                                    tbody {
4910                                        tr { td { "C" } td { "gcc -O3 -march=native -flto -lm" } }
4911                                        tr { td { "C++" } td { "g++ -O3 -march=native -flto -std=c++17" } }
4912                                        tr { td { "Rust" } td { "rustc --edition 2021 -C opt-level=3 -C lto=fat -C codegen-units=1 -C target-cpu=native" } }
4913                                        tr { td { "Zig" } td { "zig build-exe -O ReleaseFast -mcpu native" } }
4914                                        tr { td { "Go" } td { "go build (Go has no -O levels; this is its optimizing release build)" } }
4915                                        tr { td { "Java" } td { "javac, run on the HotSpot JIT" } }
4916                                        tr { td { "Nim" } td { "nim c -d:release --passC:\"-O3 -march=native\"" } }
4917                                        tr { td { "JavaScript" } td { "node (V8 JIT)" } }
4918                                        tr { td { "LOGOS" } td { "largo build --release \u{2192} generated Rust \u{2192} rustc -C opt-level=3 -C lto=fat -C codegen-units=1 -C target-cpu=native" } }
4919                                        tr { td { "LOGOS (interpreted)" } td { "largo run --interpret (bytecode VM + copy-and-patch JIT)" } }
4920                                    }
4921                                }
4922
4923                                h3 { "Links" }
4924                                ul {
4925                                    li {
4926                                        a { href: "{runsh_url}", target: "_blank", "benchmarks/run.sh" }
4927                                        " \u{2014} benchmark runner script"
4928                                    }
4929                                    li {
4930                                        a { href: "{raw_json_url}", target: "_blank", "results/latest.json" }
4931                                        " \u{2014} raw benchmark data"
4932                                    }
4933                                    li {
4934                                        a { href: "{history_url}", target: "_blank", "results/history/" }
4935                                        " \u{2014} historical results by version"
4936                                    }
4937                                    li {
4938                                        a { href: "{bench_dir_url}", target: "_blank", "benchmarks/" }
4939                                        " \u{2014} all benchmark source code"
4940                                    }
4941                                }
4942                            }
4943                        }
4944                    }
4945                }
4946            }
4947            if bench_tab() == BenchTab::Solver {
4948                div { class: "bench-content",
4949                    SolverSection {}
4950                }
4951            }
4952            if bench_tab() == BenchTab::Codec {
4953                div { class: "bench-content",
4954                    CodecSection {}
4955                }
4956            }
4957
4958            Footer {}
4959        }
4960    }
4961}