progress: optimize progress bar updates a bit

Rather than erase the entire line first then print out the new content,
print out the new content on top of the old and then erase anything we
didn't update.  This should result in a lot less flashing with faster
terminals.

Bug: https://crbug.com/gerrit/11293
Change-Id: Ie2920b0bf3d5e6f920b8631a1c406444b23cd12d
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/335214
Reviewed-by: LaMont Jones <lamontjones@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
This commit is contained in:
Mike Frysinger 2022-04-19 02:30:09 -04:00
parent b90a422ab6
commit 4c11aebeb9

View File

@ -24,6 +24,11 @@ _NOT_TTY = not os.isatty(2)
# column 0.
CSI_ERASE_LINE = '\x1b[2K'
# This will erase all content in the current line after the cursor. This is
# useful for partial updates & progress messages as the terminal can display
# it better.
CSI_ERASE_LINE_AFTER = '\x1b[K'
def duration_str(total):
"""A less noisy timedelta.__str__.
@ -85,10 +90,10 @@ class Progress(object):
return
if self._total <= 0:
sys.stderr.write('%s\r%s: %d,' % (
CSI_ERASE_LINE,
sys.stderr.write('\r%s: %d,%s' % (
self._title,
self._done))
self._done,
CSI_ERASE_LINE_AFTER))
sys.stderr.flush()
else:
p = (100 * self._done) / self._total
@ -96,14 +101,14 @@ class Progress(object):
jobs = '[%d job%s] ' % (self._active, 's' if self._active > 1 else '')
else:
jobs = ''
sys.stderr.write('%s\r%s: %2d%% %s(%d%s/%d%s)%s%s%s' % (
CSI_ERASE_LINE,
sys.stderr.write('\r%s: %2d%% %s(%d%s/%d%s)%s%s%s%s' % (
self._title,
p,
jobs,
self._done, self._units,
self._total, self._units,
' ' if msg else '', msg,
CSI_ERASE_LINE_AFTER,
'\n' if self._print_newline else ''))
sys.stderr.flush()
@ -113,19 +118,19 @@ class Progress(object):
duration = duration_str(time() - self._start)
if self._total <= 0:
sys.stderr.write('%s\r%s: %d, done in %s\n' % (
CSI_ERASE_LINE,
sys.stderr.write('\r%s: %d, done in %s%s\n' % (
self._title,
self._done,
duration))
duration,
CSI_ERASE_LINE_AFTER))
sys.stderr.flush()
else:
p = (100 * self._done) / self._total
sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s), done in %s\n' % (
CSI_ERASE_LINE,
sys.stderr.write('\r%s: %3d%% (%d%s/%d%s), done in %s%s\n' % (
self._title,
p,
self._done, self._units,
self._total, self._units,
duration))
duration,
CSI_ERASE_LINE_AFTER))
sys.stderr.flush()