Skip to content

feat(cdt): add simulation output and resumable checkpoints#121

Merged
acgetchell merged 2 commits intomainfrom
feat/60-116-outputs-checkpoints
May 6, 2026
Merged

feat(cdt): add simulation output and resumable checkpoints#121
acgetchell merged 2 commits intomainfrom
feat/60-116-outputs-checkpoints

Conversation

@acgetchell
Copy link
Copy Markdown
Owner

  • Add CSV measurement and JSON summary output paths for configured simulation runs.
  • Add serde-backed CDT triangulation and MCMC checkpoints with validated resume state, preserved RNG streams, and typed checkpoint errors.
  • Add an output-and-checkpoint example with semantic example validation through just examples-validate.
  • Document output files, resumable checkpoints, example validation, and Rust review guidance updates.

Closes #60
Closes #116

- Add CSV measurement and JSON summary output paths for configured simulation runs.
- Add serde-backed CDT triangulation and MCMC checkpoints with validated resume state, preserved RNG streams, and typed checkpoint errors.
- Add an output-and-checkpoint example with semantic example validation through `just examples-validate`.
- Document output files, resumable checkpoints, example validation, and Rust review guidance updates.

Closes #60
Closes #116
@acgetchell acgetchell enabled auto-merge May 6, 2026 21:59
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: ff5ff3ce-6dfe-4cb2-a376-031625660ca6

📥 Commits

Reviewing files that changed from the base of the PR and between 99a7ba9 and 45bc9e0.

📒 Files selected for processing (8)
  • src/cdt/foliation.rs
  • src/cdt/metropolis.rs
  • src/cdt/results.rs
  • src/config.rs
  • src/errors.rs
  • src/geometry/backends/delaunay.rs
  • src/lib.rs
  • tests/cli.rs
🚧 Files skipped from review as they are similar to previous changes (7)
  • tests/cli.rs
  • src/errors.rs
  • src/geometry/backends/delaunay.rs
  • src/lib.rs
  • src/cdt/results.rs
  • src/cdt/metropolis.rs
  • src/config.rs

Walkthrough

Adds serde-backed serialization and checkpointing across CDT types, CSV/JSON output writers, CLI flags for output paths, RNG changes to Xoshiro, new error variants for I/O/checkpointing, example + CI wiring for output/checkpoint validation, and tests exercising serialization and resume semantics.

Changes

Serialization & Output Infrastructure

