From: Lennart Poettering Date: Fri, 24 May 2024 09:56:13 +0000 (+0200) Subject: pretty-print: enable stdio buffering while outputting progress bar X-Git-Tag: v257-rc1~1143 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aab74e1d93141823e844ef2427b5dcc457873475;p=thirdparty%2Fsystemd.git 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). --- 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); }