-
Notifications
You must be signed in to change notification settings - Fork 277
Description
I'm trying to run a few operations on files while "logging" the files using MultiProgress::println. This leads to unexpected results:
8.01 MiB: SomeFile1.ext
Bytes copied: #####----------------------- 2.37 GiB / 69.64 GiB ETA: 14m
8.60 MiB: SomeFile2.ext
17.33 MiB: SomeFile3.ext
Bytes copied: #####----------------------- 2.37 GiB / 69.64 GiB ETA: 14m
▹▹▹ SomeFile4.ext
Copying: ===>
The last three lines (and the two log entries before that) are completely fine, but, as you can see, there are "copies" of the progress bar interleaved with the logged output. I'm calling them dummies or ghosts, for lack of a better word.
Because of excessive flickering, I've already done the following:
- buffer log entries to some extend
- throttle log prints
However, this still happens. I've noticed that it seems to be happening mostly when there are lots of files being processed quickly (eg. they are very small); for larger files, this seems to be working fine almost all the time.
// ...
// Prepare buffer for file name logging, if enabled
// `Task` is an externally defined type
let mut filename_buffer: VecDeque<Task> = VecDeque::with_capacity(20);
// Tracks the last time the buffer was flushed
let mut last_filename_log = Instant::now();
// Target buffer flushing interval
let filename_log_interval = Duration::from_millis(500);
// Little helper allows easy call to "flush buffer" from multiple locations
let log_files = |buffer: &mut VecDeque<Task>| {
for file in buffer.drain(..) {
// For every buffered task, print it's size and relative path; both part of `Task`
// `progress` is MultiProgress
let _ = progress.println(format!(
"{:>10}: {}",
match &file {
Task::Copy(task) => bytes_to_str(task.bytes).dimmed().bold(),
Task::Delete(_) => "DEL".dimmed().bold()
},
file.relative().dimmed()
));
}
Instant::now()
};
// ...
for task in tasks {
// If logging enabled at all AND interval is reached OR buffer is at capacity
// (don't want it to grow too large, this would hinder realtime readability
// and use needless memory), print all lines from buffer
if args.log_files && (
filename_buffer.len() >= 20 ||
last_filename_log.elapsed() >= filename_log_interval
) { last_filename_log = log_files(&mut filename_buffer); }
// ...Any help would be greatly appreciated; for me, multi::println would be a significant asset in my little project.