-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dd: use an alarm thread instead of elapsed() calls #4447
Conversation
Quick benchmark on FreeBSD 13.1-RELEASE: Summary './dd-thread-alarm if=/dev/zero of=/dev/null count=4000000 status=progress' ran 1.17 ± 0.17 times faster than './dd-baseline if=/dev/zero of=/dev/null count=4000000 status=progress'
One small change in behaviour I observe is the initial progress update is now delayed by a second. This matches both FreeBSD and GNU dd behaviour, and that first report after a single block has been copied isn't very useful anyway. |
Cool! It's a nice solution. In your experiments,
This should be fine. If we really want to we could just send an empty update before the loop if we want to create the progress bar early. |
Yes, my tests are against BSD dd. I do have GNU coreutils 9.1 installed, and it looks to roughly match uutils baseline:
And indeed it looks to follow the same approach as baseline: if (status_level == STATUS_PROGRESS)
{
xtime_t progress_time = gethrxtime ();
if (next_time <= progress_time)
{
print_xfer_stats (progress_time);
next_time += XTIME_PRECISION;
}
} |
Thanks for checking! This approach seems to be similar to what indicatif is doing for their progress bars too, so I think this makes sense. |
trigger: Arc<AtomicBool>, | ||
} | ||
|
||
impl Alarm { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be nice if you could add some documentations / comment here :)
Sorry for the latency. Could you please add your benchmark in src/uu/dd/BENCHMARKING.md if it isn't covered? thanks |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't check the code out locally, but this makes sense to me
let trigger = Arc::new(AtomicBool::default()); | ||
|
||
let weak_trigger = Arc::downgrade(&trigger); | ||
thread::spawn(move || { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So now if I understand correctly, there are three threads: the main thread, this thread which has a periodic alarm, and the progress output thread. Is that right?
dd
's main IO loop makes anInstant::elapsed
call for every block copied for updating the display thread. When I implemented status=progress support in FreeBSD's dd I used a SIGALRM to set a flag in much the same way its SIGINFO support worked, which avoids all those timekeeping calls.This isn't portable, but a similar approach can be used with a thread in a sleep loop and an atomic flag. I knocked one together and ran a comparison with FreeBSD/amd64 13.1-RELEASE on an AMD 5700X:
dd-no-timekeeping
has the elapsed() call completely elided and doesn't respect status=progress,dd-thread-alarm
is this patch, anddd-baseline
is unmodified uutils. It would be interesting to see if this holds up on other platforms and other situations.I just messily dumped
Alarm
near the top of the file for now.