Skip to content

Commit fbf027c

Browse files
authored
Merge pull request #3766 from emilioheredia-source/rtplot/parallel-rendering-for-rttank
perf(rtplot): add parallel_rendering preference for RTTank UpdateThrottle
2 parents f556261 + 2268304 commit fbf027c

3 files changed

Lines changed: 48 additions & 4 deletions

File tree

app/rtplot/src/main/java/org/csstudio/javafx/rtplot/Activator.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ public class Activator
3030
@Preference(name="shady_future") private static int[] rgba;
3131
public static final Color shady_future;
3232

33+
/** When true, RTTank renders on the shared thread pool (one thread per CPU
34+
* core) so many simultaneous Tank / ProgressBar instances update in
35+
* parallel. When false, all renders serialise on a single global thread
36+
* (the pre-fix behaviour). Controlled by the {@code parallel_rendering}
37+
* preference. */
38+
@Preference(name="parallel_rendering") public static boolean parallel_rendering;
39+
3340
/** Thread pool for scrolling, throttling updates
3441
*
3542
* <p>One per CPU core allows that many plots to run updateImageBuffer in parallel.

app/rtplot/src/main/java/org/csstudio/javafx/rtplot/RTTank.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.awt.image.BufferedImage;
1717
import java.text.NumberFormat;
1818
import java.util.Objects;
19+
import java.util.regex.Pattern;
1920
import java.util.concurrent.TimeUnit;
2021
import java.util.concurrent.atomic.AtomicBoolean;
2122

@@ -166,7 +167,11 @@ public RTTank()
166167
widthProperty().addListener(resize_listener);
167168
heightProperty().addListener(resize_listener);
168169

169-
// 20Hz default throttle
170+
// 20Hz default throttle.
171+
// When parallel_rendering is enabled, each tank renders on the shared thread pool
172+
// so that many tanks on a display update concurrently. The default (false) serialises
173+
// all renders on the single global UpdateThrottle.TIMER thread — safe but slow for
174+
// displays with many Tank / ProgressBar widgets.
170175
update_throttle = new UpdateThrottle(50, TimeUnit.MILLISECONDS, () ->
171176
{
172177
if (needUpdate.getAndSet(false)){
@@ -178,7 +183,7 @@ public RTTank()
178183
requestUpdate();
179184
}
180185
}
181-
});
186+
}, Activator.parallel_rendering ? Activator.thread_pool : UpdateThrottle.TIMER);
182187

183188
// Configure right-side scale — must happen after update_throttle is
184189
// initialised because setOnRight() triggers requestUpdate() via the
@@ -335,12 +340,12 @@ private static NumberFormat significantDigitsFormat(final int prec)
335340
@Override
336341
public StringBuffer format(final double v, final StringBuffer buf, final java.text.FieldPosition pos)
337342
{
338-
return buf.append(String.format(java.util.Locale.ROOT, pattern, v));
343+
return buf.append(normaliseExponent(String.format(java.util.Locale.ROOT, pattern, v)));
339344
}
340345
@Override
341346
public StringBuffer format(final long v, final StringBuffer buf, final java.text.FieldPosition pos)
342347
{
343-
return buf.append(String.format(java.util.Locale.ROOT, pattern, (double) v));
348+
return buf.append(normaliseExponent(String.format(java.util.Locale.ROOT, pattern, (double) v)));
344349
}
345350
@Override
346351
public Number parse(final String s, final java.text.ParsePosition pos)
@@ -350,6 +355,28 @@ public Number parse(final String s, final java.text.ParsePosition pos)
350355
};
351356
}
352357

358+
/** Pre-compiled pattern for stripping the sign and leading zeros from a
359+
* {@code %g} exponent string such as {@code "-01"} or {@code "+02"}.
360+
*/
361+
private static final Pattern EXP_LEADING_ZEROS = Pattern.compile("^[+-]?0*");
362+
363+
/** Normalise a {@code %g}-formatted string to match Phoebus axis convention:
364+
* uppercase {@code E}, no leading zeros on the exponent, no {@code +} sign.
365+
* Examples: {@code "1.0e-01"} &rarr; {@code "1.0E-1"},
366+
* {@code "2.5e+02"} &rarr; {@code "2.5E2"}.
367+
*/
368+
private static String normaliseExponent(final String s)
369+
{
370+
final int e = s.indexOf('e');
371+
if (e < 0)
372+
return s; // decimal notation — no exponent to fix
373+
final String mantissa = s.substring(0, e);
374+
final String raw = s.substring(e + 1); // e.g. "-01", "+02"
375+
final boolean neg = raw.startsWith("-");
376+
final String digits = EXP_LEADING_ZEROS.matcher(raw).replaceFirst("");
377+
return mantissa + "E" + (neg ? "-" : "") + (digits.isEmpty() ? "0" : digits);
378+
}
379+
353380
/** Set alarm and warning limit values to display as horizontal lines on the tank.
354381
* Pass {@link Double#NaN} for any limit that should not be shown.
355382
* @param lolo LOLO (major alarm) lower limit

app/rtplot/src/main/resources/rt_plot_preferences.properties

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,13 @@
2020
#
2121
# shady_future=128, 128, 128, 0
2222
shady_future=128, 128, 128, 128
23+
24+
# Use a thread pool for RTTank rendering so that many simultaneous RTTank
25+
# instances (Tank widget, ProgressBar with scale) render in parallel rather
26+
# than serialising on a single global thread.
27+
#
28+
# Set to false only on severely resource-constrained systems where you want
29+
# to limit background CPU usage at the cost of slower widget refresh.
30+
#
31+
# :default: false
32+
parallel_rendering=false

0 commit comments

Comments
 (0)