Skip to content

fix(prover): print per-table instruments report on the continuation path#853

Open
MauroToscano wants to merge 1 commit into
mainfrom
fix/continuation-instruments-report
Open

fix(prover): print per-table instruments report on the continuation path#853
MauroToscano wants to merge 1 commit into
mainfrom
fix/continuation-instruments-report

Conversation

@MauroToscano

Copy link
Copy Markdown
Contributor

Bug

The instruments cargo feature prints a rich per-table-kind timing report
(merges split tables by kind, e.g. MEMW[0..4] -> MEMW x5, aggregates
count / rows / duration / sub-ops, sorted by cost). That report was only ever
emitted on the monolithic prove() path, from the
#[cfg(feature = "instruments")] block in prover/src/lib.rs.

The continuation path never went through that block: prove_epoch and
prove_global in prover/src/continuation.rs call Prover::multi_prove
directly. multi_prove does instruments::store(MultiProveTiming { .. }) for
every call, so the per-table data was already being computed and stored — but
nothing on the continuation path ever printed it. Result:
prove --continuations with --features instruments produced no per-table
report at all.

Fix

Feature-gated only (zero cost, and byte-for-byte identical compile, when the
feature is off):

  • prover/src/instruments.rs: factor the mp-derived per-table block out of
    print_report into a shared print_multi_prove(mp, total) helper, and add
    print_epoch_report(label) which drains the timing stored by the preceding
    multi_prove via stark::instruments::take() and formats it with that same
    helper (so both paths format from a single source of truth). Also inlined a
    literal into one eprintln! format string to silence a pre-existing
    clippy::print_literal that only trips under --features instruments;
    rendered output is unchanged.
  • prover/src/continuation.rs: after each Prover::multi_prove, call
    print_epoch_report, labeled EPOCH N for each epoch (from the 1-based
    EpochStart.label) and GLOBAL for the cross-epoch memory proof.

The monolithic path's output is unchanged (same statements, same order — the
mp block was moved into a function and called with the same mp/total). No
proving logic changed; this is purely gated reporting.

Note on GLOBAL: its per-epoch total is derived from the sum of the proving
phases, so for a trivially small global proof (a couple of tiny tables that run
in parallel) individual table percentages can exceed 100% — an honest artifact
of parallel per-table timing against a tiny sequential-phase denominator (the
monolithic formatter has the same parallel overlap, just diluted by a larger
wall-clock total). The EPOCH N reports, which carry the real work, read
normally.

Verification

Built and ran a continuation prove that exercises prove_epoch (x2) +
prove_global:

cargo build --release -p cli --features instruments
./target/release/cli prove executor/program_artifacts/asm/fib_iterative_500k.elf \
    --output /tmp/cont.proof --continuations --epoch-size-log2 18

Per-epoch reports now print. Sample (trimmed):

=== EPOCH 0 ===
  Phase                                    Wall      %
  --------------------------------------------------------
  Pre-pass (domains/twiddles)             0.03s    1.0%
  Round 1                                 1.30s   38.8%
    Main trace commits                    0.59s          17.7%
    ...
  Rounds 2-4                              2.01s   60.1%
      BITWISE              1.0M           0.82s          24.5%
      MEMW_R               524K           0.47s          13.9%
      EQ                    66K           0.32s           9.7%
      CPU                  262K           0.32s           9.6%
      ...
      (16 others)                         0.67s          20.0%
      -- sub-operation totals (all tables) --
      R4  queries & openings              1.09s          32.7%
      R3  OOD evaluation                  0.66s          19.7%
      ...
  Total FFT                               0.79s   23.6%
  Total Merkle                            0.86s   25.7%
  --------------------------------------------------------
  TOTAL                                   3.34s

=== EPOCH 1 ===
  ... (same layout) ...

=== GLOBAL ===
  ... (same layout) ...
  • Feature ON: reports print per epoch (EPOCH 0, EPOCH 1, GLOBAL).
  • Feature OFF (cargo build --release -p cli): zero instruments lines in the
    continuation prove output; compiles clean (all new code is
    #[cfg(feature = "instruments")]).
  • cargo test --release -p lambda-vm-prover --lib: 521 passed, 0 failed.
  • clippy --features instruments (which CI's make lint does not exercise)
    is clean on the changed crates; all three make lint clippy passes exit 0;
    cargo fmt --check is clean on the changed crates.

The `instruments` feature's per-table-kind timing report only printed on the
monolithic `prove()` path. The continuation path (`prove_epoch`/`prove_global`)
calls `Prover::multi_prove` directly; `multi_prove` still `store()`s the
`MultiProveTiming` for each call, but nothing ever printed it, so
`prove --continuations` with `--features instruments` produced no per-table
report at all.

Factor the mp-derived per-table block out of `instruments::print_report` into a
shared `print_multi_prove()` helper, and add `print_epoch_report()` which drains
the stored timing via `stark::instruments::take()` and formats it with that same
helper. `prove_epoch`/`prove_global` now call it (feature-gated) right after each
`multi_prove`, labeled "EPOCH N" / "GLOBAL". The monolithic path's output is
unchanged (same statements, same order). All new code and both call sites are
under `#[cfg(feature = "instruments")]`, so the feature-off build compiles
identically with zero added overhead.
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.

2 participants