Skip to content

perf: use worksteal distribution for pytest-xdist#750

Merged
Aureliolo merged 4 commits intomainfrom
perf/pytest-worksteal
Mar 22, 2026
Merged

perf: use worksteal distribution for pytest-xdist#750
Aureliolo merged 4 commits intomainfrom
perf/pytest-worksteal

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Switch xdist from the default load scheduler to worksteal via addopts in pyproject.toml
  • Workers that finish fast tests early now steal work from slower workers, improving load balance when test durations vary widely (0.01s to 10s range)
  • Benchmarked locally: ~170s to ~125s for 10,195 unit tests (~26% reduction, 32 workers)

What was investigated and rejected

Option Result Why rejected
--import-mode=importlib Slightly worse No collection speedup for this codebase
-p no:cacheprovider ~1s improvement Negligible, not worth config noise
Module-scoped API fixtures Net negative Requires loadscope/loadfile distribution which is less efficient than worksteal at balancing 10K+ tests across 32 workers

Test plan

  • Full unit test suite passes (10,190 passed, 5 skipped -- same as baseline)
  • No new test failures introduced
  • Pre-commit hooks pass

🤖 Generated with Claude Code

Switch xdist from the default `load` scheduler to `worksteal`.
Workers that finish fast tests early now steal work from slower
workers, improving load balance when test durations vary widely.

Benchmarked locally: ~170 s -> ~125 s for 10 195 unit tests
(~26 % reduction, 32 workers).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 22, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d8b232a9-a23a-41c0-a823-2ee7424330e6

📥 Commits

Reviewing files that changed from the base of the PR and between 8ec45ed and 909d98d.

