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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//! Within-pass re-fire measurement — sizing how much of a propagation is
//! redundant re-fire, and thus coalesceable, **without changing any behavior**.
//!
//! A *pass* is one logical propagation boundary. For the motivating case
//! (rship's server-side fanout) that is one store-diff / `EventBatch`
//! application: wrap it in [`pass`], and while that scope is on the stack every
//! cell **fanout** — one per emit — is tallied by cell id. A cell that fans out
//! more than once in a single pass is *re-firing*: in a glitch-free coalesced
//! world it would emit once with its settled value, so every fire past the
//! first is coalesceable.
//!
//! This is pure measurement on the synchronous path — it defers, coalesces, and
//! reorders nothing. Two ways to use it:
//!
//! - On today's synchronous build, [`pass`] reports the full re-fire count —
//! direct proof of the coalesceable fraction before you adopt [`batch`].
//! - Run the *same* pass with [`batch`] active and each cell's count collapses
//! toward 1: that is the coalescing landing, measured the same way, so the
//! two numbers are directly comparable (an A/B on one metric).
//!
//! Gated behind `profiling`; compiles to nothing otherwise.
//!
//! ```
//! use hyphae::{Cell, MapExt, MaterializeDefinite, Mutable, Watchable};
//! use hyphae::profiling::{pass, take_report};
//!
//! let a = Cell::new(1);
//! let b = a.clone().map(|x| x + 1).materialize();
//! let guard = b.subscribe(|_| {});
//!
//! pass(|| {
//! a.set(2);
//! a.set(3);
//! });
//! let report = take_report().unwrap();
//! assert!(report.total_fires() >= report.total_refires());
//! drop(guard);
//! ```
use RefCell;
use FxHashMap;
use Uuid;
thread_local!
/// Per-thread pass state: the reentrancy depth, the in-flight per-cell tally,
/// and the most recently sealed report.
/// Per-cell fanout tally for one completed [`pass`].
///
/// `per_cell` holds `(cell id, fanouts in the pass)` for every cell that fired.
/// The derived accessors turn that into the numbers you actually want: how much
/// firing was redundant, and which cells drove it.
/// Run `f` as one measured pass, tallying every cell fanout that happens inside
/// it. Retrieve the tally with [`take_report`] after `f` returns.
///
/// Returns `f`'s value untouched. Nested calls join the outermost pass — only
/// the outermost resets the tally on entry and seals the [`PassReport`] on exit
/// (including on unwind), so a panic inside `f` still leaves a clean slate.
///
/// This measures whatever fanouts occur, so it composes with [`batch`]: wrap
/// `pass(|| batch(|| ..))` (or the reverse) and the report reflects the
/// coalesced fanout count.
/// Take the most recently completed pass's report, if one has been sealed since
/// the last take. The read clears it, so a second call returns `None` until the
/// next [`pass`] completes.
/// Tally one fanout for `id` when a pass is active. Called from `Cell::fanout`;
/// a no-op (one thread-local borrow and a depth check) outside a pass.
pub