1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
//! Phase stopwatches for witness computations, compiled out unless the calling crate's
//! `witness_timers` feature is on.
//!
//! These are for the inside of a witness computation: how its own phases divide up (gathering the
//! inputs, filling the trace, merging per-batch multiplicity caches, flushing them to the `std`),
//! which is the granularity the `stats` command's per-air totals cannot show. They report at `info`
//! so a run with the feature on needs no `-v`, and each state machine emits one line per instance.
//!
//! Being macros rather than functions is what lets them vanish: `#[cfg]` inside a `macro_rules!`
//! body is evaluated where the macro is expanded, so each crate decides with its own
//! `witness_timers` feature and pays nothing when it is off — no `Instant::now()`, no formatting,
//! and no unused bindings to silence.
//!
//! ```ignore
//! phase_start!(t_fill);
//! ... // the phase
//! phase_end!(d_fill, t_fill);
//! ...
//! phase_log!("Mem[{}] fill {:.0}ms", segment_id, phase_ms!(d_fill));
//! ```
//!
//! # Why a phase is closed where it ends
//!
//! `phase_end!` captures the duration at the point the phase finishes, and `phase_ms!` formats that
//! captured value. Reading the stopwatch at log time instead would report the time from the phase's
//! *start* to the log, which for anything but the last phase is the rest of the function as well --
//! a mistake worth naming, because the resulting numbers look plausible: every phase comes out
//! roughly equal to the one after it.
//!
//! # Caveat
//!
//! A `phase_ms!` outside a `phase_log!` will not compile with the feature off, because the binding
//! it reads does not exist. Read a duration only from inside a `phase_log!`.
/// Starts a stopwatch named `$name`. Expands to nothing without `witness_timers`.
/// Closes the phase started as `$since`, capturing its duration as `$name`. Expands to nothing
/// without `witness_timers`.
/// A duration captured by [`phase_end!`], in milliseconds. Only valid inside a [`phase_log!`],
/// which is the only place that survives without the feature.
/// Logs a phase breakdown at `info`. Expands to nothing without `witness_timers`, which is what
/// makes the `phase_ms!` calls in its arguments disappear along with it.
/// A stopwatch shared by parallel batches, reporting the slowest of them.
///
/// The batches of a fill run under `rayon`, so each has to record its own timing somewhere shared;
/// this keeps the maximum. Expands to nothing without `witness_timers`.
/// Records `$since`'s elapsed time into the shared maximum `$name`.
/// The slowest time recorded in `$name`, in milliseconds. Only valid inside a [`phase_log!`].