This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-23648-run-folder in repository https://gitbox.apache.org/repos/asf/camel.git
commit faf9fd7aaa35ff8c7375f2d5d4c61a3ce4c81ffd Author: Claus Ibsen <[email protected]> AuthorDate: Mon Jun 1 10:16:26 2026 +0200 CAMEL-23648: camel-jbang - TUI performance: cache PIDs and optimize refresh Move log reading before the PID scan so logs appear instantly. Cache the PID list and only do a full ProcessHandle.allProcesses() scan on the Overview tab or F3 switch popup. On other tabs reuse cached PIDs with direct ProcessHandle.of() lookups, eliminating the 3-4 second delay. Also add stripAnsi fast-path for lines without escape sequences. Co-Authored-By: Claude Opus 4.6 <[email protected]> --- .../dsl/jbang/core/commands/tui/CamelMonitor.java | 167 ++++++++++++--------- .../dsl/jbang/core/commands/tui/TuiHelper.java | 3 + 2 files changed, 96 insertions(+), 74 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java index b40053bf55db..c3b48163029a 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java @@ -197,6 +197,9 @@ public class CamelMonitor extends CamelCommand { private final Map<String, LoadAvg> cpuLoadAvg = new ConcurrentHashMap<>(); private final Map<String, long[]> prevCpuSample = new ConcurrentHashMap<>(); + // Cached PID list — full process scan only on Overview tab or F3 switch popup + private volatile List<Long> cachedPids = Collections.emptyList(); + // Trace/history data — shared between CamelMonitor and tabs private final AtomicReference<List<TraceEntry>> traces = new AtomicReference<>(Collections.emptyList()); private final Map<String, Long> traceFilePositions = new ConcurrentHashMap<>(); @@ -1696,6 +1699,66 @@ public class CamelMonitor extends CamelCommand { // ---- Data Loading ---- + private void refreshLogData() { + if (tabsState.selected() != TAB_LOG) { + return; + } + String logPid = null; + String logFileName = null; + InfraInfo selInfra = findSelectedInfra(); + if (selInfra != null) { + logPid = selInfra.pid; + logFileName = "infra-" + selInfra.alias + "-" + selInfra.pid + ".log"; + } else { + IntegrationInfo selected = findSelectedIntegration(); + if (selected != null) { + logPid = selected.pid; + logFileName = selected.pid + ".log"; + } + } + if (logPid == null) { + return; + } + if (!logPid.equals(logTab.logFilePid)) { + logTab.mutableFilteredEntries.clear(); + logTab.logFilePos = -1; + logTab.logTotalLinesRead = 0; + logTab.logLineBuffer.setLength(0); + logTab.logLoading = true; + } + // Load older lines when scrolled to the top or Home pressed + boolean loadAll = logTab.loadAllRequested; + if (logTab.logFileStartPos > 0 + && (loadAll || (!logTab.followMode && logTab.scroll == 0))) { + logTab.loadAllRequested = false; + List<String> olderLines = new ArrayList<>(); + logTab.readOlderLogLines(logFileName, loadAll, olderLines); + if (!olderLines.isEmpty()) { + List<LogEntry> olderEntries = new ArrayList<>(); + for (String line : olderLines) { + olderEntries.add(LogTab.parseLogLine(line)); + } + logTab.mutableFilteredEntries.addAll(0, olderEntries); + logTab.logTotalLinesRead += olderLines.size(); + logTab.scroll = olderEntries.size(); + } + } + List<String> newRawLines = new ArrayList<>(); + logTab.readNewLogLinesFromFile(logPid, logFileName, newRawLines); + if (!newRawLines.isEmpty()) { + logTab.logTotalLinesRead += newRawLines.size(); + for (String line : newRawLines) { + logTab.mutableFilteredEntries.add(LogTab.parseLogLine(line)); + } + if (logTab.mutableFilteredEntries.size() > MAX_LOG_LINES) { + logTab.mutableFilteredEntries.subList(0, logTab.mutableFilteredEntries.size() - MAX_LOG_LINES) + .clear(); + } + } + logTab.filteredLogEntries = new ArrayList<>(logTab.mutableFilteredEntries); + logTab.logLoading = false; + } + private void refreshData() { if (runner == null) { refreshDataSync(); @@ -1718,24 +1781,36 @@ public class CamelMonitor extends CamelCommand { private void refreshDataSync() { lastRefresh = System.currentTimeMillis(); try { + // Read log data early — before the heavy PID/status scan + refreshLogData(); + List<IntegrationInfo> infos = new ArrayList<>(); - List<Long> pids = findPids(name); - ProcessHandle.allProcesses() - .filter(ph -> pids.contains(ph.pid())) - .forEach(ph -> { - JsonObject root = loadStatus(ph.pid()); - if (root != null) { - IntegrationInfo info = StatusParser.parseIntegration(ph, root); - if (info != null) { - infos.add(info); - updateThroughputHistory(info); - updateEndpointHistory(info); - updateCbHistory(info); - updateHeapHistory(info); - updateLoadMetrics(ph, info); - } - } - }); + boolean fullScan = tabsState.selected() == TAB_OVERVIEW || showSwitchPopup || cachedPids.isEmpty(); + List<Long> pids; + if (fullScan) { + pids = findPids(name); + cachedPids = pids; + } else { + pids = cachedPids; + } + for (Long pid : pids) { + JsonObject root = loadStatus(pid); + if (root != null) { + ProcessHandle ph = ProcessHandle.of(pid).orElse(null); + if (ph == null) { + continue; + } + IntegrationInfo info = StatusParser.parseIntegration(ph, root); + if (info != null) { + infos.add(info); + updateThroughputHistory(info); + updateEndpointHistory(info); + updateCbHistory(info); + updateHeapHistory(info); + updateLoadMetrics(ph, info); + } + } + } // Detect disappeared integrations and start vanishing Set<String> livePids = infos.stream().map(i -> i.pid).collect(Collectors.toSet()); @@ -1851,63 +1926,7 @@ public class CamelMonitor extends CamelCommand { } } - // Refresh log data only when the Log tab is visible - if (tabsState.selected() == TAB_LOG) { - String logPid = null; - String logFileName = null; - InfraInfo selInfra = findSelectedInfra(); - if (selInfra != null) { - logPid = selInfra.pid; - logFileName = "infra-" + selInfra.alias + "-" + selInfra.pid + ".log"; - } else { - IntegrationInfo selected = findSelectedIntegration(); - if (selected != null) { - logPid = selected.pid; - logFileName = selected.pid + ".log"; - } - } - if (logPid != null) { - if (!logPid.equals(logTab.logFilePid)) { - logTab.mutableFilteredEntries.clear(); - logTab.logFilePos = -1; - logTab.logTotalLinesRead = 0; - logTab.logLineBuffer.setLength(0); - logTab.logLoading = true; - } - List<String> newRawLines = new ArrayList<>(); - // Load older lines when scrolled to the top or Home pressed - boolean loadAll = logTab.loadAllRequested; - if (logTab.logFileStartPos > 0 - && (loadAll || (!logTab.followMode && logTab.scroll == 0))) { - logTab.loadAllRequested = false; - List<String> olderLines = new ArrayList<>(); - logTab.readOlderLogLines(logFileName, loadAll, olderLines); - if (!olderLines.isEmpty()) { - List<LogEntry> olderEntries = new ArrayList<>(); - for (String line : olderLines) { - olderEntries.add(LogTab.parseLogLine(line)); - } - logTab.mutableFilteredEntries.addAll(0, olderEntries); - logTab.logTotalLinesRead += olderLines.size(); - // Adjust scroll to keep the same content visible - logTab.scroll = olderEntries.size(); - } - } - logTab.readNewLogLinesFromFile(logPid, logFileName, newRawLines); - if (!newRawLines.isEmpty()) { - logTab.logTotalLinesRead += newRawLines.size(); - for (String line : newRawLines) { - logTab.mutableFilteredEntries.add(LogTab.parseLogLine(line)); - } - if (logTab.mutableFilteredEntries.size() > MAX_LOG_LINES) { - logTab.mutableFilteredEntries.subList(0, logTab.mutableFilteredEntries.size() - MAX_LOG_LINES) - .clear(); - } - } - logTab.filteredLogEntries = new ArrayList<>(logTab.mutableFilteredEntries); - logTab.logLoading = false; - } - } + // Log data is now refreshed at the top of refreshDataSync() via refreshLogData() // Scope history/error/trace refresh to the selected integration only List<Long> selectedPids = selectedPidAsList(); diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java index ea967b02d759..c8ab629ca13c 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java @@ -183,6 +183,9 @@ final class TuiHelper { if (line == null || line.isEmpty()) { return line; } + if (line.indexOf('\u001B') < 0 && line.indexOf('\r') < 0 && line.indexOf('\t') < 0) { + return line; + } StringBuilder sb = new StringBuilder(line.length()); int i = 0; while (i < line.length()) {
