perf(tui): optimize graph rendering and increase UI responsiveness
Rust CI / cargo fmt (push) Successful in 18s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 33s
Rust CI / cargo clippy (push) Successful in 34s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 7s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m14s
Rust CI / cargo doc (push) Successful in 24s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 29s
Supply chain / cargo-deny advisories (push) Successful in 6s
Supply chain / cargo-deny bans licenses sources (push) Successful in 5s
Supply chain / actionlint (push) Successful in 2s
Netem Interop / netem interop (push) Successful in 1m5s

Efficiently sample data within the viewport for graph series and reduce the rendering interval for a smoother user experience.
This commit is contained in:
Nils Andreas Svee committed 2026-10-06 14:39:05 +07:00
1 parent 8e4424764d
commit b98d1001de
2 files changed
+20 -8

No files matched your search

+1 -1
View File
@@ -26,7 +26,7 @@ use tokio::{
time::{sleep, Instant},
};
const RENDER_INTERVAL: Duration = Duration::from_millis(250);
const RENDER_INTERVAL: Duration = Duration::from_millis(100);
pub async fn run_tui(
args: TuiArgs,
+19 -7
View File
@@ -1272,13 +1272,27 @@ fn target_metric_series(
viewport: GraphViewportRange,
metric: GraphMetric,
) -> Option<ChartSeries> {
let points = target.graph_history.iter().filter_map(|sample| {
// Histories are monotonic. Skip old samples without converting every
// retained measurement on each repaint, then keep the nearest valid
// predecessor for interpolation across the left boundary.
let first = target
.graph_history
.partition_point(|sample| sample.timestamp.mono < viewport.start);
let mut previous = target
.graph_history
.range(..first)
.rev()
.find_map(|sample| {
metric
.value_ns(sample)
.map(|ns| (sample.timestamp.mono, ns as f64 / 1_000_000.0))
});
let points = target.graph_history.range(first..).filter_map(|sample| {
metric
.value_ns(sample)
.map(|ns| (sample.timestamp.mono, ns as f64 / 1_000_000.0))
});
let mut data = Vec::new();
let mut previous: Option<(Instant, f64)> = None;
for point in points {
if let Some(before) = previous {
// Only genuine crossing segments contribute boundary points. In
@@ -1423,12 +1437,10 @@ fn graph_timestamp_anchor(state: &TuiState, end: Instant) -> Option<ClientTimest
.targets
.iter()
.filter_map(|target| {
target
let after = target
.graph_history
.iter()
.rev()
.find(|sample| sample.timestamp.mono <= end)
.or_else(|| target.graph_history.front())
.partition_point(|sample| sample.timestamp.mono <= end);
target.graph_history.get(after.saturating_sub(1))
})
.map(|sample| sample.timestamp)
.min_by_key(|timestamp| {