Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
11 changes: 11 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ binary(=proptest_delaunay_triangulation)
'''
slow-timeout = { period = "60s", terminate-after = 1 }

[[profile.ci.overrides]]
# This regression deliberately compiles and runs a standalone downstream crate
# in a separate target directory so Cargo feature unification cannot mask the
# serde_json configuration under test. A clean dependency build can cross the
# normal per-test watchdog even though the fixture itself is small.
filter = '''
binary(=checkpoint_downstream)
& test(=downstream_json_without_float_roundtrip_preserves_checkpoint_bits)
'''
slow-timeout = { period = "120s", terminate-after = 1 }

[[profile.ci.overrides]]
# Complete 5D exact SoS expansion can cross the default budget on hosted
# runners. Keep the exception limited to the deterministic co-spherical
Expand Down
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ When in doubt, favor the invariant over the convenient edit.
`Orientation::DEGENERATE`.
- No f64 operation may silently lose sign information. Avoid patterns such as
`unwrap_or(NaN)`, `unwrap_or(f64::INFINITY)`, or "return `true` on error."
- Repository-owned Rust must not use `f64::algebraic_add`,
`f64::algebraic_sub`, `f64::algebraic_mul`, `f64::algebraic_div`, or
`f64::algebraic_rem`. Ordinary IEEE-754 operators and deliberate
`f64::mul_add` remain allowed. Any other relaxed or fast-math facility
requires a separate tracked scientific review before adoption.
- Algorithms cite their source in `REFERENCES.md` and document conditioning
behavior.
- When two predicate implementations answer the same question, property tests
Expand Down
72 changes: 64 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ rustdoc-args = [ "--cfg", "docsrs" ]

[dependencies]
allocation-counter = { version = "0.8.1", optional = true } # for memory profiling
ciborium = { version = "0.2.2", default-features = false }
clap = { version = "4.6.6", features = [ "derive" ], optional = true }
la-stack = { version = "0.4.5", default-features = false, features = [ "exact" ] }
tracing = { version = "0.1.44", default-features = false, features = [ "std" ] }
Expand All @@ -67,6 +68,7 @@ ordered-float = { version = "5.5.0", features = [ "serde" ] }
rand = "0.10.2"
serde = { version = "1.0.229", features = [ "derive" ] }
serde_json = { version = "1.0.151", optional = true }
sha2 = { version = "0.11.0", default-features = false }
same-file = { version = "1.0.6", optional = true }
slotmap = { version = "1.1.1", features = [ "serde" ] }
thiserror = "2.0.20"
Expand Down Expand Up @@ -181,6 +183,11 @@ name = "topology_guarantee_construction"
path = "benches/topology_guarantee_construction.rs"
harness = false

[[bench]]
name = "checkpoint_serialization"
path = "benches/checkpoint_serialization.rs"
harness = false

[lints.rust]
# Per RFC 3389: lint groups must use a lower (more negative) priority so specific
# lints at default priority 0 deterministically override the group level.
Expand Down
9 changes: 9 additions & 0 deletions benches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ allocation checks, or targeted diagnostics.
| Benchmark | Purpose | Scale | Typical Runtime | Used By |
|-----------|---------|-------|-----------------|---------|
| `allocation_hot_paths.rs` | Bootstrap/insert/query/barycenter allocations | Calibrated 2D-5D canaries | ~1-2 min | Manual allocation checks |
| `checkpoint_serialization.rs` | Manifest and JSON checkpoint write/load | 64-vertex 2D owner | <1 min | Checkpoint tuning |
| `ci_performance_suite.rs` | Public workflow regression contract | Calibrated 2D-5D canaries | ~5-10 min | CI, baselines, `just perf-no-regressions` |
| `circumsphere_containment.rs` | Circumsphere predicates and solves | 2D-5D predicates, 3D LU/exact solves | ~5 min | Predicate/circumcenter tuning |
| `cold_path_predicates.rs` | Track predicate paths | Hot, centered, and certified exact cases in 2D-5D | ~2-5 min | Predicate tuning |
Expand All @@ -186,6 +187,7 @@ allocation checks, or targeted diagnostics.
| Use Case | Command |
|----------|---------|
| Final local invariant validation gate | `just ci` |
| Measure checkpoint manifest and JSON write/load paths | `cargo bench --bench checkpoint_serialization --features bench -- --noplot` |
| Quick local large-scale wall-clock guard | `just perf-large-scale-smoke` |
| Fast local PR performance guard with cached same-machine main baseline | `just perf-no-regressions` |
| Compare current branch against a local release/ref baseline | `just perf-vs-ref v0.7.8` |
Expand Down Expand Up @@ -223,6 +225,13 @@ allocation checks, or targeted diagnostics.
| Isolated 32k-vertex 2D Level 4 acceptance run | `DELAUNAY_LARGE_DEBUG_VALIDATION=realization just debug-large-scale-2d 32000` |
| Deep profiling | `cargo bench --profile perf --bench profiling_suite --features count-allocations` |

The checkpoint benchmark uses one deterministic 2D owner because its purpose is
to isolate digest construction and codec overhead, whose dimension-generic
implementation is shared across dimensions. Correctness and exact replay remain
covered separately by the 2D–5D checkpoint tests; expanding the timed matrix
would primarily repeat topology construction cost rather than sharpen this
serialization signal.

## Profiles And Local Guards

Benchmarks that publish or compare performance data use Cargo's `perf` profile:
Expand Down
72 changes: 72 additions & 0 deletions benches/checkpoint_serialization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//! Throughput evidence for scientific checkpoint manifest and wire serialization.

#![forbid(unsafe_code)]

use criterion::{Criterion, Throughput, criterion_group, criterion_main};
use delaunay::prelude::checkpoint::DelaunayCheckpoint;
use delaunay::prelude::construction::{
DelaunayTriangulation, DelaunayTriangulationBuilder, Vertex,
};
use delaunay::prelude::geometry::AdaptiveKernel;
use serde_json::{from_slice, to_vec};
use std::hint::black_box;

#[path = "common/bench_utils.rs"]
mod bench_utils;
use bench_utils::{OrAbort, OrAbortWithContext};

fn representative_triangulation() -> DelaunayTriangulation<AdaptiveKernel<f64>, (), (), 2> {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
let mut vertices = Vec::with_capacity(64);
for row in 0_u32..8 {
for column in 0_u32..8 {
let jitter = f64::from((row * 17 + column * 31) % 11) * 1.0e-4;
vertices.push(
Vertex::try_new([f64::from(column) + jitter, f64::from(row) - jitter]).or_abort(),
);
}
}
DelaunayTriangulationBuilder::new(&vertices)
.build()
.or_abort()
}

fn checkpoint_benches(criterion: &mut Criterion) {
let triangulation = representative_triangulation();
let checkpoint_json = to_vec(&triangulation).or_abort();
let expected_manifest = triangulation.checkpoint_manifest().or_abort();
let checkpoint: DelaunayCheckpoint<(), (), 2> = from_slice(&checkpoint_json).or_abort();
let restored = checkpoint
.try_into_delaunay_with_kernel(AdaptiveKernel::new())
.or_abort();
assert_eq!(restored.checkpoint_manifest().or_abort(), expected_manifest);
restored.validate().or_abort();
restored
.simplices()
.next()
.or_abort("restored checkpoint benchmark must contain a simplex");

let mut group = criterion.benchmark_group("checkpoint_serialization/64_vertices");
group.throughput(Throughput::Elements(64));

group.bench_function("manifest", |bencher| {
bencher.iter(|| black_box(triangulation.checkpoint_manifest()).or_abort());
});
group.bench_function("json", |bencher| {
bencher.iter(|| black_box(to_vec(black_box(&triangulation))).or_abort());
});
group.bench_function("json_load", |bencher| {
bencher.iter(|| {
let checkpoint: DelaunayCheckpoint<(), (), 2> =
from_slice(black_box(&checkpoint_json)).or_abort();
black_box(
checkpoint
.try_into_delaunay_with_kernel(AdaptiveKernel::new())
.or_abort(),
);
});
});
group.finish();
}

criterion_group!(benches, checkpoint_benches);
criterion_main!(benches);
8 changes: 5 additions & 3 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ just update
```

`just update` resolves exact pins under `[dependency-groups].dev` together for
the repository's supported Python version before refreshing `uv.lock`. It does
not change ranged development requirements, runtime or optional dependencies,
or `[build-system].requires` through that exact-pin step. Its
the repository's supported Python version before refreshing `uv.lock`. Its
Cargo update also refreshes the root package and the isolated
`tests/fixtures/checkpoint_no_float_roundtrip/` manifest and lockfile. It does
not change ranged Python development requirements, runtime or optional
dependencies, or `[build-system].requires` through that exact-pin step. Its
`cargo-install-update` preflight runs before either dependency updater can
change declarations or lockfiles.

Expand Down
16 changes: 11 additions & 5 deletions docs/architecture/module_map.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ algorithm machinery that operates on it:
completion, orientation repair, incidence updates, and neighbor maintenance.
Higher proof owners delegate storage edits here.
- `tds/snapshot.rs` - persistence boundary from raw codec records into
validated UUID snapshots before hydration allocates fresh slotmap keys.
validated UUID snapshots before hydration allocates fresh slotmap keys, plus
the owner-borrowed Levels 1–2 evidence required for unchecked snapshot
encoding.
- `tds/validation.rs` - Level 2 Combinatorial Consistency validation and adjacency checks.
- `tds/rollback.rs` - canonical TDS snapshot ownership plus the shared
transaction window used by nested proof refinements without duplicate
Expand Down Expand Up @@ -172,8 +174,12 @@ coordinate model/API rather than loosening ordinary `f64` APIs.
an orthogonal core transformation before Levels 1–4 restoration.
- `repair.rs` - Delaunay repair policies, rebuild config, and repair outcomes.
- `serialization.rs` - versioned owner-level persistence that stores the
canonical `Tds` plus topology guarantee, global topology, and validation
policy, then re-proves Levels 3–5 during restoration.
canonical `Tds` as an embedded CBOR byte image plus topology
guarantee, global topology, validation policy, and a versioned scientific
integrity manifest. It owns bounded envelope parsing, typed load/migration
APIs, canonical UUID-ordered streaming hashes with map-only buffering,
owner-bound reuse of Level-3 f-vector/Euler evidence, and independently
replayed 4D/5D Euclidean construction proof before Levels 3–5 restoration.
- `spherical.rs` - bounded `S^2`/`S^3` construction,
realization-validation, and empty-cap Delaunay backend using the topology
space coordinate/metric backend.
Expand All @@ -186,8 +192,8 @@ coordinate model/API rather than loosening ordinary `f64` APIs.
`src/lib.rs` wires public modules, root re-exports, focused preludes, and the
crate-level documentation map. Public workflow modules are exposed directly as
`delaunay::builder`, `delaunay::construction`, `delaunay::flips`,
`delaunay::incremental_builder`, `delaunay::pachner`, `delaunay::repair`,
`delaunay::validation`, and focused preludes rather than through a nested
`delaunay::checkpoint`, `delaunay::incremental_builder`, `delaunay::pachner`,
`delaunay::repair`, `delaunay::validation`, and focused preludes rather than through a nested
`delaunay::delaunay` facade. The physical
location of `flips` and `pachner` under `src/triangulation/` records that these
operations require only the Levels 1–4 owner.
Expand Down
1 change: 1 addition & 0 deletions docs/architecture/prelude_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ they exercise.
| Unified Pachner move workflow / local topology edits | `use delaunay::prelude::pachner::*` |
| Collection aliases and small buffers | `use delaunay::prelude::collections::*` |
| Construct/configure Euclidean, toroidal, or spherical Delaunay triangulations | `use delaunay::prelude::construction::*` |
| Decode, migrate, inspect, and verify versioned Delaunay checkpoints | `use delaunay::prelude::checkpoint::*` |
| Build, validate, query, or repair generic triangulations | `use delaunay::prelude::triangulation::*` |
| Construction telemetry diagnostics | `use delaunay::prelude::diagnostics::*` |
| Export stable simplicial-complex primitives | `use delaunay::prelude::export::*` |
Expand Down
Loading
Loading