From 930ffbe394df8ab4dfd626b908235b52b2a5cbfd Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sat, 4 Mar 2023 11:51:02 +0100 Subject: [PATCH] Cool down progress loop. Previously it actually was very hot and needed an entire CPU for itself due to constant querying of progress information. Now it's slowed down by consistently sleeping for a short amount of time. This time should be short enough to not let the progress bar hold up the overall progress of the fetch operation, hence the 10ms sleep time, reducing the worst-case hold-up to 10ms. --- src/cargo/sources/git/oxide.rs | 36 ++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/cargo/sources/git/oxide.rs b/src/cargo/sources/git/oxide.rs index cf301bbd0111..56d7f820b9ed 100644 --- a/src/cargo/sources/git/oxide.rs +++ b/src/cargo/sources/git/oxide.rs @@ -69,18 +69,34 @@ fn translate_progress_to_bar( // We choose `N=10` here to make a `300ms * 10slots ~= 3000ms` // sliding window for tracking the data transfer rate (in bytes/s). - let mut last_update = Instant::now(); - let mut counter = MetricsCounter::<10>::new(0, last_update); + let mut last_percentage_update = Instant::now(); + let mut last_fast_update = Instant::now(); + let mut counter = MetricsCounter::<10>::new(0, last_percentage_update); let mut tasks = Vec::with_capacity(10); - let update_interval = std::time::Duration::from_millis(300); - let short_check_interval = Duration::from_millis(50); + let slow_check_interval = std::time::Duration::from_millis(300); + let fast_check_interval = Duration::from_millis(50); + let sleep_interval = Duration::from_millis(10); + debug_assert_eq!( + slow_check_interval.as_millis() % fast_check_interval.as_millis(), + 0, + "progress should be smoother by keeping these as multiples of each other" + ); + debug_assert_eq!( + fast_check_interval.as_millis() % sleep_interval.as_millis(), + 0, + "progress should be smoother by keeping these as multiples of each other" + ); while let Some(root) = root.upgrade() { - let not_yet = last_update.elapsed() < update_interval; - if not_yet { - std::thread::sleep(short_check_interval); + std::thread::sleep(sleep_interval); + let needs_update = last_fast_update.elapsed() >= fast_check_interval; + if !needs_update { + continue; } + let now = Instant::now(); + last_fast_update = now; + root.sorted_snapshot(&mut tasks); fn progress_by_id( @@ -115,10 +131,10 @@ fn translate_progress_to_bar( let total_objects = objs.done_at.expect("known amount of objects"); let received_bytes = read_pack.step.load(Ordering::Relaxed); - let now = Instant::now(); - if !not_yet { + let needs_percentage_update = last_percentage_update.elapsed() >= slow_check_interval; + if needs_percentage_update { counter.add(received_bytes, now); - last_update = now; + last_percentage_update = now; } let (rate, unit) = human_readable_bytes(counter.rate() as u64); let msg = format!(", {rate:.2}{unit}/s");