Skip to content

Communication Over Time: focus a summary trace on a time range and a subset of entry methods - #167

Merged
ritvikrao merged 5 commits into
mainfrom
messages-over-time-focus
Aug 14, 2026
Merged

Communication Over Time: focus a summary trace on a time range and a subset of entry methods#167
ritvikrao merged 5 commits into
mainfrom
messages-over-time-focus

Conversation

@lvkale

@lvkale lvkale commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Follow-on to #166, from using it on a 1792 PE Frontier summary trace (14995 intervals of 1 ms, 440 entry methods). Everything here is about finding the part of such a chart worth looking at.

Five commits, each building on its own.

Switch entry methods off from the entry chooser. The chart stacks every entry method that processed a message, and one commonly has two orders of magnitude more than the rest, flattening the others into the axis. Ticking one off in "Choose Entry Colors" drops it from the chart, the totals and the legend, so the y axis rescales to what is left. The dialog already had a visibility column (Timeline uses it); the graph tools' path into it hardcoded colors-only, and that is now the entryFilterAllowsHiding() hook, which only this tool answers yes to.

Drag to zoom the time axis. Dragging across the plot narrows it to that stretch, with a Reset Zoom button to undo. Only the selected slice is handed to the chart, so the stacked maximum is recomputed from it and the x axis re-bases; popups, totals, legend and the chooser's entry list all follow. Zooming re-slices data already in memory rather than re-reading the trace, so it cannot show bins finer than the range dialog loaded. The rubber band is Graph.setXRangeSelectionListener, filling in mouse handlers that were empty stubs -- a tool that registers no listener sees no change.

Order the entry chooser by count where a tool has one. 50 of the 78 entry methods in range on the test trace have under 100 events each, against 1.76 M messages total; listed by id, the ones that matter are scattered among them. getEntriesArray() already returned numbers rather than flags, so a tool can opt in with sortEntriesByCount(): largest first, counts in a column, anything under a thousandth of the busiest greyed at the bottom. Only Messages Over Time opts in. This also stops MyTableModel hardcoding its column count and editable columns by position -- as a side effect the id column is no longer editable, which it had been all along.

