pytest-xdist-memory
Size pytest-xdist by available RAM, not by CPU count.
On a developer laptop the bottleneck of a parallel test run is usually memory.
pytest -n auto starts one worker per core; with heavy workers (Django and
a database, a browser per worker for Playwright, a live server...) a 14-core,
14 GB laptop goes into swap thrashing and freezes. This plugin measures how
much a worker of your test suite needs on this machine and answers
-n auto with as many workers as fit into the memory available right now.
Status: alpha.
What it does
With --xdist-memory (or xdist_memory = true in the ini file):
- Measures the peak memory of every worker together with all its child processes: browsers, live servers, subprocesses. Linux uses PSS (a fair share of pages shared between processes, so the several processes of one Chromium are not counted several times over); other systems use RSS.
- Measures containers too, if you ask it to: a test database started by
testcontainers is not a child of pytest. Containers can be matched by name
(
--xdist-memory-docker SUBSTR) or, more precisely, by the host port they publish (--xdist-memory-docker-port-env VAR, whereVARis the environment variable your fixtures export with the port). Matching by port is exact even when parallel runs from other checkouts have containers with similar names. The peak is divided by the number of workers. - Records the peaks in a per-machine profile,
.pytest-xdist-memory.json. Each-mmarker expression is a separate "suite":-m playwrightworkers are much heavier than-m "not playwright"ones. The last 5 runs are kept, and the estimate uses the maximum. Runs with fewer than 20 tests, or interrupted runs, are not recorded. - Answers
-n auto/-n logical:workers = (available - reserve - controller) / (worker_peak × safety + extra), capped by the CPU count. With--xdist-memory-performance-cores, Apple Silicon is capped at the number of performance cores. - Optional watchdog (
--xdist-memory-watchdog): kills the run when the whole process tree, plus the measured containers, exceeds the memory available at start minus the reserve.
Nothing changes until you enable it. PYTEST_XDIST_AUTO_NUM_WORKERS still
wins over the estimate.
Usage
pip install pytest-xdist-memory
# First run: no profile yet, so it assumes 1024 MB per worker; the run is measured.
pytest -n auto --xdist-memory
# Later runs use what was measured (per -m expression):
pytest -n auto --xdist-memory -m "not playwright"
pytest -n auto --xdist-memory -m playwright --xdist-memory-performance-cores
The terminal summary shows the measured peaks and the calculation:
================================ xdist-memory =================================
-n auto [default]: 3 workers: available 7282 MB - reserve 2048 - controller 215 = 5019 MB; per worker 1357 MB (910 x safety + extra 220); cpu cap 14; from profile (4 runs)
peak per worker 905 MB (all: [905, 871, 860]), controller 210 MB, containers 214 MB/worker
recorded in .pytest-xdist-memory.json [default]
Add .pytest-xdist-memory.json to .gitignore: the profile describes one
machine.
Options
| Option | ini | Default | |
|---|---|---|---|
--xdist-memory |
xdist_memory |
off | enable |
--xdist-memory-profile PATH |
xdist_memory_profile |
.pytest-xdist-memory.json |
relative to rootdir |
--xdist-memory-reserve MB |
xdist_memory_reserve |
2048 | left for the desktop/system |
--xdist-memory-safety F |
xdist_memory_safety |
1.25 | multiplier on the worker peak |
--xdist-memory-default-worker MB |
xdist_memory_default_worker |
1024 | used until a run is recorded |
--xdist-memory-extra MB |
xdist_memory_extra |
0 | fixed extra per worker (e.g. its DB) |
--xdist-memory-docker SUBSTR |
xdist_memory_docker |
measure containers by name | |
--xdist-memory-docker-port-env VAR |
xdist_memory_docker_port_env |
measure the container publishing port $VAR |
|
--xdist-memory-performance-cores |
xdist_memory_performance_cores |
off | Apple Silicon: P-cores only |
--xdist-memory-min-tests N |
xdist_memory_min_tests |
20 | smaller runs are not recorded |
--xdist-memory-watchdog |
xdist_memory_watchdog |
off | kill the run over budget |
--xdist-memory-interval S |
xdist_memory_interval |
2 | sampling interval |
Watchdog vs. a cgroup limit
The watchdog is portable but best effort: it checks once per sampling interval, so a very fast allocation spike can get past it. When it fires, it kills the workers and exits with code 3, without pytest's teardown: containers are left to their own reaper (Ryuk for testcontainers).
On Linux with systemd, a cgroup limit is the hard guarantee: the kernel kills the run instead of swapping the desktop to death. You can use both:
systemd-run --user --scope -q -p MemoryMax=6G -p MemorySwapMax=0 \
pytest -n auto --xdist-memory
Neither is needed for measuring. Measuring uses only psutil (and
docker stats, if you ask for containers).
Requirements
Python ≥ 3.10, pytest ≥ 7, psutil. pytest-xdist is optional: without it, the plugin only reports the peak of the whole process tree.
License
MIT
Metadata
Release files for pytest-xdist-memory 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pytest_xdist_memory-0.1.0.tar.gz | 13.6 kB | With provenance | Details for pytest_xdist_memory-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pytest_xdist_memory-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for pytest_xdist_memory-0.1.0-py3-none-any.whl |
Total release size: 27.4 kB
Release files / pytest_xdist_memory-0.1.0.tar.gz
| Download URL | pytest_xdist_memory-0.1.0.tar.gz |
|---|---|
| Size | 13.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3ee916790c6e63fea4faefb143023769a9ecf859281003e3e399a729fd869346
|
|
BLAKE2b-256 checksum How to use checksums |
7e2a72e2c363b27d6bb3bcb7f59ffb8f1863dc6153d3b9ed7ca41ea6d6bf61da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logRelease files / pytest_xdist_memory-0.1.0-py3-none-any.whl
| Download URL | pytest_xdist_memory-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
821b99e10f4bdb04041c2344d05d394ba1f6a4c107532d13fe5a307a1dc67d61
|
|
BLAKE2b-256 checksum How to use checksums |
4b867a45e37443d1f6e3ca6975849aef0864f1da7cdf827dd9188aeb0ed905d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logSecurity for pytest-xdist-memory 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for pytest_xdist_memory-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.