Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,15 @@ jobs:
# pytest once per directory `SHARDS` names, then once over the rest,
# and every run starts its workers afresh. Each run but the last writes
# a JUnit file of its own, beside junit.xml; the step fails if any did.
#
# #2600: run whole, tests/protocols took the workers past the runner's
# 16 GB, and its tail stalled past tests._support.time_limit's 30 s. So
# its internet, application and misc subpackages run first, each a shard
# of its own, and `tests/protocols` then takes the remainder.
env:
COVERAGE: ${{ matrix.coverage }}
LATEST: ${{ matrix.python-version == needs.python-versions.outputs.latest }}
SHARDS: ${{ startsWith(matrix.python-version, 'pypy') && 'tests/protocols tests/corekit' || '' }}
SHARDS: ${{ startsWith(matrix.python-version, 'pypy') && 'tests/protocols/internet tests/protocols/application tests/protocols/misc tests/protocols tests/corekit' || '' }}
run: |
if [ "$LATEST" = "true" ]; then
if ! skipped=$(python -c "from tests._tiers import project_pin_paths; print(' '.join(project_pin_paths()))"); then
Expand Down
15 changes: 12 additions & 3 deletions docs/source/contributing/workflows.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1046,12 +1046,21 @@ extras cap |cryptography|_ below 46, as 45.0.7 is the newest release with a Linu
On PyPy an xdist worker's RSS grows with every test it runs, rather than in a few
heavy modules, so a PyPy leg's ``Run unit tests`` hands its pytest command to
:file:`util/pytest_shards.py`, as GraalPy's leg does (see below), which runs it once per
directory its ``SHARDS`` names, ``tests/protocols`` and then ``tests/corekit``, and once
more over the rest, ignoring each (:issue:`2005`).
directory its ``SHARDS`` names and once more over the rest, ignoring each
(:issue:`2005`). The directories are ``tests/protocols/internet``,
``tests/protocols/application``, ``tests/protocols/misc``, ``tests/protocols`` and
``tests/corekit``, in that order, so ``tests/protocols`` runs after its own
subpackages and takes only what they left.
Each run starts its workers afresh. Measured on PyPy 8.0.1 at ``-n 4``, one run
over the whole ``ALL`` tier took each worker to 5.4-5.9 GB and the workers together
past 20 GB, beyond the runner's 16 GB; split, the largest run peaked at 2.6 GB a
worker and 8.5 GB in all, and the tier took 383 s rather than 493 s. A smaller
worker and 8.5 GB in all, and the tier took 383 s rather than 493 s. With
:issue:`2543`'s checksum tests, ``tests/protocols`` run whole outgrew the runner as
well, and on CI the tests at its tail stalled past ``tests._support.time_limit``'s
30-second deadline, which counts wall-clock time, so it is split (:issue:`2600`).
Measured on PyPy 7.3.19 at ``-n 4``, its one run peaked at 17.7 GiB and took 267 s,
its slowest test 16.4 s; split, the largest of its runs peaked at 5.7 GiB, they took
224 s together, and the slowest test 11.9 s. A smaller
``-n`` would only hand each worker more tests, and a ``PYPY_GC_MAX`` heap cap turns
the kills into ``MemoryError``\ s. Each run but the last writes a JUnit file of its
own beside ``junit.xml``, which ``Upload test timings`` takes too, and the step
Expand Down
16 changes: 12 additions & 4 deletions tests/project/test_pypy_worker_memory_2005.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
own script with a stub ``python``, as
:mod:`tests.project.test_sweeps_on_latest_only_1732` does.

#2600: run whole, ``tests/protocols`` outgrew the runner too, so its
``internet``, ``application`` and ``misc`` subpackages are shards of their own
ahead of it, and it takes the remainder.

"""

from __future__ import annotations
Expand All @@ -33,8 +37,9 @@

#: The ``test`` job's KTLO twin, which runs its steps by YAML alias.
KTLO = ('unit-tests.yml', 'test-ktlo')
#: The directories a PyPy leg runs on their own, in order.
SHARDS = ['tests/protocols', 'tests/corekit']
#: The directories a PyPy leg runs on their own, in order; #2600 split ``tests/protocols``.
SHARDS = ['tests/protocols/internet', 'tests/protocols/application', 'tests/protocols/misc', 'tests/protocols',
'tests/corekit']
#: The page that says how the legs run.
DOC = ROOT / 'docs' / 'source' / 'contributing' / 'workflows.rst'

Expand All @@ -61,10 +66,13 @@ def test_the_ktlo_twin_runs_the_same_step(self) -> None:
self.assertEqual(job(*KTLO)['steps'], job(*JOB)['steps'])

def test_each_shard_is_a_directory_the_tier_keeps(self) -> None:
for shard in SHARDS:
"""#2600: and each keeps unit-tier modules no earlier shard took, so its run collects a test."""
for index, shard in enumerate(SHARDS):
with self.subTest(shard=shard):
self.assertTrue((ROOT / shard).is_dir())
self.assertTrue([module for module in _tiers.all_tier_paths() if module.startswith(shard + '/')])
earlier = tuple(taken + '/' for taken in SHARDS[:index])
self.assertTrue([module for module in _tiers.all_tier_paths() if module.startswith(shard + '/')
and not module.startswith(earlier) and _tiers.is_unit_tier(module)])


@unittest.skipIf(shutil.which('bash') is None, 'the step is a bash script')
Expand Down
Loading