Layer / File(s) Summary
Dependencies
Cargo.toml
Added/updated deps for serde, serde_json, rand (with serde feature), markov-chain-monte-carlo (serde), dirs, env_logger, float-ord, log, num-traits.
Config shape / CLI wiring
src/config.rs, src/lib.rs
CdtConfig/CdtConfigOverrides derive Serialize/Deserialize and gain output_csv: Option<PathBuf> / output_json: Option<PathBuf>; CLI args exposed and merge-with-override updated; run_simulation updated to write configured outputs and write_configured_outputs helper added.
Core data shape: CDT & MCMC
src/cdt/action.rs, src/cdt/ergodic_moves.rs, src/cdt/foliation.rs, src/cdt/metropolis.rs, src/cdt/triangulation.rs
Many core types now derive Serialize/Deserialize: ActionConfig, MoveType, MoveStatistics (with total_* helpers), ErgodicsSystem, EdgeType, CellType, Foliation (custom Deserialize), MetropolisConfig, MonteCarloStep, SimulationEvent, and new CdtMcmcCheckpoint type with accessors and conversion. RNGs switched from StdRng to Xoshiro256PlusPlus; metropolis acceptance made generic; resume/validation logic added.
Results & output writers
src/cdt/results.rs
Measurement and SimulationResultsBackend derive serde; added write_measurements_csv, write_summary_json, private summary structs, helpers (ensure_parent_directory, output_error, mean_measurement_action), and tests validating CSV/JSON content and aggregation semantics.
Geometry backend serialization
src/geometry/backends/delaunay.rs
Added Serializable wrapper and Serialize/Deserialize impls for DelaunayBackend including conversion scaffolding for global topology and topology guarantees; deserialization validates toroidal periods; tests added.
Errors
src/errors.rs
Extended CdtError with structured variants: OutputWriteFailed, OutputPathResolutionFailed, OutputPathConflict, OutputReadFailed, CheckpointSerializationFailed, CheckpointResumeFailed and corresponding tests.
Examples & CI/tooling
examples/output_and_checkpoint.rs, scripts/run_all_examples.sh, justfile
New example demonstrating CSV/JSON outputs and checkpoint roundtrip; CI validation target renamed examples-validate and example wired into validation markers.
Tests & integration
tests/cli.rs, tests/integration_tests.rs, various src/* tests
CLI integration test for configured outputs; tests for checkpoint roundtrip and resume-failure modes; parameterized toroidal test constants; multiple unit/integration tests added/updated across modules.
Docs & minor guidance
AGENTS.md, docs/dev/*.md, docs/code_organization.md, README.md
Documented new features, added Rust error-handling and import-hygiene guidance, updated commands/docs to use examples-validate, and listed new example file.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant CLI as CLI
    participant Sim as Simulation
    participant MCMC as MCMC_Engine
    participant Serializer as Serializer
    participant FS as FileIO

    User->>CLI: invoke run_simulation (--output-csv/--output-json)
    CLI->>Sim: build CDT (or run Metropolis)
    Sim->>MCMC: run iterations / resume from checkpoint
    MCMC->>Sim: return steps, measurements, move stats
    Sim->>Serializer: prepare measurement CSV and JSON summary
    Serializer->>FS: write CSV (if configured)
    Serializer->>FS: write JSON (if configured)
    FS-->>CLI: files persisted / errors reported
    CLI-->>User: return SimulationResultsBackend (or error)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
I serialized a triangulation bright,
Wrote CSV rows through the night,
Saved RNG seeds for the next run's start,
Checkpoints tucked in JSON heart,
Hop on—resume the science art!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding simulation output (CSV/JSON) and resumable checkpoints, which aligns with the primary objectives of the PR.
Description check ✅ Passed The description is directly related to the changeset, covering CSV/JSON output paths, serde-backed checkpoints, example validation, and documentation updates that match the code changes.
Linked Issues check ✅ Passed The PR comprehensively implements requirements from both linked issues: #60 adds CSV/JSON output with serde derives for measurement types and CLI flags; #116 adds serde support for CDT triangulations, checkpoint validation, RNG preservation, and comprehensive testing.
Out of Scope Changes check ✅ Passed All code changes align with the stated objectives: output serialization, checkpoint support, example validation tooling, and documentation updates. No unrelated changes detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/60-116-outputs-checkpoints

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@acgetchell acgetchell self-assigned this May 6, 2026
@acgetchell acgetchell added this to the v0.1.0 milestone May 6, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 86.48649% with 145 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.82%. Comparing base (8346580) to head (99a7ba9).

Files with missing lines Patch % Lines
src/cdt/metropolis.rs 81.00% 121 Missing ⚠️
src/geometry/backends/delaunay.rs 82.85% 12 Missing ⚠️
src/cdt/results.rs 94.92% 7 Missing ⚠️
src/errors.rs 93.33% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #121      +/-   ##
==========================================
- Coverage   92.52%   91.82%   -0.71%     
==========================================
  Files          19       19              
  Lines        8661     9642     +981     
==========================================
+ Hits         8014     8854     +840     
- Misses        647      788     +141     
Flag Coverage Δ
unittests 91.82% <86.48%> (-0.71%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

🔴 Performance Regression Detected

Performance Analysis Report

CDT Performance Analysis Report

Generated: 2026-05-06T22:08:27+00:00

Summary

  • Total benchmarks: 44
  • Regressions: 14
  • Improvements: 13
  • Stable: 12
  • New benchmarks: 5
  • Average change: -2.6%
  • Median change: 0.3%

🔴 Performance Regressions

Benchmark Change Current Baseline Ratio
simulation_analysis/acceptance_rate +142.4% 6.6ns 2.7ns 2.42x
edge_counting/uncached/200 +31.4% 9.3µs 7.1µs 1.31x
edge_counting/uncached/10 +31.1% 377.0ns 287.6ns 1.31x
edge_counting/uncached/50 +30.6% 2.1µs 1.6µs 1.31x
simulation_analysis/average_action +29.1% 3.2ns 2.5ns 1.29x
edge_counting/uncached/100 +28.5% 4.3µs 3.4µs 1.29x
edge_counting/uncached/25 +26.3% 953.5ns 755.2ns 1.26x
ergodic_moves/move/Move31Remove +20.7% 7.4µs 6.1µs 1.21x
geometry_queries/euler_characteristic +20.3% 2.0µs 1.7µs 1.20x
ergodic_moves/random_move_attempt +18.3% 8.2µs 6.9µs 1.18x
ergodic_moves/move/Move22 +15.6% 8.1µs 7.0µs 1.16x
ergodic_moves/move/EdgeFlip +15.5% 8.1µs 7.0µs 1.16x
ergodic_moves/move/Move13Add +15.3% 7.8µs 6.7µs 1.15x
metropolis_simulation/metropolis_steps/50 +13.1% 4.2ms 3.7ms 1.13x

🟢 Performance Improvements

Benchmark Change Current Baseline Ratio
ergodic_moves/random_move_selection -94.0% 4.1ns 69.0ns 16.78x
geometry_queries/iterate_faces -52.7% 91.0ns 192.4ns 2.11x
geometry_queries/iterate_vertices -50.2% 60.7ns 121.8ns 2.01x
geometry_queries/face_count -42.1% 0.3ns 0.5ns 1.73x
edge_counting/cached/25 -42.1% 0.3ns 0.5ns 1.73x
edge_counting/cached/200 -42.1% 0.3ns 0.5ns 1.73x
geometry_queries/vertex_count -42.0% 0.3ns 0.5ns 1.73x
edge_counting/cached/50 -42.0% 0.3ns 0.5ns 1.72x
edge_counting/cached/10 -41.9% 0.3ns 0.5ns 1.72x
edge_counting/cached/100 -41.9% 0.3ns 0.5ns 1.72x
simulation_analysis/equilibrium_measurements -21.5% 20.9ns 26.6ns 1.27x
geometry_queries/iterate_edges -14.1% 2.3µs 2.7µs 1.16x
geometry_queries/is_valid -10.2% 222.9µs 248.3µs 1.11x

🆕 New Benchmarks

  • cache_operations/metadata_cache_invalidation: 123.6ns
  • simulation_analysis/hausdorff_dimension_estimate: 7.1µs
  • simulation_analysis/average_volume_profile: 77.4ns
  • simulation_analysis/volume_fluctuations: 143.5ns
  • simulation_analysis/spectral_dimension_estimate: 46.5µs

✅ Stable Benchmarks

No significant changes detected in 12 benchmarks.

⚠️ This PR introduces performance regressions that exceed the threshold. Please review the changes.


Performance analysis powered by Criterion.rs

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cdt/foliation.rs (1)

339-345: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate Foliation during deserialization.

Deriving Deserialize here bypasses Foliation::from_slice_sizes(), so inputs like a mismatched num_slices or an empty slice can now construct a Foliation value that the public constructor explicitly rejects. For checkpoint/resume state, this should fail at the serde boundary instead of leaking an invalid public state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cdt/foliation.rs` around lines 339 - 345, The derived Deserialize for
struct Foliation allows invalid states to be created; replace the auto-derived
Deserialize with a custom impl that validates inputs (e.g., ensure slice_sizes
is non-empty and that the provided num_slices matches slice_sizes.len()) by
either calling the public constructor Foliation::from_slice_sizes(slice_sizes)
inside deserialization or performing the same checks and returning an error on
mismatch so invalid checkpoint/resume data fails at the serde boundary.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cdt/ergodic_moves.rs`:
- Around line 16-17: The code imports rand::rngs::Xoshiro256PlusPlus which isn’t
re-exported by rand 0.10.1; either add the rand_xoshiro crate to Cargo.toml and
change the import to use rand_xoshiro::Xoshiro256PlusPlus (keeping
SeedableRng/RngExt usage), or replace all Xoshiro256PlusPlus usages with a
rand-provided RNG such as StdRng and update the imports (e.g., use
rand::rngs::StdRng) as used in the functions/blocks referencing
Xoshiro256PlusPlus (search for the Xoshiro256PlusPlus symbol and the
SeedableRng/RngExt uses around the ergodic_moves logic) so the code compiles
without missing-reexport errors.

In `@src/cdt/metropolis.rs`:
- Line 1042: The struct initializer currently reserves capacity for steps using
Vec::with_capacity(usize::try_from(self.config.steps).unwrap_or(0)), which can
pre-allocate a huge buffer and cause OOM; change the initialization of steps to
avoid reserving the full self.config.steps up front (use Vec::new() or a small
heuristic like min(self.config.steps as usize, 16)) in the
constructor/initializer where steps is set so the Step history grows
incrementally instead of allocating based on self.config.steps.

In `@src/cdt/results.rs`:
- Around line 138-139: The Summary struct currently hardcodes steps: &'a
[MonteCarloStep] and measurements: &'a [Measurement]; change both to optional
types (e.g., Option<&'a [MonteCarloStep]> and Option<&'a [Measurement]>) and add
serde attributes like #[serde(skip_serializing_if = "Option::is_none")] to those
fields so they are omitted from the JSON when None; update any constructors or
places that build the Summary (functions creating the Summary) to pass
Some(slice) when full telemetry is desired or None when emitting a lightweight
manifest, and adjust any consumers that iterate these fields to handle the
Option (unwrap_or(&[]) or pattern-match) accordingly.
- Around line 598-605: The aggregate.average_action currently calls
self.average_action() which includes the step-0 snapshot and pre-thermalization
measurements, biasing the result when thermalization_steps > 0; update the
call/site so that average_action uses only equilibrium measurements (i.e. skip
the first snapshot and all measurements before self.thermalization_steps),
either by adding a skip/offset parameter to average_action (e.g.
average_action(skip=self.thermalization_steps)) or by adding a new method that
computes the mean from measurements[self.thermalization_steps..], and replace
the call here so average_action is consistent with how average_volume_profile
and other volume aggregates already exclude warmup samples.

In `@src/config.rs`:
- Around line 27-28: The serde serialization for the enum CdtTopology currently
uses default variant names (PascalCase) which differs from clap::ValueEnum's
kebab-case, breaking round-tripping; add the serde attribute to unify them by
annotating the CdtTopology enum with #[serde(rename_all = "kebab-case")] so
serialized JSON uses the same kebab-case vocabulary as the CLI (affecting places
that serialize CdtTopology such as output_json and CdtConfigOverrides).

In `@src/geometry/backends/delaunay.rs`:
- Around line 111-130: into_global_topology() currently only verifies domain
length for SerializableGlobalTopology::Toroidal but must also reject NaN,
infinite, or non-positive periods; update the Toroidal branch in
into_global_topology<const D: usize, E: DeError> to, after converting domain
into [f64; D], iterate the array and validate each element is finite
(f.is_finite()) and > 0.0, returning Err(E::custom(...)) on the first offending
index/value with a clear message like "invalid toroidal period at index i:
value" so bad checkpoints fail deserialization instead of later panicking or
producing invalid topology.
- Around line 173-205: The Serialize and Deserialize impls for DelaunayBackend
must include explicit serde trait bounds for the triangulation Tds type because
SerializedDelaunayBackend::serialize()/deserialize() require them; update the
impl headers for DelaunayBackend<VertexData, CellData, D> (the impl Serialize
and impl<'de> Deserialize<'de>) to add where clauses requiring Tds<f64,
VertexData, CellData, D>: Serialize (for Serialize impl) and Tds<f64,
VertexData, CellData, D>: Deserialize<'de> (for Deserialize impl), and any
equivalent bounds on VertexData and CellData if needed so that calling
SerializedDelaunayBackend::serialize()/deserialize() compiles. Ensure the
changes reference the same generic parameters used in the current impls
(DelaunayBackend, VertexData, CellData, const D).

In `@src/lib.rs`:
- Around line 518-527: Pre-resolve both config.output_csv and config.output_json
using CdtConfig::resolve_path with base_dir, compare the resulting PathBufs for
equality, and if they are identical return an Err (or exit early) with a clear
error before calling results.write_measurements_csv or
results.write_summary_json; update the block around config.output_csv /
config.output_json to perform this preflight equality check and abort before any
file is written so one artifact cannot be silently overwritten.

In `@tests/cli.rs`:
- Around line 17-23: The temp_output_dir helper (and the similar test helpers in
the test modules in src/lib.rs and src/cdt/results.rs) uses
thread::current().name().unwrap_or("test") directly in a filename which can
contain ':' on Rust test thread names and break Windows paths; update these
helpers (e.g., temp_output_dir) to sanitize the thread name before joining into
the PathBuf by mapping invalid filename characters (at minimum ':' → '_', and
ideally other OS-invalid chars) to safe replacements and use the sanitized
string in the format! call so test-generated temp directories are cross-platform
safe.

---

Outside diff comments:
In `@src/cdt/foliation.rs`:
- Around line 339-345: The derived Deserialize for struct Foliation allows
invalid states to be created; replace the auto-derived Deserialize with a custom
impl that validates inputs (e.g., ensure slice_sizes is non-empty and that the
provided num_slices matches slice_sizes.len()) by either calling the public
constructor Foliation::from_slice_sizes(slice_sizes) inside deserialization or
performing the same checks and returning an error on mismatch so invalid
checkpoint/resume data fails at the serde boundary.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: aba7fd83-8e84-4b0b-9f13-f39cd4b6768b

📥 Commits

Reviewing files that changed from the base of the PR and between 8346580 and 99a7ba9.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (23)
  • AGENTS.md
  • Cargo.toml
  • README.md
  • docs/code_organization.md
  • docs/dev/commands.md
  • docs/dev/rust.md
  • docs/dev/testing.md
  • docs/dev/tooling-alignment.md
  • examples/output_and_checkpoint.rs
  • justfile
  • scripts/run_all_examples.sh
  • src/cdt/action.rs
  • src/cdt/ergodic_moves.rs
  • src/cdt/foliation.rs
  • src/cdt/metropolis.rs
  • src/cdt/results.rs
  • src/cdt/triangulation.rs
  • src/config.rs
  • src/errors.rs
  • src/geometry/backends/delaunay.rs
  • src/lib.rs
  • tests/cli.rs
  • tests/integration_tests.rs

Comment thread src/cdt/ergodic_moves.rs
Comment on lines +16 to +17
use rand::{RngExt, SeedableRng, rngs::Xoshiro256PlusPlus};
use serde::{Deserialize, Serialize};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, check the Cargo.toml for rand version and any rand_xoshiro dependency
fd -t f Cargo.toml | head -1 | xargs cat | grep -A 5 "rand\|xoshiro" | head -20

Repository: acgetchell/causal-triangulations

Length of output: 251


🏁 Script executed:

# Check the full ergodic_moves.rs file to see the actual imports and usage
head -50 src/cdt/ergodic_moves.rs

Repository: acgetchell/causal-triangulations

Length of output: 1936


🏁 Script executed:

# Also check lines around 239-245, 284-288, 665-669 to see the usage context
sed -n '235,250p; 280,295p; 660,675p' src/cdt/ergodic_moves.rs

Repository: acgetchell/causal-triangulations

Length of output: 1268


Add rand_xoshiro as a dependency or switch to a RNG type provided by rand.

The code imports rand::rngs::Xoshiro256PlusPlus, but rand 0.10.1 does not re-export Xoshiro types. Either add rand_xoshiro to Cargo.toml and use use rand_xoshiro::Xoshiro256PlusPlus;, or replace the RNG with one that rand provides directly (e.g., StdRng). This applies to all usages at lines 16, 239–245, 284–288, and 665–669.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cdt/ergodic_moves.rs` around lines 16 - 17, The code imports
rand::rngs::Xoshiro256PlusPlus which isn’t re-exported by rand 0.10.1; either
add the rand_xoshiro crate to Cargo.toml and change the import to use
rand_xoshiro::Xoshiro256PlusPlus (keeping SeedableRng/RngExt usage), or replace
all Xoshiro256PlusPlus usages with a rand-provided RNG such as StdRng and update
the imports (e.g., use rand::rngs::StdRng) as used in the functions/blocks
referencing Xoshiro256PlusPlus (search for the Xoshiro256PlusPlus symbol and the
SeedableRng/RngExt uses around the ergodic_moves logic) so the code compiles
without missing-reexport errors.

Comment thread src/cdt/metropolis.rs Outdated
Comment thread src/cdt/results.rs
Comment on lines +138 to +139
steps: &'a [MonteCarloStep],
measurements: &'a [Measurement],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Make the large telemetry arrays optional in the JSON summary.

Issue #60 called for the full measurement array to be optional, but this schema hardwires both steps and measurements into every summary. On long simulations that turns the “summary” file into a second full-data export and removes any way to emit a lightweight run manifest.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cdt/results.rs` around lines 138 - 139, The Summary struct currently
hardcodes steps: &'a [MonteCarloStep] and measurements: &'a [Measurement];
change both to optional types (e.g., Option<&'a [MonteCarloStep]> and Option<&'a
[Measurement]>) and add serde attributes like #[serde(skip_serializing_if =
"Option::is_none")] to those fields so they are omitted from the JSON when None;
update any constructors or places that build the Summary (functions creating the
Summary) to pass Some(slice) when full telemetry is desired or None when
emitting a lightweight manifest, and adjust any consumers that iterate these
fields to handle the Option (unwrap_or(&[]) or pattern-match) accordingly.

Comment thread src/cdt/results.rs
Comment thread src/config.rs
Comment thread src/geometry/backends/delaunay.rs
Comment thread src/geometry/backends/delaunay.rs
Comment thread src/lib.rs Outdated
Comment thread tests/cli.rs
- Reject invalid checkpoint state at serde boundaries, including empty foliation bookkeeping and invalid toroidal periods.
- Prevent CSV and JSON outputs from resolving to the same file before writing either artifact.
- Align serialized topology names with CLI vocabulary and report equilibrium-only average action in JSON summaries.
- Avoid preallocating simulation step history from the full configured step count.

Closes #60
Closes #116
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

🔴 Performance Regression Detected

Performance Analysis Report

CDT Performance Analysis Report

Generated: 2026-05-06T23:39:19+00:00

Summary

  • Total benchmarks: 44
  • Regressions: 33
  • Improvements: 5
  • Stable: 1
  • New benchmarks: 5
  • Average change: 14.8%
  • Median change: 15.4%

🔴 Performance Regressions

Benchmark Change Current Baseline Ratio
action_calculations/calculate_action/50 +54.6% 7.6ns 4.9ns 1.55x
ergodic_moves/move/Move31Remove +45.8% 8.9µs 6.1µs 1.46x
ergodic_moves/random_move_attempt +40.1% 9.7µs 6.9µs 1.40x
ergodic_moves/move/Move13Add +37.8% 9.3µs 6.7µs 1.38x
action_calculations/calculate_action/10 +35.8% 6.7ns 4.9ns 1.36x
ergodic_moves/move/Move22 +34.5% 9.4µs 7.0µs 1.35x
edge_counting/uncached/25 +34.0% 1.0µs 755.2ns 1.34x
ergodic_moves/move/EdgeFlip +33.5% 9.3µs 7.0µs 1.34x
edge_counting/uncached/50 +31.1% 2.1µs 1.6µs 1.31x
metropolis_simulation/metropolis_steps/50 +28.3% 4.8ms 3.7ms 1.28x
edge_counting/uncached/100 +27.2% 4.3µs 3.4µs 1.27x
simulation_analysis/average_action +27.0% 3.1ns 2.5ns 1.27x
edge_counting/uncached/10 +24.7% 358.6ns 287.6ns 1.25x
action_calculations/calculate_action/100 +23.6% 6.1ns 4.9ns 1.24x
edge_counting/uncached/200 +23.1% 8.7µs 7.1µs 1.23x
geometry_queries/euler_characteristic +22.3% 2.0µs 1.7µs 1.22x
triangulation_creation/delaunay_backend/5 +22.3% 70.0µs 57.3µs 1.22x
triangulation_creation/delaunay_backend/10 +18.5% 379.8µs 320.4µs 1.19x
geometry_queries/is_valid +15.6% 287.0µs 248.3µs 1.16x
metropolis_simulation/metropolis_steps/100 +15.4% 11.0ms 9.5ms 1.15x
triangulation_creation/delaunay_backend/20 +14.7% 1.5ms 1.3ms 1.15x
edge_counting/cached/100 +14.2% 0.6ns 0.5ns 1.14x
edge_counting/cached/200 +14.2% 0.6ns 0.5ns 1.14x
edge_counting/cached/50 +14.2% 0.6ns 0.5ns 1.14x
geometry_queries/vertex_count +14.2% 0.6ns 0.5ns 1.14x
edge_counting/cached/10 +14.1% 0.6ns 0.5ns 1.14x
edge_counting/cached/25 +14.1% 0.6ns 0.5ns 1.14x
geometry_queries/face_count +14.0% 0.6ns 0.5ns 1.14x
metropolis_simulation/metropolis_steps/10 +13.5% 1.8ms 1.6ms 1.13x
triangulation_creation/delaunay_backend/100 +12.8% 32.0ms 28.4ms 1.13x
triangulation_creation/delaunay_backend/50 +12.8% 8.7ms 7.7ms 1.13x
validation/validate +12.4% 366.8µs 326.4µs 1.12x
cache_operations/refresh_cache +12.3% 8.7ms 7.8ms 1.12x

🟢 Performance Improvements

Benchmark Change Current Baseline Ratio
ergodic_moves/random_move_selection -93.6% 4.4ns 69.0ns 15.64x
geometry_queries/iterate_vertices -49.6% 61.4ns 121.8ns 1.98x
geometry_queries/iterate_faces -32.7% 129.5ns 192.4ns 1.49x
geometry_queries/iterate_edges -10.7% 2.4µs 2.7µs 1.12x
simulation_analysis/equilibrium_measurements -10.5% 23.8ns 26.6ns 1.12x

🆕 New Benchmarks

  • cache_operations/metadata_cache_invalidation: 178.4ns
  • simulation_analysis/hausdorff_dimension_estimate: 6.2µs
  • simulation_analysis/average_volume_profile: 78.4ns
  • simulation_analysis/volume_fluctuations: 123.5ns
  • simulation_analysis/spectral_dimension_estimate: 38.1µs

✅ Stable Benchmarks

No significant changes detected in 1 benchmarks.

⚠️ This PR introduces performance regressions that exceed the threshold. Please review the changes.


Performance analysis powered by Criterion.rs

@acgetchell acgetchell disabled auto-merge May 6, 2026 23:40
@acgetchell acgetchell merged commit b854261 into main May 6, 2026
14 checks passed
@acgetchell acgetchell deleted the feat/60-116-outputs-checkpoints branch May 6, 2026 23:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add serde checkpoint support for CDT triangulations Serialize and save simulation results (CSV/JSON output)

1 participant