Skip to content

Conversation

@hanabi1224
Copy link
Contributor

@hanabi1224 hanabi1224 commented Oct 22, 2025

Summary of changes

     Running benches/tipset-validation.rs (target/release/deps/tipset_validation-53fe2cbfabefa755)
Gnuplot not found, using plotters backend
tipset_validation/calibnet@3111900
                        time:   [43.040 ms 43.478 ms 43.912 ms]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild
Benchmarking tipset_validation/mainnet@5427431: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 67.6s, or reduce sample count to 10.
tipset_validation/mainnet@5427431
                        time:   [665.71 ms 670.72 ms 675.52 ms]

Changes introduced in this pull request:

Reference issue to close (if applicable)

Closes

Other information and links

Change checklist

  • I have performed a self-review of my own code,
  • I have made corresponding changes to the documentation. All new code adheres to the team's documentation standards,
  • I have added tests that prove my fix is effective or that my feature works (if possible),
  • I have made sure the CHANGELOG is up-to-date. All user-facing changes should be reflected in this document.

Summary by CodeRabbit

  • Chores
    • Added benchmarking infrastructure and tools for performance testing and validation.
    • Updated build configuration to support new benchmark targets.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

Walkthrough

This PR introduces criterion-based benchmarking infrastructure for tipset validation. It adds a new optional criterion dependency, creates a benchmark-private feature, and implements a tipset-validation benchmark that measures state computation performance using cached snapshots from calibnet and mainnet.

Changes

Cohort / File(s) Summary
Manifest Updates
Cargo.toml
Added criterion as optional dependency, introduced benchmark-private feature, and registered new tipset-validation benchmark target with criterion integration
Benchmark Documentation and Setup
benches/car-index.rs, benches/tipset-validation.rs
Updated car-index documentation to reference benchmark-private feature; added new tipset-validation benchmark file that registers Criterion benchmarks via criterion_group and criterion_main macros
Private Benchmark Module
src/benchmark_private/mod.rs
Introduced new public module with re-exports of forest and cid, and new tipset_validation submodule for benchmarking utilities
Tipset Validation Benchmark Logic
src/benchmark_private/tipset_validation.rs
New benchmark module implementing snapshot download/caching, tipset validation preparation (database, chain config, StateManager initialization), and Criterion benchmarks for calibnet@3111900 and mainnet@5427431
Module Structure
src/lib.rs
Reorganized benchmark_private from inline re-exports to dedicated module file

Sequence Diagram

sequenceDiagram
    participant Criterion as Criterion Benchmark
    participant BTV as bench_tipset_validation()
    participant GS as get_snapshot()
    participant PV as prepare_validation()
    participant V as validate()

    Criterion->>BTV: Initialize tokio runtime
    BTV->>GS: Download snapshot (calibnet/mainnet)
    GS-->>BTV: Return cached snapshot path
    BTV->>PV: Prepare validation (build DB, ChainStore, StateManager)
    PV->>V: Warmup call to compute_tipset_state
    V-->>PV: Warmup complete
    PV-->>BTV: Return StateManager + Tipset
    BTV->>V: Benchmark loop - validate(state_manager, tipset)
    V-->>BTV: compute_tipset_state result
    BTV-->>Criterion: Benchmark metrics
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25–35 minutes

The changes span multiple file types with mixed complexity: manifest and documentation updates are straightforward, while the tipset_validation.rs introduces meaningful logic involving async operations, snapshot management, database construction, and state setup. The coordination across Cargo.toml, new module structure, and the benchmark implementation requires verification of correctness and integration points.

Possibly related PRs

Suggested reviewers

  • akaladarshi
  • LesnyRumcajs
  • sudo-shashank

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "bench: tipset validation" directly and specifically describes the primary change in the changeset. The PR adds a new benchmark for tipset validation, including the necessary infrastructure changes (Criterion dependency, benchmark module, benchmark files). The title uses clear, conventional formatting ("type: feature" pattern) and avoids vague terms or noise. A teammate scanning the repository history would immediately understand that this PR introduces benchmarking for tipset validation.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch hm/bench-tipset-validation

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

