From d0e3af34ebf5f01bc1923e0024667200361a104b Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 9 Aug 2020 19:38:24 +0800 Subject: [PATCH] first attempt to bring throughput to TUI --- examples/shared/mod.rs | 1 + src/line/draw.rs | 6 +++--- src/tree/throughput.rs | 10 +++++++--- src/tui/draw/all.rs | 5 +++-- src/tui/draw/progress.rs | 33 ++++++++++++++++++++++++++++----- src/tui/engine.rs | 11 +++++------ 6 files changed, 47 insertions(+), 19 deletions(-) diff --git a/examples/shared/mod.rs b/examples/shared/mod.rs index 3f7c937..bb4e94f 100644 --- a/examples/shared/mod.rs +++ b/examples/shared/mod.rs @@ -64,6 +64,7 @@ pub fn launch_ambient_gui( title: TITLES.choose(&mut thread_rng()).copied().unwrap().into(), frames_per_second: args.fps, recompute_column_width_every_nth_frame: args.recompute_column_width_every_nth_frame, + throughput: true, ..tui::Options::default() }, futures_util::stream::select( diff --git a/src/line/draw.rs b/src/line/draw.rs index 7adea10..ec05a54 100644 --- a/src/line/draw.rs +++ b/src/line/draw.rs @@ -134,7 +134,7 @@ pub fn all( } let mut tokens: Vec> = Vec::with_capacity(4); let mut max_midpoint = 0; - for ((key, progress), ref mut blocks_in_last_iteration) in state + for ((key, value), ref mut blocks_in_last_iteration) in state .tree .iter() .filter(|(k, _)| level_range.contains(&k.level())) @@ -143,14 +143,14 @@ pub fn all( max_midpoint = max_midpoint.max( format_progress( key, - progress, + value, config.terminal_dimensions.0, config.colored, state.last_progress_midpoint, state .throughput .as_mut() - .and_then(|tp| tp.update_and_get(key, progress)), + .and_then(|tp| tp.update_and_get(key, value.progress.as_ref())), &mut tokens, ) .unwrap_or(0), diff --git a/src/tree/throughput.rs b/src/tree/throughput.rs index 354f411..d601f90 100644 --- a/src/tree/throughput.rs +++ b/src/tree/throughput.rs @@ -1,4 +1,4 @@ -use crate::{progress, tree, unit}; +use crate::{progress, tree, unit, Progress}; use std::time::{Duration, SystemTime}; const THROTTLE_INTERVAL: Duration = Duration::from_secs(1); @@ -68,8 +68,12 @@ impl Throughput { self.updated_at = Some(now); } - pub fn update_and_get(&mut self, key: &tree::Key, value: &progress::Value) -> Option { - value.progress.as_ref().and_then(|progress| { + pub fn update_and_get( + &mut self, + key: &tree::Key, + progress: Option<&Progress>, + ) -> Option { + progress.and_then(|progress| { self.elapsed .and_then(|elapsed| match self.sorted_by_key.binary_search_by_key(key, |t| t.0) { Ok(index) => self.sorted_by_key[index].1.update(progress.step, elapsed), diff --git a/src/tui/draw/all.rs b/src/tui/draw/all.rs index 68fd2e7..6b4cbb3 100644 --- a/src/tui/draw/all.rs +++ b/src/tui/draw/all.rs @@ -1,5 +1,6 @@ use crate::{ progress::Value, + tree, tree::{Key, Message}, tui::{ draw, @@ -16,7 +17,7 @@ use tui::{ widgets::{Block, Borders, Widget}, }; -#[derive(Default, Clone, Eq, PartialEq)] +#[derive(Default)] pub struct State { pub title: String, pub task_offset: u16, @@ -30,7 +31,7 @@ pub struct State { pub maximize_info: bool, pub last_tree_column_width: Option, pub next_tree_column_width: Option, - pub elapsed: Option, + pub throughput: Option, } pub(crate) fn all( diff --git a/src/tui/draw/progress.rs b/src/tui/draw/progress.rs index 19ff934..976ea61 100644 --- a/src/tui/draw/progress.rs +++ b/src/tui/draw/progress.rs @@ -1,7 +1,7 @@ use crate::{ progress::{self, Step, Value}, time::format_now_datetime_seconds, - tree::Key, + tree::{self, Key}, tui::{ draw::State, utils::{ @@ -57,8 +57,22 @@ pub fn pane(entries: &[(Key, progress::Value)], mut bound: Rect, buf: &mut Buffe } { + if let Some(tp) = state.throughput.as_mut() { + tp.update_elapsed(); + } + let progress_area = rect::offset_x(bound, desired_max_tree_draw_width); - draw_progress(entries, buf, progress_area, state.task_offset, state.elapsed); + draw_progress( + entries, + buf, + progress_area, + state.task_offset, + state.throughput.as_mut(), + ); + + if let Some(tp) = state.throughput.as_mut() { + tp.reconcile(entries); + } } if needs_overflow_line { @@ -155,7 +169,13 @@ fn has_child(entries: &[(Key, Value)], index: usize) -> bool { .unwrap_or(false) } -pub fn draw_progress(entries: &[(Key, Value)], buf: &mut Buffer, bound: Rect, offset: u16, _elapsed: Option) { +pub fn draw_progress( + entries: &[(Key, Value)], + buf: &mut Buffer, + bound: Rect, + offset: u16, + mut throughput: Option<&mut tree::Throughput>, +) { let title_spacing = 2u16 + 1; // 2 on the left, 1 on the right let max_progress_label_width = entries .iter() @@ -172,13 +192,16 @@ pub fn draw_progress(entries: &[(Key, Value)], buf: &mut Buffer, bound: Rect, of None => state, }); - for (line, (entry_index, (_, Value { progress, name: title }))) in entries + for (line, (entry_index, (key, Value { progress, name: title }))) in entries .iter() .enumerate() .skip(offset as usize) .take(bound.height as usize) .enumerate() { + let throughput = throughput + .as_mut() + .and_then(|tp| tp.update_and_get(key, progress.as_ref())); let line_bound = rect::line_bound(bound, line); let progress_text = format!( " {progress}", @@ -189,7 +212,7 @@ pub fn draw_progress(entries: &[(Key, Value)], buf: &mut Buffer, bound: Rect, of } else { 0 }, - None + throughput ) ); diff --git a/src/tui/engine.rs b/src/tui/engine.rs index 61a50ad..2cc905d 100644 --- a/src/tui/engine.rs +++ b/src/tui/engine.rs @@ -1,9 +1,9 @@ -use crate::{tree::Root, tui::draw, tui::ticker}; +use crate::{tree, tree::Root, tui::draw, tui::ticker}; use futures_util::StreamExt; use std::{ io::{self, Write}, - time::{Duration, SystemTime}, + time::Duration, }; use tui::layout::Rect; @@ -153,6 +153,9 @@ pub fn render_with_input( duration_per_frame, ..draw::State::default() }; + if throughput { + state.throughput = Some(tree::Throughput::default()); + } let mut interrupt_mode = InterruptDrawInfo::Instantly; let mut entries = Vec::with_capacity(progress.num_tasks()); let mut messages = Vec::with_capacity(progress.messages_capacity()); @@ -164,7 +167,6 @@ pub fn render_with_input( let mut tick = 0usize; let store_task_size_every = recompute_column_width_every_nth_frame.unwrap_or(1).max(1); - let mut time_of_previous_draw_request = None::; while let Some(event) = events.next().await { let mut skip_redraw = false; match event { @@ -223,9 +225,6 @@ pub fn render_with_input( progress.copy_messages(&mut messages); } - let now = SystemTime::now(); - state.elapsed = time_of_previous_draw_request.and_then(|then| now.duration_since(then).ok()); - time_of_previous_draw_request = Some(now); draw::all(&mut state, interrupt_mode, &entries, &messages, window_size, buf); if tick == 1 || tick % store_task_size_every == 0 || state.last_tree_column_width.unwrap_or(0) == 0 { state.next_tree_column_width = state.last_tree_column_width;