pretty-print: enable stdio buffering while outputting progress bar

Writing the progress bar so far was irritatingly slow, which was caused
by the fact that the various things we output so far resulted in one
write() syscall each because STDERR is unbuffered by default.

Let's fix that, and temporarily turn on full buffering for stderr,
restoring the normal unbuffered output right after.

This makes progress bar print visibly more efficient (and flicker free
too, since terminals no longer will move the cursor around during
output).
This commit is contained in:
Lennart Poettering 2024-05-24 11:56:13 +02:00 committed by Luca Boccassi
parent bba55185de
commit aab74e1d93

View file

@ -461,6 +461,12 @@ bool shall_tint_background(void) {
void draw_progress_bar(const char *prefix, double percentage) {
/* We are going output a bunch of small strings that shall appear as a single line to STDERR which is
* unbuffered by default. Let's temporarily turn on full buffering, so that this is passed to the tty
* as a single buffer, to make things more efficient. */
char buffer[LONG_LINE_MAX];
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
fputc('\r', stderr);
if (prefix)
fputs(prefix, stderr);
@ -512,10 +518,16 @@ void draw_progress_bar(const char *prefix, double percentage) {
fputc('\r', stderr);
fflush(stderr);
/* Disable buffering again */
setvbuf(stderr, NULL, _IONBF, 0);
}
void clear_progress_bar(const char *prefix) {
char buffer[LONG_LINE_MAX];
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
fputc('\r', stderr);
if (terminal_is_dumb())
@ -526,4 +538,7 @@ void clear_progress_bar(const char *prefix) {
fputc('\r', stderr);
fflush(stderr);
/* Disable buffering again */
setvbuf(stderr, NULL, _IONBF, 0);
}