@hanabi1224 hanabi1224 force-pushed the hm/bench-tipset-validation branch from 2b5a46a to 83e0353 Compare October 22, 2025 13:07
@hanabi1224 hanabi1224 marked this pull request as ready for review October 22, 2025 13:09
@hanabi1224 hanabi1224 requested a review from a team as a code owner October 22, 2025 13:09
@hanabi1224 hanabi1224 requested review from LesnyRumcajs, elmattic and sudo-shashank and removed request for a team October 22, 2025 13:09
Copy link
Contributor

@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: 0

🧹 Nitpick comments (6)
Cargo.toml (1)

56-56: Unify criterion features across dep and dev-dep to avoid accidental default features.

Right now, [dependencies] sets default-features = false, but [dev-dependencies] likely enables default features implicitly. This can re-enable unwanted transitive features during benches due to feature unification. Recommend disabling default features in dev-deps too and listing only what you need.

Apply this change in dev-dependencies:

-[dev-dependencies]
-criterion = { version = "0.7", features = ["async_tokio", "csv_output"] }
+[dev-dependencies]
+criterion = { version = "0.7", default-features = false, features = ["async_tokio", "csv_output"] }
benches/tipset-validation.rs (1)

4-6: Optional: note about plots to avoid surprise warning.

You may add a hint like “Install gnuplot to enable plot rendering; otherwise plotters backend is used” to align with the observed output.

src/benchmark_private/mod.rs (1)

4-6: Scoped re-exports OK; consider narrowing later.

Re-exporting forest and cid works for benches. Optionally re-export only the items benches require to keep the surface tighter.

src/benchmark_private/tipset_validation.rs (3)

26-33: Limit visibility of CACHE_DIR to avoid leaking bench internals

Make this crate-private; it’s only used inside the crate and doesn’t need to be exposed publicly.

