Skip to content

Commit 1c83f3c

Browse files
authored
Merge branch 'main' into feat/private-input-v2
2 parents 4b85658 + d706420 commit 1c83f3c

7 files changed

Lines changed: 387 additions & 6 deletions

File tree

bin/cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ tikv-jemalloc-ctl = { version = "0.6", features = ["stats"], optional = true }
1414

1515
[features]
1616
jemalloc-stats = ["dep:tikv-jemalloc-ctl"]
17-
instruments = ["prover/instruments"]
17+
instruments = ["prover/instruments", "stark/instruments"]

bin/cli/src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,12 @@ fn cmd_prove(
346346
#[cfg(feature = "jemalloc-stats")]
347347
let tracker = heap_tracker::HeapTracker::start();
348348

349+
#[cfg(all(feature = "jemalloc-stats", feature = "instruments"))]
350+
stark::instruments::set_heap_reader(|| {
351+
tikv_jemalloc_ctl::epoch::advance().ok();
352+
tikv_jemalloc_ctl::stats::allocated::read().ok()
353+
});
354+
349355
let start = Instant::now();
350356
let proof = match blowup {
351357
Some(b) => {

crypto/stark/src/instruments.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
11
use std::cell::RefCell;
2+
use std::sync::OnceLock;
23
use std::sync::atomic::{AtomicU64, Ordering};
34
use std::time::Duration;
45

6+
static HEAP_READER: OnceLock<fn() -> Option<usize>> = OnceLock::new();
7+
8+
pub fn set_heap_reader(f: fn() -> Option<usize>) {
9+
let _ = HEAP_READER.set(f);
10+
}
11+
12+
pub fn heap_bytes() -> Option<usize> {
13+
HEAP_READER.get().and_then(|f| f())
14+
}
15+
16+
pub type HeapSnapshot = (&'static str, usize);
17+
18+
pub fn snap(label: &'static str) -> Option<HeapSnapshot> {
19+
heap_bytes().map(|b| (label, b))
20+
}
21+
22+
pub struct ProveHeapProfile {
23+
pub before: Option<usize>,
24+
pub after_execute: Option<usize>,
25+
pub after_trace_build: Option<usize>,
26+
pub after_air: Option<usize>,
27+
}
28+
529
/// Sub-operation timing breakdown for a single table in Rounds 2-4.
630
#[derive(Clone, Debug, Default)]
731
pub struct TableSubOps {
@@ -47,6 +71,7 @@ pub struct MultiProveTiming {
4771
pub round1_sub: Round1SubOps,
4872
/// (name, rows, duration, sub_ops) per table for rounds 2-4.
4973
pub table_timings: Vec<(String, usize, Duration, TableSubOps)>,
74+
pub heap_snapshots: Vec<HeapSnapshot>,
5075
}
5176

5277
/// Round 1 sub-timings: atomics so parallel rayon workers can accumulate safely.

crypto/stark/src/prover.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,8 @@ pub trait IsStarkProver<
15061506

15071507
#[cfg(feature = "instruments")]
15081508
crate::instruments::reset_all();
1509+
#[cfg(feature = "instruments")]
1510+
let mut heap_snaps: Vec<crate::instruments::HeapSnapshot> = Vec::new();
15091511

15101512
let num_airs = air_trace_pairs.len();
15111513

@@ -1537,6 +1539,10 @@ pub trait IsStarkProver<
15371539

15381540
#[cfg(feature = "instruments")]
15391541
let prepass_elapsed = phase_start.elapsed();
1542+
#[cfg(feature = "instruments")]
1543+
if let Some(s) = crate::instruments::snap("After pool alloc") {
1544+
heap_snaps.push(s);
1545+
}
15401546

15411547
// =====================================================================
15421548
// Round 1, Phase A: Commit all main traces (parallel in chunks of K)
@@ -1599,6 +1605,10 @@ pub trait IsStarkProver<
15991605

16001606
#[cfg(feature = "instruments")]
16011607
let main_commits_elapsed = phase_start.elapsed();
1608+
#[cfg(feature = "instruments")]
1609+
if let Some(s) = crate::instruments::snap("After main commits") {
1610+
heap_snaps.push(s);
1611+
}
16021612

16031613
// =====================================================================
16041614
// Round 1, Phase B: Sample shared LogUp challenges
@@ -1645,6 +1655,10 @@ pub trait IsStarkProver<
16451655

16461656
#[cfg(feature = "instruments")]
16471657
let aux_build_elapsed = phase_start.elapsed();
1658+
#[cfg(feature = "instruments")]
1659+
if let Some(s) = crate::instruments::snap("After aux build") {
1660+
heap_snaps.push(s);
1661+
}
16481662

16491663
// Pass 2: Parallel fork transcript → extract → LDE → commit in chunks of K.
16501664
// Each table gets its own transcript fork.
@@ -1752,6 +1766,10 @@ pub trait IsStarkProver<
17521766

17531767
#[cfg(feature = "instruments")]
17541768
let aux_commit_elapsed = phase_start.elapsed();
1769+
#[cfg(feature = "instruments")]
1770+
if let Some(s) = crate::instruments::snap("After aux commit") {
1771+
heap_snaps.push(s);
1772+
}
17551773

17561774
#[cfg(feature = "debug-checks")]
17571775
Self::run_debug_checks(&air_trace_pairs, &commitments, &domains, &twiddle_caches);
@@ -1869,6 +1887,7 @@ pub trait IsStarkProver<
18691887
rounds_2_4: phase_start.elapsed(),
18701888
round1_sub: crate::instruments::take_r1_sub(),
18711889
table_timings,
1890+
heap_snapshots: heap_snaps,
18721891
});
18731892
}
18741893

prover/src/instruments.rs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub fn print_report(
5757
trace_build: Duration,
5858
air_construction: Duration,
5959
total: Duration,
60+
heap_profile: &stark::instruments::ProveHeapProfile,
6061
) {
6162
let mp = stark::instruments::take();
6263

@@ -69,18 +70,26 @@ pub fn print_report(
6970
row_top("Trace build", trace_build, total);
7071
row_top("AIR construction", air_construction, total);
7172

72-
if let Some(mp) = mp {
73+
if let Some(ref mp) = mp {
7374
let round1 = mp.main_commits + mp.aux_build + mp.aux_commit;
7475

7576
row_top("Pre-pass (domains/twiddles)", mp.prepass, total);
7677
row_top("Round 1", round1, total);
7778
row_sub(" Main trace commits", mp.main_commits, total);
78-
row_sub(" expand_columns_to_lde", mp.round1_sub.main_lde, total);
79-
row_sub(" commit (Merkle)", mp.round1_sub.main_merkle, total);
79+
row_sub(
80+
" Main expand_columns_to_lde",
81+
mp.round1_sub.main_lde,
82+
total,
83+
);
84+
row_sub(" Main commit (Merkle)", mp.round1_sub.main_merkle, total);
8085
row_sub(" Aux trace build (parallel)", mp.aux_build, total);
8186
row_sub(" Aux trace commit", mp.aux_commit, total);
82-
row_sub(" expand_columns_to_lde", mp.round1_sub.aux_lde, total);
83-
row_sub(" commit (Merkle)", mp.round1_sub.aux_merkle, total);
87+
row_sub(
88+
" Aux expand_columns_to_lde",
89+
mp.round1_sub.aux_lde,
90+
total,
91+
);
92+
row_sub(" Aux commit (Merkle)", mp.round1_sub.aux_merkle, total);
8493
row_top("Rounds 2\u{2013}4", mp.rounds_2_4, total);
8594

8695
// Merge split tables: MEMW[0..4] → MEMW x5
@@ -208,4 +217,33 @@ pub fn print_report(
208217
eprintln!(" {}", "─".repeat(58));
209218
eprintln!(" {:<36} {:>7.2}s", "TOTAL", total.as_secs_f64());
210219
eprintln!();
220+
221+
let mb = |b: usize| b / (1024 * 1024);
222+
if let Some(before) = heap_profile.before {
223+
eprintln!("=== HEAP PROFILE (MB) ===");
224+
eprintln!(" {:<36} {:>8} {:>8}", "Phase", "Heap", "Delta");
225+
eprintln!(" {}", "─".repeat(56));
226+
let mut prev = before;
227+
let mut print_row = |label: &str, val: Option<usize>| {
228+
if let Some(v) = val {
229+
let cur = mb(v);
230+
let delta = mb(v) as isize - mb(prev) as isize;
231+
eprintln!(" {:<36} {:>7} {:>+8}", label, cur, delta);
232+
prev = v;
233+
}
234+
};
235+
print_row("After execute", heap_profile.after_execute);
236+
print_row("After trace build", heap_profile.after_trace_build);
237+
print_row("After AIR construction", heap_profile.after_air);
238+
if let Some(ref mp_data) = mp {
239+
for (label, bytes) in &mp_data.heap_snapshots {
240+
let cur = mb(*bytes);
241+
let delta = cur as isize - mb(prev) as isize;
242+
eprintln!(" {:<36} {:>7} {:>+8}", label, cur, delta);
243+
prev = *bytes;
244+
}
245+
}
246+
eprintln!(" {}", "─".repeat(56));
247+
eprintln!();
248+
}
211249
}

prover/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@ pub fn prove_with_options_and_inputs(
511511
) -> Result<VmProof, Error> {
512512
#[cfg(feature = "instruments")]
513513
let total_start = std::time::Instant::now();
514+
#[cfg(feature = "instruments")]
515+
let heap_before = stark::instruments::heap_bytes();
514516

515517
// Phase 1: Execute (ELF load + run)
516518
#[cfg(feature = "instruments")]
@@ -525,6 +527,8 @@ pub fn prove_with_options_and_inputs(
525527

526528
#[cfg(feature = "instruments")]
527529
let execute_elapsed = phase_start.elapsed();
530+
#[cfg(feature = "instruments")]
531+
let heap_after_execute = stark::instruments::heap_bytes();
528532

529533
// Phase 2: Trace build
530534
#[cfg(feature = "instruments")]
@@ -536,6 +540,8 @@ pub fn prove_with_options_and_inputs(
536540

537541
#[cfg(feature = "instruments")]
538542
let trace_build_elapsed = phase_start.elapsed();
543+
#[cfg(feature = "instruments")]
544+
let heap_after_trace = stark::instruments::heap_bytes();
539545

540546
// Phase 3: AIR construction
541547
#[cfg(feature = "instruments")]
@@ -552,6 +558,8 @@ pub fn prove_with_options_and_inputs(
552558

553559
#[cfg(feature = "instruments")]
554560
let air_elapsed = phase_start.elapsed();
561+
#[cfg(feature = "instruments")]
562+
let heap_after_air = stark::instruments::heap_bytes();
555563

556564
let runtime_page_ranges = traces.runtime_page_ranges();
557565

@@ -569,6 +577,12 @@ pub fn prove_with_options_and_inputs(
569577
trace_build_elapsed,
570578
air_elapsed,
571579
total_start.elapsed(),
580+
&stark::instruments::ProveHeapProfile {
581+
before: heap_before,
582+
after_execute: heap_after_execute,
583+
after_trace_build: heap_after_trace,
584+
after_air: heap_after_air,
585+
},
572586
);
573587
}
574588

0 commit comments

Comments
 (0)