Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does pytest-xdist make my tests run slower, not faster?

I'm porting a ~2000 method test suite from nose to pytest because django-nose didn't support parallelization well. Swapping out nose for pytest seemed to work pretty well, and after adding python_files to pytest.ini it found almost all of our tests.

The big downside is that when I run with -n 4, the test suite becomes slower than without the -n flag at all. Running on a ~10% subset of the entire suite, it appears to be about 20-30% flat slowdown, though the timings I've taken are rather noisy. This makes some sense as overhead, but no matter how many processes I select, the timing never goes down.

Running with --durations=20 shows each setup phase takes a few seconds longer per process, and each other test gets marginally slower.

With -vvv to list the tests as they're run, the output is almost entirely serialized:

api/tests/VERSION_NUMBER.py::ATestCase::test_forbidden_methods <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::ATestCase::test_access_token <- api/testcases.py
api/tests/VERSION_NUMBER.py::ATestCase::test_create <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::ATestCase::test_create <- api/testcases.py
api/tests/VERSION_NUMBER.py::ATestCase::test_delete <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::ATestCase::test_delete <- api/testcases.py
api/tests/VERSION_NUMBER.py::ATestCase::test_patch <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::ATestCase::test_patch <- api/testcases.py
api/tests/VERSION_NUMBER.py::ATestCase::test_put <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::ATestCase::test_put <- api/testcases.py
api/tests/VERSION_NUMBER.py::ATestCase::test_retrieve <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::ATestCase::test_retrieve <- api/testcases.py
api/tests/VERSION_NUMBER.py::BTestCase::test_access_token <- api/testcases.py
[gw0] PASSED api/tests/VERSION_NUMBER.py::ATestCase::test_forbidden_methods <- api/testcases.py
api/tests/VERSION_NUMBER.py::ATestCase::test_list <- api/testcases.py
[gw0] PASSED api/tests/VERSION_NUMBER.py::ATestCase::test_list <- api/testcases.py
api/tests/VERSION_NUMBER.py::BTestCase::test_delete <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::BTestCase::test_access_token <- api/testcases.py
api/tests/VERSION_NUMBER.py::BTestCase::test_create <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::BTestCase::test_create <- api/testcases.py
api/tests/VERSION_NUMBER.py::BTestCase::test_list <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::BTestCase::test_list <- api/testcases.py
api/tests/VERSION_NUMBER.py::BTestCase::test_patch <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::BTestCase::test_patch <- api/testcases.py
api/tests/VERSION_NUMBER.py::BTestCase::test_put <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::BTestCase::test_put <- api/testcases.py
[gw0] PASSED api/tests/VERSION_NUMBER.py::BTestCase::test_delete <- api/testcases.py
api/tests/VERSION_NUMBER.py::BTestCase::test_forbidden_methods <- api/testcases.py
api/tests/VERSION_NUMBER.py::BTestCase::test_retrieve <- api/testcases.py
[gw0] PASSED api/tests/VERSION_NUMBER.py::BTestCase::test_forbidden_methods <- api/testcases.py
[gw1] PASSED api/tests/VERSION_NUMBER.py::BTestCase::test_retrieve <- api/testcases.py

With few exceptions, it's almost always "start a test, get PASSED from a worker" for the entire log. This leads me to believe that something is serializing the tests, but I'm baffled as to what.

I've tried disabling all pytest plugins except for pytest itself, pytest-xdist, and pytest-django, with no change.

like image 544
Cassie Meharry Avatar asked Feb 17 '17 02:02

Cassie Meharry


1 Answers

Read https://github.com/pytest-dev/pytest-xdist/blob/master/OVERVIEW.md and you will guess why it can be considerably slower in particular cases.

When parallelized may be slower:

  • total test duration is quite slow (under 2minutes) - bootraping pytest workers adds extra time, if that is bigger than the benefit...
  • your tests already hog a shared finite resource like disk or networking, so running in parallel may make it slower
like image 160
sorin Avatar answered Sep 19 '22 08:09

sorin