-pub static CACHE_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
+pub(crate) static CACHE_DIR: LazyLock<PathBuf> = LazyLock::new(|| {

65-66: Propagate warmup errors; keep unwrap only in the measured path

Return Result from validate, use ? during warmup, and unwrap inside the Criterion closure to fail fast during measurement without hiding setup errors.

-    // warmup
-    validate(state_manager.clone(), ts.clone()).await;
+    // warmup
+    validate(state_manager.clone(), ts.clone()).await?;
-async fn validate(state_manager: Arc<StateManager<ManyCar>>, ts: Arc<Tipset>) {
-    state_manager
-        .compute_tipset_state(ts, crate::state_manager::NO_CALLBACK, VMTrace::NotTraced)
-        .await
-        .unwrap();
-}
+async fn validate(
+    state_manager: Arc<StateManager<ManyCar>>,
+    ts: Arc<Tipset>,
+) -> anyhow::Result<()> {
+    state_manager
+        .compute_tipset_state(ts, crate::state_manager::NO_CALLBACK, VMTrace::NotTraced)
+        .await?;
+    Ok(())
+}
-            b.to_async(&rt)
-                .iter(|| validate(black_box(state_manager.clone()), black_box(ts.clone())))
+            b.to_async(&rt).iter(|| async {
+                validate(black_box(state_manager.clone()), black_box(ts.clone()))
+                    .await
+                    .unwrap()
+            })
-            b.to_async(&rt)
-                .iter(|| validate(black_box(state_manager.clone()), black_box(ts.clone())))
+            b.to_async(&rt).iter(|| async {
+                validate(black_box(state_manager.clone()), black_box(ts.clone()))
+                    .await
+                    .unwrap()
+            })

Also applies to: 69-74, 94-96, 106-108


18-23: Tune Criterion for mainnet to avoid “100 samples couldn’t complete in 5s”

Split the chained benches so you can dial different settings; reduce sample_size or increase measurement_time for mainnet.

 use criterion::Criterion;
+use std::time::Duration;
-    let mut group = c.benchmark_group("tipset_validation");
-
-    group
-        .bench_function("calibnet@3111900", |b| {
+    let mut group = c.benchmark_group("tipset_validation");
+    group.sample_size(50);
+    group.bench_function("calibnet@3111900", |b| {
             // ...
-        })
-        .bench_function("mainnet@5427431", |b| {
+        });
+
+    // Heavier: fewer samples and longer measurement
+    group.sample_size(10);
+    group.measurement_time(Duration::from_secs(70));
+    group.bench_function("mainnet@5427431", |b| {
             // ...
-        });
+        });

Also applies to: 82-108

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f95dccc and 83e0353.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • Cargo.toml (3 hunks)
  • benches/car-index.rs (1 hunks)
  • benches/tipset-validation.rs (1 hunks)
  • src/benchmark_private/mod.rs (1 hunks)
  • src/benchmark_private/tipset_validation.rs (1 hunks)
  • src/lib.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
benches/tipset-validation.rs (1)
src/benchmark_private/tipset_validation.rs (1)
  • bench_tipset_validation (76-111)
src/benchmark_private/tipset_validation.rs (3)
src/genesis/mod.rs (1)
  • read_genesis_header (21-44)
src/utils/net/download_file.rs (1)
  • download_file_with_cache (30-89)
src/networks/mod.rs (1)
  • from_chain (404-414)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: tests-release
  • GitHub Check: tests
  • GitHub Check: Build forest binaries on Linux AMD64
  • GitHub Check: cargo-publish-dry-run
  • GitHub Check: Build Ubuntu
  • GitHub Check: All lint checks
🔇 Additional comments (7)
benches/car-index.rs (1)

5-5: Doc update matches feature-gated benches.

The invocation reflects the new benchmark-private gating and looks good.

Cargo.toml (2)

301-302: Feature wiring looks correct.

benchmark-private = ["dep:criterion"] cleanly pulls criterion only when needed.


325-329: Bench target registration is set up properly.

harness = false with required-features = ["benchmark-private"] matches the Criterion entry points in benches.

src/lib.rs (1)

100-106: Public gate for benchmark internals is appropriate.

pub mod benchmark_private; behind #[cfg(feature = "benchmark-private")] + #[doc(hidden)] keeps the surface semver-exempt and opt-in. LGTM.

benches/tipset-validation.rs (1)

8-12: Criterion wiring and import path are correct.

criterion_group!/criterion_main! with bench_tipset_validation compiles under the gated module.

src/benchmark_private/tipset_validation.rs (2)

35-37: No action required - NetworkChain Display already outputs correct CDN naming

The NetworkChain enum derives displaydoc::Display using doc comments that are already lowercase ("mainnet", "calibnet", "butterflynet"). The URL construction on line 36 invokes Display via {chain}, which produces the exact lowercase tokens expected by the CDN. No explicit normalization or conversion is necessary.

Likely an incorrect or invalid review comment.


34-43: Verify MD5 support with actual DigitalOcean Spaces snapshot URLs; confirm Resumable is appropriate

Your concern is partially validated:

  1. DigitalOcean Spaces is explicitly supported in HOSTS_WITH_MD5_ETAG (".digitaloceanspaces.com"), and the cache logic extracts MD5 from the etag header. However, if the etag header is missing or unparseable as hex, get_content_md5_hash_from_url returns None, and the cache logic calls bail!() on None, causing a re-run to error rather than gracefully miss.

  2. The DownloadFileOption::Resumable enum variant exists and is valid, so that suggestion is sound for large .car.zst files.

The code assumes DigitalOcean Spaces provides MD5 in the etag header. You should verify this assumption by testing against the actual snapshot URLs to confirm they provide the expected etag format; otherwise, cache hits will fail on subsequent runs.

@elmattic elmattic added this pull request to the merge queue Oct 23, 2025
Merged via the queue into main with commit 8f96137 Oct 23, 2025
40 checks passed
@elmattic elmattic deleted the hm/bench-tipset-validation branch October 23, 2025 22:42
@coderabbitai coderabbitai bot mentioned this pull request Oct 24, 2025
4 tasks
@coderabbitai coderabbitai bot mentioned this pull request Dec 16, 2025
4 tasks
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.

4 participants