Skip to content

Run independent validation checks in parallel - #191

Open
akacross wants to merge 1 commit into
themuffinator:mainfrom
akacross:ci/parallel-python-checks
Open

akacross wants to merge 1 commit into
themuffinator:mainfrom
akacross:ci/parallel-python-checks

Conversation

@akacross

Copy link
Copy Markdown
Contributor

Why CI takes so long

The slow part is mostly checks that compile C++ harnesses from production sources, often many times for --mutations. Each check is its own process writing only to fresh temporary directories, so they can run concurrently.

Change

  • openq4_validate.py runs its Python checks concurrently, by default as many as the machine has CPUs.
    • --python-jobs N or OPENQ4_PYTHON_TEST_JOBS sets the count; --python-jobs 1 restores the sequential run.
    • Output is still printed in list order with one ==> Python check: section per check, now with each check's duration.
    • Failures are aggregated exactly as before.
  • New tools/validation/run_parallel_commands.py does the same for a list of commands on standard input. Both script-smoke steps feed their unchanged check list to it through a heredoc, so every test name still appears in the workflow and validation_hardening.py's wiring checks still apply.
  • validation_hardening.py now covers failure aggregation on the parallel path as well as the sequential one.
  • BUILDING.md documents the option.

Measurements (Linux x64, 16 threads)

Sequential Parallel
openq4_validate.py Python checks (350) 2041 s 311 s
Rewritten script-smoke step (353 commands) — 343 s

Both modes produced the same failure set: 11 tests that this host's newer clang/libstdc++ rejects (-Wunused-but-set-global under -Werror, missing <cstdint>). GitHub's runners don't hit these, and they are unrelated to parallelism.

GitHub's standard runners have 4 vCPUs, so the CI gain will be smaller than 6×. Most of these checks are CPU-bound compiles, so I'd expect roughly 3×: script smoke in about 25 minutes, and about 12–15 minutes off each platform job.

Possible follow-ups (not in this PR)

  • Platform jobs could pass --skip-python-tests (as one job already does), since script smoke covers the platform-independent checks.
  • The PR time limits could be revisited once real durations are known.

🤖 Generated with Claude Code

The script-smoke job ran its ~350 checks one after another, about 77 minutes
on main, and every platform job then reran the same Python suite in sequence
before its build (39 of the Linux job's 66 minutes). On the slower runners
that left Windows ARM64 and the macOS Intel jobs cancelled at 150 minutes on
main, and pull-request jobs, with 90-minute limits, cancelled regardless of
the change.

Each check is its own process that writes only to fresh temporary
directories, so they can overlap:

- openq4_validate.py runs its Python checks concurrently, as many as the
  machine has CPUs. --python-jobs N or OPENQ4_PYTHON_TEST_JOBS change that and
  --python-jobs 1 restores sequential runs. Output is still printed in list
  order, one section per check, with each check's duration.
- tools/validation/run_parallel_commands.py does the same for a list of
  commands on standard input; both script-smoke steps feed their unchanged
  check list through it.
- validation_hardening.py covers the parallel path's failure aggregation as
  well as the sequential one.

On a 16-thread Linux host the validator's 350 checks took 2041 s in sequence
and 311 s in parallel with the same results; the whole rewritten smoke step
took 343 s. The only failures, identical either way, are host-toolchain ones
(newer clang/libstdc++), not parallelism.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant