From 7c755e5c51d4e79e0b4e95f19ee17cf9595eb4a8 Mon Sep 17 00:00:00 2001 From: Benjamin A. Beasley Date: Oct 01 2025 10:35:39 +0000 Subject: [PATCH 1/2] Don’t set up upload progress when stdout isn’t a tty This saves effort compared to setting up the progress callback and then always checking if stdout is a tty. Signed-off-by: Benjamin A. Beasley --- diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py index 5929fc9..4f4a633 100644 --- a/pyrpkg/lookaside.py +++ b/pyrpkg/lookaside.py @@ -65,11 +65,6 @@ class CGILookasideCache(object): self.download_path = '%(name)s/%(filename)s/%(hashtype)s/%(hash)s/%(filename)s' def print_progress(self, to_download, downloaded, to_upload, uploaded): - if not sys.stdout.isatty(): - # Don't print progress if not outputting into TTY. The progress - # output is not useful in logs. - return - if to_download > 0: done = downloaded / to_download @@ -174,8 +169,13 @@ class CGILookasideCache(object): c = pycurl.Curl() c.setopt(pycurl.URL, url) c.setopt(pycurl.HTTPHEADER, ['Pragma:']) - c.setopt(pycurl.NOPROGRESS, False) - c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress) + if sys.stdout.isatty(): + c.setopt(pycurl.NOPROGRESS, False) + c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress) + else: + # Don't print progress if not outputting into TTY. The progress + # output is not useful in logs. + c.setopt(pycurl.NOPROGRESS, True) c.setopt(pycurl.OPT_FILETIME, True) c.setopt(pycurl.LOW_SPEED_LIMIT, 1000) c.setopt(pycurl.LOW_SPEED_TIME, 60) @@ -334,8 +334,13 @@ class CGILookasideCache(object): c = pycurl.Curl() c.setopt(pycurl.URL, self.upload_url) - c.setopt(pycurl.NOPROGRESS, False) - c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress) + if sys.stdout.isatty(): + c.setopt(pycurl.NOPROGRESS, False) + c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress) + else: + # Don't print progress if not outputting into TTY. The progress + # output is not useful in logs. + c.setopt(pycurl.NOPROGRESS, True) c.setopt(pycurl.HTTPPOST, post_data) c.setopt(pycurl.FOLLOWLOCATION, 1) From 241a724ef7f1ae7e460c86316ed59ca48e69d7e7 Mon Sep 17 00:00:00 2001 From: Benjamin A. Beasley Date: Oct 01 2025 10:35:51 +0000 Subject: [PATCH 2/2] Only update the progress bar when meaningfully changed Remember the last reported progress in per mille (tenths of a percent) and only update the progress bar when this integer value changes. This should fix high CPU usage (to the extent the upload is CPU-limited rather than network-limited) in large file uploads. Signed-off-by: Benjamin A. Beasley --- diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py index 4f4a633..c86e952 100644 --- a/pyrpkg/lookaside.py +++ b/pyrpkg/lookaside.py @@ -64,6 +64,12 @@ class CGILookasideCache(object): self.download_path = '%(name)s/%(filename)s/%(hashtype)s/%(hash)s/%(filename)s' + # Remember the last printed progress fraction in tenths of a percent; + # used to throttle useless progress updates by printing only when the + # value changes. This should ideally be reset to an invalid value like + # -1 each time the progress callback is configured. + self._last_progress_per_mille = -1 + def print_progress(self, to_download, downloaded, to_upload, uploaded): if to_download > 0: done = downloaded / to_download @@ -74,9 +80,14 @@ class CGILookasideCache(object): else: return + per_mille = int(done * 1000) + if per_mille == self._last_progress_per_mille: + return # No need to update the progress bar + + self._last_progress_per_mille = per_mille done_chars = int(done * 72) remain_chars = 72 - done_chars - done = int(done * 1000) / 10.0 + done = per_mille / 10.0 p = "\r%s%s %s%%" % ("#" * done_chars, " " * remain_chars, done) sys.stdout.write(p) @@ -170,6 +181,7 @@ class CGILookasideCache(object): c.setopt(pycurl.URL, url) c.setopt(pycurl.HTTPHEADER, ['Pragma:']) if sys.stdout.isatty(): + self._last_progress_per_mille = -1 c.setopt(pycurl.NOPROGRESS, False) c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress) else: @@ -335,6 +347,7 @@ class CGILookasideCache(object): c = pycurl.Curl() c.setopt(pycurl.URL, self.upload_url) if sys.stdout.isatty(): + self._last_progress_per_mille = -1 c.setopt(pycurl.NOPROGRESS, False) c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress) else: