]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-109276: libregrtest: limit number workers (#109288)
authorVictor Stinner <vstinner@python.org>
Tue, 12 Sep 2023 03:47:04 +0000 (05:47 +0200)
committerGitHub <noreply@github.com>
Tue, 12 Sep 2023 03:47:04 +0000 (03:47 +0000)
Don't spawn more threads than the number of jobs: these worker
threads would never get anything to do.

* Add the number of tests in "Run ... tests in ..." message.
* Add RunTests.get_jobs() method.
* Add plural() function.
* count() uses f-string.

Lib/test/libregrtest/main.py
Lib/test/libregrtest/run_workers.py
Lib/test/libregrtest/runtests.py
Lib/test/libregrtest/utils.py

index f52deac329dc84d153976191f764e8d4fae8a309..a89e3c6a498da6918be365e1144863da8d8ba58c 100644 (file)
@@ -295,7 +295,12 @@ class Regrtest:
 
         save_modules = sys.modules.keys()
 
-        msg = "Run tests sequentially"
+        jobs = runtests.get_jobs()
+        if jobs is not None:
+            tests = f'{jobs} tests'
+        else:
+            tests = 'tests'
+        msg = f"Run {tests} sequentially"
         if runtests.timeout:
             msg += " (timeout: %s)" % format_duration(runtests.timeout)
         self.log(msg)
index 5c665abfeb57bd523dbc860be2d824179d49011d..cfa36f7800943aaebff72b47c0912e4a99b6ab63 100644 (file)
@@ -21,7 +21,7 @@ from .runtests import RunTests
 from .single import PROGRESS_MIN_TIME
 from .utils import (
     StrPath, StrJSON, TestName, MS_WINDOWS,
-    format_duration, print_warning)
+    format_duration, print_warning, plural)
 from .worker import create_worker_process, USE_PROCESS_GROUP
 
 if MS_WINDOWS:
@@ -401,10 +401,24 @@ class RunWorkers:
             self.worker_timeout = None
         self.workers = None
 
+        jobs = self.runtests.get_jobs()
+        if jobs is not None:
+            # Don't spawn more threads than the number of jobs:
+            # these worker threads would never get anything to do.
+            self.num_workers = min(self.num_workers, jobs)
+
     def start_workers(self) -> None:
         self.workers = [WorkerThread(index, self)
                         for index in range(1, self.num_workers + 1)]
-        msg = f"Run tests in parallel using {len(self.workers)} child processes"
+        jobs = self.runtests.get_jobs()
+        if jobs is not None:
+            tests = f'{jobs} tests'
+        else:
+            tests = 'tests'
+        nworkers = len(self.workers)
+        processes = plural(nworkers, "process", "processes")
+        msg = (f"Run {tests} in parallel using "
+               f"{nworkers} worker {processes}")
         if self.timeout:
             msg += (" (timeout: %s, worker timeout: %s)"
                     % (format_duration(self.timeout),
index 656958fa71312fabf786d8a9cbd087af36646ef7..5c68df126e2a8f6b20a0e070b8e964175e74e220 100644 (file)
@@ -53,6 +53,13 @@ class RunTests:
         else:
             return None
 
+    def get_jobs(self):
+        # Number of run_single_test() calls needed to run all tests.
+        # None means that there is not bound limit (--forever option).
+        if self.forever:
+            return None
+        return len(self.tests)
+
     def iter_tests(self):
         if self.forever:
             while True:
index b46cec6f0eec700cd7cf77ebe78c385bb8f3ccd0..ce1b1088127bf7db868b35556d1a63f863d84114 100644 (file)
@@ -70,11 +70,20 @@ def strip_py_suffix(names: list[str]):
             names[idx] = basename
 
 
+def plural(n, singular, plural=None):
+    if n == 1:
+        return singular
+    elif plural is not None:
+        return plural
+    else:
+        return singular + 's'
+
+
 def count(n, word):
     if n == 1:
-        return "%d %s" % (n, word)
+        return f"{n} {word}"
     else:
-        return "%d %ss" % (n, word)
+        return f"{n} {word}s"
 
 
 def printlist(x, width=70, indent=4, file=None):