From 6901a034eee5aa846a6b7301e5183e3578fb115b Mon Sep 17 00:00:00 2001 From: zitterbewegung Date: Tue, 25 Apr 2023 18:02:15 -0500 Subject: [PATCH 1/7] gh-82054: Executing tests in parallel by sharding. --- Lib/test/libregrtest/runtest.py | 38 +++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index e9bb72a7d77ee1..28117564608ed0 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -143,6 +143,14 @@ def __str__(self) -> str: # set of tests that we don't want to be executed when using regrtest NOTTESTS = set() +# If these test directories are encountered recurse into them and treat each +# test_ .py or dir as a separate test module. This can increase parallelism. +# Beware this can't generally be done for any directory with sub-tests as the +# __init__.py may do things which alter what tests are to be run. +SPLITTESTDIRS = { + "test_asyncio", + "test_compiler", +} # Storage of uncollectable objects FOUND_GARBAGE = [] @@ -158,18 +166,26 @@ def findtestdir(path=None): return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir -def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): - """Return a list of all applicable test modules.""" - testdir = findtestdir(testdir) - names = os.listdir(testdir) - tests = [] - others = set(stdtests) | nottests - for name in names: - mod, ext = os.path.splitext(name) - if mod[:5] == "test_" and ext in (".py", "") and mod not in others: - tests.append(mod) - return stdtests + sorted(tests) + def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS, splittestdirs=SPLITTESTDIRS, base_mod=""): + """Return a list of all applicable test modules.""" + testdir = findtestdir(testdir) + names = os.listdir(testdir) + tests = [] + others = set(stdtests) | nottests + for name in names: + mod, ext = os.path.splitext(name) + if mod[:5] == "test_" and mod not in others: + if mod in splittestdirs: + subdir = os.path.join(testdir, mod) + if len(base_mod): + mod = f"{base_mod}.{mod}" + else: + mod = f"test.{mod}" + tests.extend(findtests(subdir, [], nottests, splittestdirs, mod)) + elif ext in (".py", ""): + tests.append(f"{base_mod}.{mod}" if len(base_mod) else mod) + return stdtests + sorted(tests) def get_abs_module(ns: Namespace, test_name: str) -> str: if test_name.startswith('test.') or ns.testdir: From 851c5f6fcea333654f5984229426d797fa843707 Mon Sep 17 00:00:00 2001 From: Joshua Herman Date: Tue, 25 Apr 2023 17:22:34 -0600 Subject: [PATCH 2/7] Fixing syntax error in commit --- Lib/test/libregrtest/runtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index 28117564608ed0..64bdcf046dcfaa 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -167,7 +167,7 @@ def findtestdir(path=None): - def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS, splittestdirs=SPLITTESTDIRS, base_mod=""): +def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS, splittestdirs=SPLITTESTDIRS, base_mod=""): """Return a list of all applicable test modules.""" testdir = findtestdir(testdir) names = os.listdir(testdir) From 95799b62ef4495b64768ad3fbaa83813d9337000 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 25 Apr 2023 23:56:06 +0000 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst diff --git a/Misc/NEWS.d/next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst b/Misc/NEWS.d/next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst new file mode 100644 index 00000000000000..445ad8810d7670 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst @@ -0,0 +1 @@ +Porting parallel test execution from cinder by sharding test execution. Note that this is being done only on the asyncio and compiler tests since they are executed serially. From f4b476b4419ccbf53ce50382265458cb3237f25d Mon Sep 17 00:00:00 2001 From: zitterbewegung Date: Tue, 25 Apr 2023 19:06:09 -0500 Subject: [PATCH 4/7] gh-82054 Removing news entry since end users won't be impacted. --- .../next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst diff --git a/Misc/NEWS.d/next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst b/Misc/NEWS.d/next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst deleted file mode 100644 index 445ad8810d7670..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-04-25-23-56-04.gh-issue-gh-82054.3GgB66.rst +++ /dev/null @@ -1 +0,0 @@ -Porting parallel test execution from cinder by sharding test execution. Note that this is being done only on the asyncio and compiler tests since they are executed serially. From 9365e990b8089e385430b04bbb486d92eb0b882a Mon Sep 17 00:00:00 2001 From: Joshua Herman Date: Tue, 25 Apr 2023 19:56:08 -0600 Subject: [PATCH 5/7] Update runtest.py to not have test_compiler since this does nothing. --- Lib/test/libregrtest/runtest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index 64bdcf046dcfaa..6ab97658f66c09 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -148,8 +148,7 @@ def __str__(self) -> str: # Beware this can't generally be done for any directory with sub-tests as the # __init__.py may do things which alter what tests are to be run. SPLITTESTDIRS = { - "test_asyncio", - "test_compiler", + "test_asyncio" } # Storage of uncollectable objects From 9ffd6b72403a9ef8d6572a560431fbe954f006a7 Mon Sep 17 00:00:00 2001 From: Joshua Jay Herman Date: Thu, 27 Apr 2023 10:08:49 -0600 Subject: [PATCH 6/7] This allows the test runner to execute test_multiprocessing and test_asyncio in parallel By sharding the individual tests in test_multiprocessing and test_asyncio we are able to reduce considerably the time it takes to run the whole test suite. --- Lib/test/libregrtest/runtest.py | 39 +++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index 6ab97658f66c09..70933e1ccb571a 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -148,7 +148,8 @@ def __str__(self) -> str: # Beware this can't generally be done for any directory with sub-tests as the # __init__.py may do things which alter what tests are to be run. SPLITTESTDIRS = { - "test_asyncio" + "test_asyncio", + "test_multiprocessing", } # Storage of uncollectable objects @@ -167,24 +168,24 @@ def findtestdir(path=None): def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS, splittestdirs=SPLITTESTDIRS, base_mod=""): - """Return a list of all applicable test modules.""" - testdir = findtestdir(testdir) - names = os.listdir(testdir) - tests = [] - others = set(stdtests) | nottests - for name in names: - mod, ext = os.path.splitext(name) - if mod[:5] == "test_" and mod not in others: - if mod in splittestdirs: - subdir = os.path.join(testdir, mod) - if len(base_mod): - mod = f"{base_mod}.{mod}" - else: - mod = f"test.{mod}" - tests.extend(findtests(subdir, [], nottests, splittestdirs, mod)) - elif ext in (".py", ""): - tests.append(f"{base_mod}.{mod}" if len(base_mod) else mod) - return stdtests + sorted(tests) + """Return a list of all applicable test modules.""" + testdir = findtestdir(testdir) + names = os.listdir(testdir) + tests = [] + others = set(stdtests) | nottests + for name in names: + mod, ext = os.path.splitext(name) + if mod[:5] == "test_" and mod not in others: + if mod in splittestdirs: + subdir = os.path.join(testdir, mod) + if len(base_mod): + mod = f"{base_mod}.{mod}" + else: + mod = f"test.{mod}" + tests.extend(findtests(subdir, [], nottests, splittestdirs, mod)) + elif ext in (".py", ""): + tests.append(f"{base_mod}.{mod}" if len(base_mod) else mod) + return stdtests + sorted(tests) def get_abs_module(ns: Namespace, test_name: str) -> str: if test_name.startswith('test.') or ns.testdir: From f5a79cc494fe73b6e852875ad3f8c1335f7ca3d9 Mon Sep 17 00:00:00 2001 From: Joshua Herman Date: Thu, 27 Apr 2023 10:40:45 -0600 Subject: [PATCH 7/7] Update runtest.py Fixing formatting in SPLITTESTDIRS --- Lib/test/libregrtest/runtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index 70933e1ccb571a..e245276c237020 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -149,7 +149,7 @@ def __str__(self) -> str: # __init__.py may do things which alter what tests are to be run. SPLITTESTDIRS = { "test_asyncio", - "test_multiprocessing", + "test_multiprocessing", } # Storage of uncollectable objects