other: Speed up first draw and first data collection (#1100)

* other: add first draw immediately after initialization

Previously, I would only do the first draw after an event triggered, so
this just makes it so that I *always* draw once first. Some widgets look
a bit weird with no data, but this is fine I guess if we want to gain a
bit of responsiveness.

* other: potentially shorten first time to get data

* other: move event loop thread init earlier in app initialization
This commit is contained in:
Clement Tsang 2023-04-15 00:15:36 -04:00 committed by GitHub
parent fa1f4976e2
commit 20902e87b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 20 deletions

View File

@ -20,7 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#1016](https://github.com/ClementTsang/bottom/pull/1016): Add support for displaying process usernames on Windows. - [#1016](https://github.com/ClementTsang/bottom/pull/1016): Add support for displaying process usernames on Windows.
- [#1022](https://github.com/ClementTsang/bottom/pull/1022): Support three-character hex colour strings for styling. - [#1022](https://github.com/ClementTsang/bottom/pull/1022): Support three-character hex colour strings for styling.
- [#1024](https://github.com/ClementTsang/bottom/pull/1024): Support FreeBSD temperature sensors based on `hw.temperature`. - [#1024](https://github.com/ClementTsang/bottom/pull/1024): Support FreeBSD temperature sensors based on `hw.temperature`.
- [#1063](https://github.com/ClementTsang/bottom/pull/1063): Add buffer and cache memory tracking - [#1063](https://github.com/ClementTsang/bottom/pull/1063): Add buffer and cache memory tracking.
## Changes ## Changes
@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Other ## Other
- [#1100](https://github.com/ClementTsang/bottom/pull/1100): Speed up first draw and first data collection.
## [0.8.0] - 2023-01-22 ## [0.8.0] - 2023-01-22
## Bug Fixes ## Bug Fixes

View File

@ -194,7 +194,20 @@ impl DataCollector {
self.update_data(); self.update_data();
std::thread::sleep(std::time::Duration::from_millis(250)); // Sleep a few seconds to avoid potentially weird data...
let sleep_duration = {
cfg_if::cfg_if! {
if #[cfg(target_os = "freebsd")] {
// FreeBSD's min duration value is 1s, which is a bit too long for me so I'll accept the one-time
// inaccuracy.
std::time::Duration::from_millis(250)
} else {
sysinfo::System::MINIMUM_CPU_UPDATE_INTERVAL + Duration::from_millis(1)
}
}
};
std::thread::sleep(sleep_duration);
self.data.cleanup(); self.data.cleanup();
} }

View File

@ -993,7 +993,7 @@ Supported widget names:
} }
} }
#[derive(Clone, Default, Debug)] #[derive(Clone, Default, Debug, Copy)]
pub struct UsedWidgets { pub struct UsedWidgets {
pub use_cpu: bool, pub use_cpu: bool,
pub use_mem: bool, pub use_mem: bool,

View File

@ -42,7 +42,7 @@ fn main() -> Result<()> {
// let _profiler = dhat::Profiler::new_heap(); // let _profiler = dhat::Profiler::new_heap();
let matches = clap::get_matches(); let matches = clap::get_matches();
#[cfg(all(feature = "fern", debug_assertions))] #[cfg(all(feature = "fern"))]
{ {
utils::logging::init_logger(log::LevelFilter::Debug, std::ffi::OsStr::new("debug.log"))?; utils::logging::init_logger(log::LevelFilter::Debug, std::ffi::OsStr::new("debug.log"))?;
} }
@ -85,15 +85,28 @@ fn main() -> Result<()> {
let thread_termination_lock = Arc::new(Mutex::new(false)); let thread_termination_lock = Arc::new(Mutex::new(false));
let thread_termination_cvar = Arc::new(Condvar::new()); let thread_termination_cvar = Arc::new(Condvar::new());
// Set up input handling
let (sender, receiver) = mpsc::channel(); let (sender, receiver) = mpsc::channel();
// Set up event loop thread; we set this up early to speed up first-time-to-data.
let (collection_thread_ctrl_sender, collection_thread_ctrl_receiver) = mpsc::channel();
let _collection_thread = create_collection_thread(
sender.clone(),
collection_thread_ctrl_receiver,
thread_termination_lock.clone(),
thread_termination_cvar.clone(),
&app.app_config_fields,
app.filters.clone(),
app.used_widgets,
);
// Set up input handling loop thread.
let _input_thread = create_input_thread(sender.clone(), thread_termination_lock.clone()); let _input_thread = create_input_thread(sender.clone(), thread_termination_lock.clone());
// Cleaning loop // Set up cleaning loop thread.
let _cleaning_thread = { let _cleaning_thread = {
let lock = thread_termination_lock.clone(); let lock = thread_termination_lock.clone();
let cvar = thread_termination_cvar.clone(); let cvar = thread_termination_cvar.clone();
let cleaning_sender = sender.clone(); let cleaning_sender = sender;
let offset_wait_time = app.app_config_fields.retention_ms + 60000; let offset_wait_time = app.app_config_fields.retention_ms + 60000;
thread::spawn(move || { thread::spawn(move || {
loop { loop {
@ -114,19 +127,7 @@ fn main() -> Result<()> {
}) })
}; };
// Event loop // Set up tui and crossterm
let (collection_thread_ctrl_sender, collection_thread_ctrl_receiver) = mpsc::channel();
let _collection_thread = create_collection_thread(
sender,
collection_thread_ctrl_receiver,
thread_termination_lock.clone(),
thread_termination_cvar.clone(),
&app.app_config_fields,
app.filters.clone(),
app.used_widgets.clone(),
);
// Set up up tui and crossterm
let mut stdout_val = stdout(); let mut stdout_val = stdout();
execute!( execute!(
stdout_val, stdout_val,
@ -162,6 +163,9 @@ fn main() -> Result<()> {
})?; })?;
let mut first_run = true; let mut first_run = true;
// Draw once first to initialize the canvas, so it doesn't feel like it's frozen.
try_drawing(&mut terminal, &mut app, &mut painter)?;
while !is_terminated.load(Ordering::SeqCst) { while !is_terminated.load(Ordering::SeqCst) {
// TODO: Would be good to instead use a mix of is_terminated check + recv. Probably use a termination event instead. // TODO: Would be good to instead use a mix of is_terminated check + recv. Probably use a termination event instead.
if let Ok(recv) = receiver.recv_timeout(Duration::from_millis(TICK_RATE_IN_MILLISECONDS)) { if let Ok(recv) = receiver.recv_timeout(Duration::from_millis(TICK_RATE_IN_MILLISECONDS)) {