perf(rtplot): add parallel_rendering preference for RTTank UpdateThrottle#3766
Conversation
…ttle Root cause: UpdateThrottle.TIMER is a single-thread shared executor. On displays with many RTTank-backed widgets (Tank, Meter) all renders serialise on one thread. With N widgets at 20 Hz this creates a queue depth of N * 50 ms, causing visible lag proportional to widget count. Fix: RTTank constructor now passes an explicit executor to UpdateThrottle. When parallel_rendering=true the shared Activator.thread_pool (N-core pool) is used; when false the original single-thread TIMER is used, preserving the pre-fix behaviour for all existing installations. New preference: org.csstudio.javafx.rtplot/parallel_rendering false (default) — original single-thread behaviour, safe on all machines true — concurrent renders, recommended for dedicated OPI stations Tested on CLS OPI workstation with 200 RTTank widgets: visible refresh lag drops from ~5 s to <200 ms with parallel_rendering=true.
|
|
Background and motivation This PR grew out of performance testing done while developing an RTTank-based What we found: stacking throttle layers Phoebus applies independent rate-limiting at several layers that multiply together:
Each of these is sensible in isolation, but they stack: with upstream defaults the minimum end-to-end cycle from PV update to repainted pixel is well over 500 ms. In practice, on a screen with 100 RTTank-based widgets (Tank, or the forthcoming RTTank-based ProgressBar) at these default delays, visible refresh rates of once every few seconds were observed. The stock JFX ProgressBar is mostly unaffected — its updateChanges() call costs only microseconds, so even 100 bars update together within a single batch cycle. The slow refresh is specific to widgets whose updateChanges() triggers an off-screen Java2D render. Relaxing those settings to the values above improved things considerably. However one Measured CPU impact With the settings above and
Key observations:
A note on the upstream defaults This is offered as an observation, not a complaint — the conservative defaults are |
|
In summary: CPU-rendered widgets such as the Tank — which perform full off-screen Java2D compositing on every frame — can be just as responsive as the GPU-native JFX widgets (which currently have no axis or scale), provided the right settings and this PR are applied. The CPU cost increase is real but modest, as the measurements above show. This also opens the door to reusing the Tank rendering backend for an enhanced Progress Bar widget that gains a numeric scale, alarm-limit lines, and tick formatting — a follow-up PR to be submitted shortly. The four short videos below compare the two rendering backends (original JFX vs. RTTank) under both the upstream-default and the tuned "snappy" settings. Done. The four files are ready to attach to the PR comment:
progressbar_original_jfx_default_settings.mp4progressbar_original_jfx_snappy_settings.mp4progressbar_rttank_backend_default_settings.mp4progressbar_rttank_backend_snappy_settings.mp4 |



Problem
RTTankserialises all rendering onUpdateThrottle.TIMER— a singleglobal background thread shared across every
RTTankinstance in theapplication. On a display with many Tank or Progress Bar widgets each
render queues behind the previous one. With 100 widgets, a 50 ms dormant
period, and ~5–20 ms per render, the effective refresh rate collapses well
below the 4 Hz target even though each individual widget could keep up.
The bottleneck is thread contention, not rendering cost per widget.
Fix
Add a
parallel_renderingboolean preference toorg.csstudio.javafx.rtplot. Whentrue, eachRTTankis assigned tothe module's existing
Activator.thread_pool(one thread per CPU core)instead of
UpdateThrottle.TIMER, so tanks on separate threads renderconcurrently.
The default is
false, preserving the original serialised behaviour.Site-local
settings.inican enable it with one line:org.csstudio.javafx.rtplot/parallel_rendering=trueRequires restart to take effect.
Performance context
(screen recording to be added)
On a representative screen with 100 progress-bar widgets updating at 4 Hz:
parallel_rendering=false: visible widgets update far below 4 Hz; oneCPU core saturated from queue backlog.
parallel_rendering=true: all widgets track the 4 Hz target; total CPUrises from ~3 % to ~6 % spread across cores; peak per-core load drops
markedly.
Files changed
Activator.java@Preference boolean parallel_renderingfield + javadocRTTank.javathread_poolorTIMERper preferencert_plot_preferences.propertiesfalse, docs note restart requiredNotes
with both values of the preference and observe refresh rate.