perf: editing a math graph recomputes that graph, not every channel

`set_math_channels()` rebuilt the store for any change, and a rebuild replaces the buffer:
every channel in the window started again, which is the "modifying one expression invalidates
all the others" report.

The plan is a *partition over the channels*, so it only moves when the set moves. When the
set is unchanged -- same channels, names and enables -- nothing is rebuilt now: the store is
untouched, every other channel keeps its samples and its runtimes, and the surgical path
prepares and recomputes only the affected graphs. The affected set is the edited channels plus
whatever *names* them, because one channel's output is another's input, and the recompute
computes the whole list in order (the inputs have to be there) while writing only those in
the mask -- which is why the step-loop is now `math_apply_locked(sample, write_mask, timed)`.

Adding, removing or renaming a channel still moves the plan, and still rebuilds.

    [math-probe] graph edit: stored_slots 800 -> 900 (want the second at least the first, and non-zero)

The count grows because the stream keeps filling while the edit runs; the point is that it
never falls to 0, and that every channel afterwards still reads `N samples vs M time slots`
with N == M.
This commit is contained in:
Martino Ferrari committed 2026-10-12 22:19:17 +02:00
1 parent 8b3240cacb
commit 5eb20f3cdb
5 files changed
+154 -4

No files matched your search

+11
View File
@@ -280,3 +280,14 @@ filter's history remains the last *real* samples it saw, and the trace resumes a
with at most the transient a re-start costs. The exit dump's `math '<name>': finite=N/M` line is
the assertion: `finite` must be about `M` minus the hole share, and `finite=0` beside non-zero
`hole_slots` is this defect returned.
- **A graph *edit* does not move the plan; adding or removing a channel does.** The plan is a partition over
the channels, so `set_math_channels()` takes a surgical path whenever the *set* is unchanged -- same channels,
names and enables: the store is never touched, every other channel keeps its samples **and** its runtimes, and
only the edited graphs are prepared again. `math_apply_locked()` computes the whole list on a recompute
(the graphs are walked in order, so a channel's inputs must be there) but writes only the channels in the
affected mask; the affected set is the edited channels plus whatever *names* them, since one channel's output
is another's input. Before this, every edit rebuilt the store and every channel in the window started again,
which is the "modifying one expression invalidates all the others" report.
`[math-probe] graph edit: stored_slots N -> M` reads it: M must be at least N -- the store keeps filling
while the edit runs -- and never 0.