From aab74e1d93141823e844ef2427b5dcc457873475 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 May 2024 11:56:13 +0200 Subject: [PATCH] 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). --- src/shared/pretty-print.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index 2c46f3e2dcf..470aaf77caa 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -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); } -- 2.47.3