Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ luxpath's one-page summary. Details live in:

| Date | Change |
|---|---|
| 2026-10-25 | The performance budgets hold on CI: GitHub's Linux runners took 53 to 101 ms for M2's 100 ms case (55 ms on a developer's machine) and failed it at random, so under `CI` each budget is doubled; `cargo xtask ci` prints the timings even when they pass. |
| 2026-10-25 | Findings per requirement: `luxpath check` lists every EN 1838:2024 requirement on every route, area and point with its clause (`luxpath_rules::en1838`), each "cannot verify" until its value is verified (gap 4); scenes gain the area kinds 2024 added (`toilets`, `swimming-pool`, `plant-room`, `local-area`). |
| 2026-10-25 | EN 1838:2024 clause map: `docs/standards-parity.md` cites the 2024 clause of every requirement, from the table of contents in the free SIST preview (values stay unverified, gap 4), and lists what 2024 added: specific areas (5.4), safety signs (6), local area and standby lighting (7), the annexes. New parity entries `en1838.specific-areas`, `en1838.local-area`, `en1838.safety-signs`. |
| 2026-10-22 | Public: the repository opened after a licence check; vulnerability reporting, topics, protected `main` with hosted CI on Linux, macOS and Windows (its first Windows run found a line-ending bug in a test, fixed). |
Expand Down
19 changes: 17 additions & 2 deletions crates/calc/tests/performance.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//! M2's performance budget: 100 luminaires × 10,000 points in under 100 ms, with a realistic table
//! (C every 5°, γ every 1°). Timing means something only in release builds, so this test is
//! ignored by default and `cargo xtask ci` runs it with `--release -- --ignored`.
//!
//! The budgets are for a developer's machine (about 55 ms there). Shared CI machines vary from run to run, from as
//! fast to about twice as slow (53 to 101 ms on GitHub's Linux runners, which failed a fixed 100 ms at random), so
//! under CI each budget is doubled ([`CI_FACTOR`]): a real slowdown of twice or more still fails there.

#![allow(clippy::unwrap_used)]

Expand Down Expand Up @@ -31,6 +35,15 @@ fn scene() -> (Vec<Luminaire>, Grid) {
(luminaires, grid)
}

/// How much slower than a developer's machine a shared CI machine may be.
const CI_FACTOR: u32 = 2;

/// `ms` on a developer's machine; [`CI_FACTOR`] times that where the `CI` variable is set (GitHub Actions sets it).
fn budget(ms: u64) -> Duration {
let ci = std::env::var_os("CI").is_some_and(|v| !v.is_empty() && v != "false");
Duration::from_millis(ms) * if ci { CI_FACTOR } else { 1 }
}

/// The best of five runs of `f`.
fn best_of_five(f: impl Fn() -> Vec<Option<f64>>) -> Duration {
let mut best = Duration::MAX;
Expand All @@ -49,7 +62,8 @@ fn a_hundred_luminaires_over_ten_thousand_points_within_budget() {
let (luminaires, grid) = scene();
let best = best_of_five(|| illuminance(&luminaires, &grid));
eprintln!("100 luminaires × 10,000 points: {best:?} (best of 5)");
assert!(best < Duration::from_millis(100), "{best:?} is over the 100 ms budget");
let limit = budget(100);
assert!(best < limit, "{best:?} is over the {limit:?} budget");
}

#[test]
Expand Down Expand Up @@ -77,5 +91,6 @@ fn walls_stay_within_budget() {
}
let best = best_of_five(|| illuminance_with_walls(&luminaires, &walls, &grid));
eprintln!("100 luminaires × 10,000 points × {} walls: {best:?} (best of 5)", walls.len());
assert!(best < Duration::from_millis(500), "{best:?} is over the 500 ms budget");
let limit = budget(500);
assert!(best < limit, "{best:?} is over the {limit:?} budget");
}
3 changes: 2 additions & 1 deletion xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ fn ci() -> Result<(), String> {
cargo(&["clippy", "--workspace", "--all-targets", "--", "-D", "warnings"])?;
cargo(&["test", "--workspace"])?;
// M2's budget: timing is meaningful only in release.
cargo(&["test", "--release", "-p", "luxpath-calc", "--test", "performance", "--", "--ignored"])?;
// `--nocapture` prints the timings even when they pass, so a budget nearly reached shows in every log.
cargo(&["test", "--release", "-p", "luxpath-calc", "--test", "performance", "--", "--ignored", "--nocapture"])?;
if wasm_target_installed() {
let mut args = vec!["check", "--target", "wasm32-unknown-unknown"];
for krate in WASM_CRATES {
Expand Down
Loading