improved perfs and event management
This commit is contained in:
1 parent
667ed0c100
commit
bb99be5889
17 files changed
+626
-59
No files matched your search
@@ -29,6 +29,21 @@ window the toolbar offers, default 600), `--holdoff` (default trigger hold-off),
|
||||
added and removed from the **Layout editor** afterwards), `--relative-time` (see below),
|
||||
`--capture-packets N` (see "Packet capture" below).
|
||||
|
||||
**What a large `--buffer-mb` costs at startup, and what the window says while it happens.** The
|
||||
buffer's rings are value-initialised, so allocating one touches every byte of `--buffer-mb` --- about
|
||||
a second per gigabyte, mostly first-touch page faults --- and it happens on the producer thread
|
||||
holding the lock the frame tick also takes. It is therefore a real freeze and not a slow paint. Two
|
||||
things follow. First, a rebuild whose plan describes the storage already allocated **clears** the
|
||||
store instead of allocating a new one, which is what most structural changes are: startup used to ask
|
||||
for fifteen allocations and now asks for two or three (3.36 s → 1.18 s at `--buffer-mb 1000`), and
|
||||
every enable of a signal is applied in one batch rather than re-planning per signal. Second, the
|
||||
window is **presented before** the buffer is planned and carries a notice naming what it is waiting
|
||||
for --- `connecting to 127.0.0.1:8000 — planning the 4000 MB buffer` --- because the remaining second
|
||||
or so at a multi-gigabyte buffer is unavoidable, and a blank window that says nothing is the part of
|
||||
it that reads as a hang. Each allocation also names itself on stderr
|
||||
(`[udpscope] buffer allocated: 4 channels, 839 s span, 74 ms`), so a run that prints a column of them
|
||||
is a re-plan that should have been coalesced.
|
||||
|
||||
Every CONFIG is dumped to stderr once -- publish mode and, per signal, its name,
|
||||
element count, rate, time mode and time-signal index -- because a signal that
|
||||
refuses to plot is almost always a signal the stream described in an unexpected
|
||||
@@ -109,6 +124,14 @@ export's second column reads — and it fixed a latent bug on the way, the expor
|
||||
having added `trigger_time()` to a *paused* view's stamps: an unrelated edge, or none at all before
|
||||
the first latch.
|
||||
|
||||
**An axis with nothing bound to it is still `[-window, 0]`.** "No samples yet" is the state every
|
||||
structural change leaves behind — opening an event or a waveform re-plans the rings, which drops
|
||||
their history, and the axis is then framed before the first sample of the new view lands. Framing it
|
||||
at `[0, window]` there (which is what it did) offsets the view by a whole window under the x link
|
||||
group's follow rule, so the two or three frames after every open drew the time base one screen to the
|
||||
left of where the following frames drew it: a trace that jumps sideways and comes back, on every open.
|
||||
The empty axis is now drawn in the same place as the full one.
|
||||
|
||||
Two things move in **opposite** directions under a rolling axis, and the asymmetry is deliberate.
|
||||
A **cursor** stays on screen: placed at -1.5 s it keeps meaning "1.5 s ago" and the data flows
|
||||
under it, which is a bench scope's roll behaviour and is free here, the cursors already being
|
||||
@@ -523,9 +546,15 @@ empty column beside the plot is what *off* must not look like. Recording is swit
|
||||
panel**, with the trigger's other options rather than in the pane whose contents it decides, and it is
|
||||
**off by default** -- writing every latch to disk is the user's decision about their disk.
|
||||
|
||||
Each row carries **its own picture** beside the numbers -- time, duration, signal count, rate -- in a
|
||||
fixed 126x42 cell (the preview's own 3:1), so the picture is the same size in every row whatever the
|
||||
pane's width. Clicking a row **replays** it: the same loader `--open` uses, on the event's file. **The layout does
|
||||
Each row carries **its own picture** beside the numbers -- time, duration, signal count, rate -- 138
|
||||
pixels wide whatever the pane's width, and as tall as that event's own proportions make it: the
|
||||
preview is one 44-pixel strip per signal, so a one-signal event is a short row and a six-signal one a
|
||||
tall one (capped, so that a row stays a row). **Hovering it shows the whole preview at full size**,
|
||||
through a tooltip -- the small picture says *which* event this is, the zoom says what is in it.
|
||||
Clicking a row **replays** it: the same loader `--open` uses, on the event's file. The click **leaves
|
||||
the list alone** -- your scroll position and the pair you had selected for a comparison both survive
|
||||
it, because marking which event is on screen rewrites the rows' titles in place instead of rebuilding
|
||||
the list. **The layout does
|
||||
not change** -- the rows, which signal sits in which slot, the colours, the row count, the time window,
|
||||
the cursors and the measurements all stay exactly where they are, and now read the stored event instead
|
||||
of the stream; that is what "show me that event" asks for, and rebinding the rows to the file would
|
||||
@@ -562,6 +591,8 @@ Three things worth knowing:
|
||||
trigger edge as a brighter line -- not captured from the window: the plot is a `GtkGLArea`, and a
|
||||
GL area's ink is not in the widget's paint tree, so a snapshot of it is empty. A data-drawn
|
||||
preview is also the honest one: it shows the samples, not the zoom the window happened to be at.
|
||||
It is a plain 24-bit BMP, written bottom-up with **blue first** — both are BMP's own order, and
|
||||
writing RGB there is what made every external viewer show the traces in the wrong colour.
|
||||
- **The picture is decoded synchronously** (`gdk_texture_new_from_filename()` into
|
||||
`gtk_picture_set_paintable()`), not through `gtk_picture_set_filename()`: that path uses the image
|
||||
loader's sandboxed, asynchronous decoder, which here fails silently -- the picture keeps a
|
||||
@@ -569,9 +600,19 @@ Three things worth knowing:
|
||||
It is then **scaled once to the row's size** and cached by file: a `GtkPicture`'s natural size is
|
||||
its content, so the stored 480-pixel preview given straight to a row claims the row's whole width
|
||||
and squeezes the text out of it -- a size request on the picture is a floor, not a cap.
|
||||
- **A picture that is missing or will not decode is drawn again from the samples.** The `.npy` is the
|
||||
event; the `.bmp` is only a picture of it, so a write that failed, a truncated file or a cache from
|
||||
an older build is repaired rather than shown as a blank row. Once per row: a second failure is a
|
||||
real one.
|
||||
- **A replay stops the acquisition** (a live producer would overwrite the loaded samples within a
|
||||
frame), so the status bar names the file until *Live* starts a fresh client and thread. The
|
||||
replayed samples age out of the ring as the stream refills it.
|
||||
- **Opening an event, a comparison or going back to *Live* is one re-plan of the buffer**, not one
|
||||
per channel. Each of those switches rebuilds the signal set, and a rebuild that moves the plan
|
||||
allocates --- and so touches --- the whole of `--buffer-mb`; enabling a comparison's eight channels
|
||||
one at a time was eight of those, which is most of what made the switch feel slow. They are now
|
||||
enabled in a single call, and a rebuild whose plan is unchanged clears the buffer instead of
|
||||
allocating a new one.
|
||||
- The switch in the pane's header stops the recording; the cache is only useful if it was already
|
||||
on when the event you wanted happened, which is why it defaults to on.
|
||||
|
||||
|
||||
Reference in new issue
Block a user