📒 Files selected for processing (1)
  • .claude/skills/pre-pr-review/SKILL.md
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test (Python 3.14)
  • GitHub Check: Build Backend
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T19:37:56.694Z
Learning: Parallelism: `pytest-xdist` via `-n auto` -- ALWAYS include when running pytest, never run tests sequentially.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Parallelism: pytest-xdist via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Test markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Coverage: 80% minimum. Async: `asyncio_mode = 'auto'` — no manual `pytest.mark.asyncio` needed. Timeout: 30 seconds per test. Parallelism: `pytest-xdist` via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to tests/**/*.py : Test markers: pytest.mark.unit, pytest.mark.integration, pytest.mark.e2e, pytest.mark.slow. Coverage: 80% minimum (enforced in CI).
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to tests/**/*.py : Test markers: pytest.mark.unit, pytest.mark.integration, pytest.mark.e2e, pytest.mark.slow. Coverage: 80% minimum (enforced in CI).

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Test markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Coverage: 80% minimum. Async: `asyncio_mode = 'auto'` — no manual `pytest.mark.asyncio` needed. Timeout: 30 seconds per test. Parallelism: `pytest-xdist` via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on cli/**/*.go) (fast gate before push, skipped in pre-commit.ci — dedicated CI jobs already run these).

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Pre-commit hooks: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint (Dockerfile linting).

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/*.yml : Dependabot: daily updates for uv + github-actions + npm + pre-commit + docker + gomod, grouped minor/patch, no auto-merge. Use `/review-dep-pr` to review Dependabot PRs before merging.

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: NEVER create a PR directly — `gh pr create` is blocked by hookify. ALWAYS use `/pre-pr-review` to create PRs — it runs automated checks + review agents + fixes before creating the PR. For trivial/docs-only changes: `/pre-pr-review quick` skips agents but still runs automated checks.

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/cli.yml : CLI workflow: Go lint (golangci-lint + go vet) + test (-race -coverprofile) + build (cross-compile: linux/darwin/windows × amd64/arm64) + govulncheck + fuzz testing (main-only, 30s/target, continue-on-error, matrix over 4 packages). cli-pass gate includes fuzz as informational. GoReleaser release on v* tags. Cosign keyless signing of checksums.txt. SLSA L3 provenance attestations. Sigstore bundle (.sigstore.json) attached. Post-release appends checksums/verification/provenance to draft release notes.

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: CLI workflow (`.github/workflows/cli.yml`) runs Go lint (golangci-lint + go vet) + test (race, coverage) + build (cross-compile matrix) + vulnerability check (govulncheck) + fuzz testing. Cross-compiles for linux/darwin/windows × amd64/arm64. GoReleaser release on v* tags with cosign keyless signing and SLSA L3 attestations.

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
📚 Learning: 2026-03-22T19:37:56.694Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T19:37:56.694Z
Learning: NEVER create a PR directly with `gh pr create` -- ALWAYS use `/pre-pr-review` to create PRs. It runs automated checks + review agents + fixes before creating the PR.

Applied to files:

  • .claude/skills/pre-pr-review/SKILL.md
🔇 Additional comments (2)
.claude/skills/pre-pr-review/SKILL.md (2)

171-175: LGTM — Coverage flags correctly removed, parallelism preserved.

The removal of --cov=synthorg and --cov-fail-under=80 from all three test invocation points (Phase 2, Phase 8, Phase 9) aligns with the PR objectives to eliminate 20–40% coverage overhead from local runs while keeping coverage enforcement in CI. The -n auto flag is correctly retained to satisfy the parallelism requirement.

All three occurrences have been updated consistently, which is good for maintainability.

Based on learnings, pytest parallelism via -n auto must always be included when running pytest, which is satisfied here.

Also applies to: 734-734, 755-755


174-174: The pytest configuration is correctly set up. The pyproject.toml addopts includes both --dist=worksteal and -n=auto, so the work-stealing distribution strategy is automatically applied. The -n auto on the command line is redundant with the configuration but harmless.


Walkthrough

Pytest configuration in pyproject.toml was updated to add --dist=worksteal and -n=auto to the addopts list. Separately, pre-PR pipeline documentation/skill steps were changed to remove coverage enforcement flags (--cov= and --cov-fail-under=) and run tests with -n auto without coverage thresholds.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'perf: use worksteal distribution for pytest-xdist' directly and accurately describes the main change in the PR: adding the --dist=worksteal flag to pytest configuration for performance improvement.
Description check ✅ Passed The description is directly related to the changeset, explaining the motivation (load balancing), benchmark results, rejected alternatives, and test plan for the xdist worksteal scheduler change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 22, 2026 20:52 — with GitHub Actions Inactive
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request optimizes the pytest-xdist configuration by changing the scheduler to worksteal. This improves load balancing across workers, especially when test durations vary significantly, resulting in a substantial reduction in overall test execution time. The change was made after investigating and rejecting several alternative approaches, and was validated by ensuring that all tests pass and no new issues were introduced.

Highlights

  • pytest-xdist Configuration: Switched the pytest-xdist scheduler from load to worksteal in pyproject.toml to improve load balancing for tests with varying durations.
  • Performance Improvement: Achieved a ~26% reduction in test suite execution time (from ~170s to ~125s) on a local benchmark with 10,195 unit tests and 32 workers.
  • Rejected Alternatives: Evaluated and rejected --import-mode=importlib and -p no:cacheprovider due to negligible or negative performance impact. Also, module-scoped API fixtures were deemed less efficient than worksteal.
  • Testing and Validation: Confirmed that the full unit test suite passes with the same number of skipped tests as the baseline, and that no new test failures or pre-commit hook failures were introduced.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pyproject.toml`:
- Line 239: Update the pytest addopts setting so local runs match CI: edit the
addopts array in pyproject.toml (the addopts key) and append the xdist auto
option (e.g., "-n=auto" or "-n auto") to the existing entries so pytest will use
automatic parallel workers locally as CI does.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6999d9f4-fbdf-4205-8e46-e735b8f311e6

📥 Commits

Reviewing files that changed from the base of the PR and between c374cc9 and 3e5144c.

📒 Files selected for processing (1)
  • pyproject.toml
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build Backend
  • GitHub Check: Build Web
  • GitHub Check: Build Sandbox
  • GitHub Check: Test (Python 3.14)
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Test markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Coverage: 80% minimum. Async: `asyncio_mode = 'auto'` — no manual `pytest.mark.asyncio` needed. Timeout: 30 seconds per test. Parallelism: `pytest-xdist` via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.

Applied to files:

  • pyproject.toml

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a performance optimization for the test suite by switching the pytest-xdist distribution strategy to worksteal. The change, located in pyproject.toml, is well-justified in the pull request description with benchmarks showing a significant reduction in test execution time. The implementation is correct and follows standard pytest configuration practices. My review did not find any issues or necessary improvements.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.28%. Comparing base (c374cc9) to head (909d98d).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #750   +/-   ##
=======================================
  Coverage   92.28%   92.28%           
=======================================
  Files         573      573           
  Lines       29690    29690           
  Branches     2877     2877           
=======================================
  Hits        27398    27398           
  Misses       1811     1811           
  Partials      481      481           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The --dist=worksteal setting only takes effect when xdist workers
are active. Without -n=auto in addopts, the worksteal scheduler
is silently ignored unless the user remembers to pass -n auto on
the command line.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 22, 2026
Coverage adds 20-40% overhead and is already measured by CI.
Remove --cov, --cov-report, and --cov-fail-under from the
pre-PR review skill's pytest invocations (Phase 2, 8, and 9).

A local hookify rule (no-local-coverage) now blocks --cov in
all local pytest commands as additional enforcement.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@Aureliolo Aureliolo merged commit b7dd7de into main Mar 22, 2026
33 checks passed
@Aureliolo Aureliolo deleted the perf/pytest-worksteal branch March 22, 2026 21:23
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 22, 2026 21:23 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Mar 22, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.4.8](v0.4.7...v0.4.8)
(2026-03-22)


### Features

* add auto_cleanup config and improve update UX
([#741](#741))
([289638f](289638f))
* add reporting lines, escalation paths, and workflow handoffs to
templates ([#745](#745))
([c374cc9](c374cc9))
* differentiate template operational configs
([#742](#742))
([9b48345](9b48345))
* diversify personality preset assignments across templates
([#743](#743))
([15487a5](15487a5))
* improve template metadata -- skill taxonomy, descriptions, tags, and
display names ([#752](#752))
([f333f24](f333f24))


### Bug Fixes

* resolve log analysis findings (Ollama prefix, logging, init)
([#748](#748))
([8f871a4](8f871a4))
* use git tag for dev release container image tags
([#749](#749))
([f30d071](f30d071))
* use subordinate_id/supervisor_id in HierarchyResolver
([#751](#751))
([118235b](118235b))


### Performance

* add long-lived cache headers for content-hashed static assets
([#747](#747))
([4d350b5](4d350b5))
* use worksteal distribution for pytest-xdist
([#750](#750))
([b7dd7de](b7dd7de))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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