Expand message sizes only when asked for. Loading a range ran two passes over the run length data, one for counts and one for sizes, each costing PEs x intervals x entry methods with its own progress bar. The second is usually for nothing: a trace written before charm recorded sizes (charmplusplus/charm#3937, still open) has no such line, so the pass walks empty data to produce zeros the Bytes view then declines to draw. Sizes now expand on the first switch to Bytes, off the event thread.

Combine intervals to see the shape under the noise. A Smoothing button offers combining every k intervals into one bar (totals preserved exactly, partial last bin kept), a moving average over k intervals (one bar per interval, edges averaged over what exists), and the special case of k equal to the whole visible range -- one bar whose bands are the totals per entry method on screen. Rates then divide by the time a bar spans rather than one interval, popups name the span a bar covers and say when a value is an average, and drag-to-zoom converts selected bars back into intervals.

Testing

Driven by hand on the 1792 PE trace above, plus headless checks of the parts that are awkward to verify by eye:

  • selection: press/drag/release dispatched into the canvas -- full-width drag selects every bin, a mid drag gives the same bins in both drag directions, a 2 pixel drag is ignored, a release past the edge clamps
  • chooser: with counts 1M/250k/3000/999/64/1 the rows come out in that order, columns read [Visible][Entry Method][ID][Count][Color], only the three under a thousandth of the largest are grey, visible and colour cells stay editable, and a tool that does not opt in still gets [Entry Method][ID][Color] in id order
  • smoothing: 10 intervals of 1..10 with k=3 give bars 6, 15, 24, 10 with totals preserved, bar 1 mapping back to intervals 3-5 and the last to 9-9; whole-range gives one bar of 55; the k=3 moving average gives 1.5, 6.0 and 9.5 at left edge, middle and right edge
  • an all-hidden chart (Hide All) paints without exception or hang

Shared files

gui/graph/Graph.java, gui/ChooseEntriesWindow.java, gui/MyTableModel.java, gui/GenericGraphWindow.java and gui/EntryMethodVisibility.java are used by other tools. Every behaviour change in them is behind an opt-in a tool has to ask for, except the id column of the chooser becoming non-editable.

lvkale added 5 commits August 13, 2026 13:24
The chart stacks every entry method that processed a message, and one of
them commonly has two orders of magnitude more than the rest, which
flattens everything else into the axis. Ticking one off in "Choose Entry
Colors" now drops it from the chart, the totals line and the legend, so
the y axis rescales to what is left.

The dialog already supports a visibility column -- Timeline uses it --
but the graph tools' path into it hardcoded colors-only. That is now a
hook, entryFilterAllowsHiding(), which only this tool answers yes to;
every other GenericGraphWindow tool opens the dialog exactly as before.
Its list is still restricted to the entry methods present in the loaded
range, and switched-off ones stay listed, since the dialog is the only
way to switch them back on.
A run of a few seconds at millisecond resolution puts thousands of
intervals on the chart, and the interesting stretch is usually a fraction
of one. Dragging across the plot now narrows it to that stretch, with a
Reset Zoom button to go back to the whole loaded range.

Both axes follow: only the selected slice is handed to the chart, so the
stacked maximum is recomputed from it and the x axis is re-based onto the
first interval on show. So does the entry chooser -- the entry methods it
lists, and the totals and legend, are those of the window being looked
at, which on a large trace is the difference between a handful of entries
and several hundred.

Zooming re-slices data already in memory rather than re-reading the
trace, so it is free at a few thousand PEs, but it cannot show finer bins
than the range dialog loaded; a shorter range still has to be loaded for
that.

The rubber band itself is Graph.setXRangeSelectionListener, filling in
mouse handlers that were empty stubs. A tool that registers no listener
sees no change at all.
Most entry methods in range on a large trace are a handful of setup calls
against millions of messages -- 50 of the 78 in range on a 1792 PE
summary trace have under 100 events each. Listed by entry method id, the
ones that matter are scattered among them, and a user looking for the
entry method that is actually on the chart has to read the whole list.

getEntriesArray() already returns numbers rather than flags (Timeline
returns real frequencies), so a tool can now opt in with
sortEntriesByCount(): its list is ordered largest first, the counts get a
column, and anything under a thousandth of the busiest is greyed at the
bottom -- present in the range, but nothing on a chart. Only Messages
Over Time opts in; every other chooser keeps the list and columns it had.

MyTableModel had the column count and the editable columns hardcoded by
position, which the extra column breaks. Both are now taken from the
data: as a side effect the id column is no longer editable, which it has
been all along, letting a user type over an entry method's id to no
effect whatever.
Loading a range ran two passes over the run length data, one for counts
and one for sizes, each costing PEs x intervals x entry methods and each
showing its own progress bar. The second one is usually for nothing: a
trace written by a charm that does not record message sizes has no such
line in its .sumd files, so the pass walks empty data on every PE to
produce an array of zeros that the Bytes view then declines to draw.

Sizes now expand the first time something needs them, which is the first
switch to the Bytes view. That switch, and a range reload made while
Bytes is showing, both do the work off the event thread -- on the event
thread the progress bar cannot paint and the window would simply hang.
A millisecond interval on a real run is noisy enough that the chart's
shape is hard to read. A Smoothing button now offers two ways to combine
intervals, and a special case of the first.

Combining every k intervals sums them into one bar, so the totals are
preserved exactly and a bar means the messages of the intervals under it;
a partial last bin is kept rather than dropped, which would lose
messages. A moving average keeps one bar per interval and puts the mean
of the k around it in each, averaging over what exists at the edges
rather than inventing data. The special case is k equal to the whole
visible range: one bar whose stacked bands are the totals per entry
method over the range on screen.

What follows from a bar no longer being an interval: rates divide by the
time the bar spans rather than by one interval, popups name the span of
intervals a bar covers and say when a value is an average, and a drag to
zoom converts the bars it selected back into intervals. Zooming and
smoothing compose -- the whole-range case re-reads the zoom every time it
draws, so narrowing the view re-totals it.
@ritvikrao
ritvikrao merged commit 2960a84 into main Aug 14, 2026
2 checks passed
@ritvikrao
ritvikrao deleted the messages-over-time-focus branch August 14, 2026 13:00
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