Skip to content

refactor(bench): 📦 release the benchmark harness as monoprop-bench-tools - #227

Merged
robertodr merged 17 commits into
mainfrom
refactor/bench-tools-uv-workspace
Aug 19, 2026
Merged

refactor(bench): 📦 release the benchmark harness as monoprop-bench-tools#227
robertodr merged 17 commits into
mainfrom
refactor/bench-tools-uv-workspace

Conversation

@Panadestein

Copy link
Copy Markdown
Member

🤖 AI text below 🤖

Turns the repository into a uv workspace and splits the benchmark harness in two: the reusable half becomes a package we can publish, the benchmarks stay here.

monoprop/
├── pyproject.toml            # the library (unchanged in scope)
├── uv.lock                   # one lock for the whole workspace
├── src/monoprop/
├── benches/                  # monoprop's own benchmark suite — stays put
└── packages/
    ├── monoprop-bench-tools/ # → PyPI
    └── bench-third-party/    # → GitHub only, standalone uv project

What moved

Was Is
benches/_memory_cpu.py monoprop_bench_tools.memory.cpu
benches/_memory_gpu.py monoprop_bench_tools.memory.gpu
benches/_builders.py monoprop_bench_tools.models
benches/report.py monoprop_bench_tools.reportmonoprop-bench-report
benches/bmf.py monoprop_bench_tools.bmfmonoprop-bench-bmf
tests/test_bench_*.py packages/monoprop-bench-tools/tests/
benches/third_party/ packages/bench-third-party/

All moves are git mv, so git log --follow still works.

Design decisions worth reviewing

benches/ does not move. Bencher keys its metric history on the benchmark name, so moving or renaming a bench_* test orphans its tracked series and resets the thresholds' sample windows. The suite therefore cannot version with a library release, which is precisely the line between "harness" and "benchmarks". monoprop-bench-tools contains no benchmarks.

The bencher.dev tracking stays in the repo. Only the renderer (bmf.py) is tooling and moved. bench_main.yml carries BENCHER_API_KEY, vars.BENCHER_PROJECT, the --branch/--testbed identity and the four threshold blocks — that is this repository's CI identity, and a published package cannot own a secret. The workflow itself is unchanged; just bench-bmf now shells out to the console script.

Three dependency groups instead of two.

  • test — monoprop's suite only, deliberately free of workspace members. cibuildwheel installs it against a built wheel via test-groups = ["test"], where a monoprop-bench-tools requirement would resolve from PyPI (nonexistent) and drag monoprop back in from source.
  • workspace-testtest + the member. What uv run pytest at the root needs.
  • benchworkspace-test + pytest-benchmark.

bench-third-party is excluded from the workspace. It pins a narrower requires-python, a git dependency and linux-x86_64-only CUDA wheels; folding it in would drag all of that into the root lock. It stays a standalone uv project with its own lockfile (cd packages/bench-third-party && uv sync). It now depends on monoprop-bench-tools properly instead of poking benches/ onto sys.path.

No gpu extra on the tools package. Adding one put cupy-cuda12x + cuda-pathfinder into the root lock. CuPy is installed separately; memory.gpu already degrades to Method.UNAVAILABLE without it.

Publishing

deploy.yml gains build-bench-tools (uv build --package monoprop-bench-tools — pure Python, no cibuildwheel matrix) and a separate upload_pypi_bench_tools job. Separate because it is a separate PyPI project, and because a failure there must not hold back the library's own upload. hatch-vcs reads the same git tags via raw-options = { root = "../.." }, so the two distributions share a version line; verified that the wheel still builds from the sdist, where there is no git.

Important

Before the next release someone has to register a trusted publisher for monoprop-bench-tools on PyPI (this workflow file, the pypi environment), or upload_pypi_bench_tools will fail on its first run.

Validation

  • uv lock --check, uv sync --all-groups --all-extras
  • pytest -m "not mpi" → 617 passed (both suites)
  • just bench-smoke and just bench-bmf smoke end to end through the console scripts
  • Both distributions build; packages/bench-third-party/uv.lock re-resolved
  • prek run --all-files clean

Deliberate non-changes

  • packages/** is excluded from Sonar scope, preserving current behaviour. Bringing it in is a separate call.
  • benches/results/*.json is untouched, so Bencher continuity holds.

One seam this creates

benches/conftest.py writes the results artifact schema and monoprop_bench_tools.report/.bmf read it — now across a package boundary. Called out in both docstrings and in AGENTS.md: a change to the recorded sections has to land on both sides.

Docs updated in the same change: AGENTS.md (new "Workspace layout" section), README.md, docs/content/docs/benchmarks.mdx, docs/content/docs/testing.mdx, benches/README.md.

Turn the repository into a uv workspace and split the benchmark harness in two:
the reusable half becomes a published package, the benchmarks stay here.

- packages/monoprop-bench-tools: peak-memory measurement (memory.cpu, memory.gpu),
  the benchmarked model builders (models), and the artifact renderers (report,
  bmf), plus the monoprop-bench-report / monoprop-bench-bmf console scripts.
  Pure Python, built by hatchling, versioned off the same git tags as monoprop.
- benches/ keeps conftest.py and the bench_* suite and imports the package.
  Benchmark names are Bencher's history key, so the suite must not move with a
  library release.
- packages/bench-third-party: the cross-engine comparison scripts, moved out of
  benches/third_party and excluded from the workspace (narrower requires-python,
  a git dependency and linux-x86_64-only CUDA wheels). It now depends on the
  tools package instead of poking benches/ onto sys.path.

Dependency groups follow the split: `test` stays free of workspace members so
cibuildwheel can install it against a built wheel, `workspace-test` adds the new
member and is what the root suite needs, and `bench` builds on that.

deploy.yml gains a job that builds and publishes monoprop-bench-tools; it is a
separate PyPI project, so it needs its own trusted-publisher entry.

Assisted-by: GitHubCopilot:claude-opus-5
@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file ci labels Aug 14, 2026
@github-actions

Copy link
Copy Markdown

Docs preview: https://pr-227.monoprop-docs.pages.dev

@robertodr robertodr added the test-in-draft Run CI even in Draft mode label Aug 14, 2026
@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

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

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #227   +/-   ##
=======================================
  Coverage   97.70%   97.70%           
=======================================
  Files          14       14           
  Lines         742      742           
  Branches       98       98           
=======================================
  Hits          725      725           
  Misses         12       12           
  Partials        5        5           
Flag Coverage Δ
cpp 97.70% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

@Panadestein
Panadestein marked this pull request as ready for review August 17, 2026 08:29
@adamglos92
adamglos92 removed their request for review August 17, 2026 08:34
@diagonal-hamiltonian

Copy link
Copy Markdown
Collaborator

Good idea 👍

@robertodr
robertodr removed the request for review from fpietra August 17, 2026 09:34
@Panadestein
Panadestein requested a lite review from Copilot August 17, 2026 10:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR restructures the repository into a uv workspace and extracts the reusable benchmark harness into a separately publishable Python distribution (monoprop-bench-tools), while keeping benches/ in-repo to preserve Bencher metric history continuity.

Changes:

  • Introduces a uv workspace setup and dependency-group split (test vs workspace-test vs bench) to keep wheel-testing isolated from workspace members.
  • Creates the new packages/monoprop-bench-tools distribution containing memory tooling, model builders, and artifact renderers with console scripts.
  • Moves third-party comparison scripts into a standalone packages/bench-third-party project with its own lockfile and updated imports.

Reviewed changes

Copilot reviewed 35 out of 57 changed files in this pull request and generated no comments.

Show a summary per file
File Description
uv.lock Adds workspace manifest members and a workspace-test group; locks the new monoprop-bench-tools editable member.
sonar-project.properties Excludes packages/** from Sonar scope to preserve previous analysis behavior.
README.md Documents workspace install flow and explains the new repository layout.
pyproject.toml Defines [tool.uv.workspace], introduces workspace-test, updates pytest collection paths, and adjusts ruff per-file ignores for new package layout.
packages/monoprop-bench-tools/tests/test_report.py Updates imports to reference monoprop_bench_tools.report.
packages/monoprop-bench-tools/tests/test_models.py Updates imports to reference monoprop_bench_tools.models.
packages/monoprop-bench-tools/tests/test_memory.py Updates imports to reference monoprop_bench_tools.memory.cpu.
packages/monoprop-bench-tools/tests/test_bmf.py Updates imports to reference monoprop_bench_tools.bmf.
packages/monoprop-bench-tools/tests/conftest.py Adds isolated pytest config/fixtures so the tools package can test standalone.
packages/monoprop-bench-tools/src/monoprop_bench_tools/report.py Converts report renderer into a console-script entrypoint (monoprop-bench-report) and tightens CLI usage.
packages/monoprop-bench-tools/src/monoprop_bench_tools/models.py Introduces reusable benchmark model builders and registry (MODELS).
packages/monoprop-bench-tools/src/monoprop_bench_tools/memory/gpu.py Moves GPU peak-memory measurement into the publishable tooling package and updates module references/docstrings.
packages/monoprop-bench-tools/src/monoprop_bench_tools/memory/cpu.py Moves CPU peak-memory and PSS sampling utilities into the publishable tooling package and expands docstrings.
packages/monoprop-bench-tools/src/monoprop_bench_tools/memory/init.py Adds package init describing CPU/GPU backends and import expectations.
packages/monoprop-bench-tools/src/monoprop_bench_tools/bmf.py Converts BMF exporter into a console-script entrypoint (monoprop-bench-bmf) and updates usage/errors.
packages/monoprop-bench-tools/src/monoprop_bench_tools/init.py Adds package top-level docstring and version exports.
packages/monoprop-bench-tools/README.md Adds end-user README for the new PyPI-distributed tooling package.
packages/monoprop-bench-tools/pyproject.toml Defines the new monoprop-bench-tools project metadata and console scripts; configures hatch-vcs versioning from repo tags.
packages/monoprop-bench-tools/LICENSE Adds Apache-2.0 license file for the new distribution.
packages/bench-third-party/uv.lock Re-resolves the standalone third-party project lockfile and adds an editable dependency on monoprop-bench-tools.
packages/bench-third-party/README.md Updates documentation to refer to monoprop_bench_tools.memory.gpu and new invocation patterns.
packages/bench-third-party/pyproject.toml Defines the standalone monoprop-bench-third-party project and consumes both monoprop packages from the checkout.
packages/bench-third-party/pauli_prop/settings.json Adds committed settings for the third-party Pauli benchmark configuration.
packages/bench-third-party/pauli_prop/scaling_results.jsonl Adds committed scaling results dataset used by plotting scripts.
packages/bench-third-party/pauli_prop/run_scaling.py Adds sweep driver that spawns per-(backend,size) subprocesses with timeouts and captures failures.
packages/bench-third-party/pauli_prop/run_scaling.jl Adds Julia scaling runner matching the Python record schema.
packages/bench-third-party/pauli_prop/run_one.py Adds single-backend runner used as the subprocess work unit for scaling sweeps.
packages/bench-third-party/pauli_prop/run_model.py Adds fixed-size multi-backend runner emitting per-step curves.
packages/bench-third-party/pauli_prop/run_model.jl Adds Julia fixed-size runner merging results into the shared JSON file.
packages/bench-third-party/pauli_prop/results.json Adds committed fixed-size results dataset used by plotting scripts.
packages/bench-third-party/pauli_prop/plot_speedup.py Adds speed-up bar chart generator (monoprop baseline vs other backends).
packages/bench-third-party/pauli_prop/plot_scaling.py Adds scaling-curve plotting and sidecar table/provenance generation.
packages/bench-third-party/pauli_prop/plot_results.py Adds fixed-size per-step plotting for runtime/memory curves.
packages/bench-third-party/pauli_prop/model.py Adds shared benchmark model definition (TFIM) used across backends.
packages/bench-third-party/pauli_prop/backends.py Switches memory instrumentation imports to monoprop-bench-tools rather than sys.path hacks; updates metric docs.
packages/bench-third-party/majorana_prop/run_benchmarks.sh Adds orchestration script to run monoprop + Julia benchmarks back-to-back.
packages/bench-third-party/majorana_prop/results.json Adds committed results dataset for the majorana comparison benchmark.
packages/bench-third-party/majorana_prop/README.md Adds documentation for the majorana comparison benchmark workflow.
packages/bench-third-party/majorana_prop/Project.toml Adds Julia project deps for the majorana benchmark.
packages/bench-third-party/majorana_prop/plot_results.py Adds plotting for majorana benchmark results, including a runtime-only figure.
packages/bench-third-party/majorana_prop/monoprop_hubbard1d_benchmark.py Updates benchmark script to import memory instrumentation from monoprop-bench-tools.
packages/bench-third-party/majorana_prop/julia_hubbard1d_benchmark.jl Adds Julia benchmark implementation and merges results/provenance into shared JSON.
packages/bench-third-party/bench_common.jl Updates comment references to match the new monoprop_bench_tools.memory.cpu source of truth.
benches/third_party/pyproject.toml Removes the previous third-party benchmark project definition (now replaced by packages/bench-third-party).
benches/README.md Documents the split between benches/ (benchmarks) and monoprop-bench-tools (reusable harness) plus the standalone third-party project.
benches/conftest.py Updates imports to consume builders/memory tooling from monoprop-bench-tools and clarifies the artifact schema boundary.
benches/bench_random.py Updates to import barriered from the new tools package.
benches/bench_models.py Updates to import model registry/build helpers from the new tools package and updates doc references.
AGENTS.md Documents the new workspace layout and the cross-package schema seam between bench writer and renderers.
justfile Updates test groups to workspace-test and switches report/BMF invocations to the new console scripts.
docs/content/docs/testing.mdx Documents that uv run pytest now collects both root and tools-member test suites and how to install them.
docs/content/docs/benchmarks.mdx Updates paths and commands to match the new packages/bench-third-party location and console scripts.
.gitignore Ignores hatch-vcs/setuptools-scm generated version files for workspace members and adds logs/.
.github/workflows/test.yml Installs workspace-test group in CI so both test suites can be collected/imported.
.github/workflows/qa-analysis.yml Installs workspace-test group for QA analysis runs.
.github/workflows/deploy.yml Adds build+upload jobs for monoprop-bench-tools and wires PR-change detection for its pyproject.toml.
.github/ISSUE_TEMPLATE/performance_issue.yml Updates suggested repro steps to the new uv sync + just bench-smoke flow.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/monoprop-bench-tools/src/monoprop_bench_tools/__init__.py Outdated
Comment thread packages/monoprop-bench-tools/src/monoprop_bench_tools/__init__.py
Comment thread packages/monoprop-bench-tools/tests/conftest.py Outdated
Comment thread packages/monoprop-bench-tools/pyproject.toml
Comment thread packages/monoprop-bench-tools/pyproject.toml Outdated
Comment thread packages/monoprop-bench-tools/README.md Outdated
Comment thread pyproject.toml Outdated
Comment thread sonar-project.properties Outdated
Comment thread .github/workflows/deploy.yml Outdated
Comment thread .github/workflows/deploy.yml
Comment thread .github/workflows/deploy.yml Outdated

@robertodr robertodr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall LGTM! Thank you @Panadestein I think we'll gain very valuable experience with uv workspaces. I have some comments on the extras for the other workspace packages.

Panadestein and others added 13 commits August 17, 2026 13:31
Co-authored-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>
Signed-off-by: Ramón L. Panadés-Barrueta <rpana92@gmail.com>
Co-authored-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>
Signed-off-by: Ramón L. Panadés-Barrueta <rpana92@gmail.com>
Co-authored-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>
Signed-off-by: Ramón L. Panadés-Barrueta <rpana92@gmail.com>
Co-authored-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>
Signed-off-by: Ramón L. Panadés-Barrueta <rpana92@gmail.com>
Co-authored-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>
Signed-off-by: Ramón L. Panadés-Barrueta <rpana92@gmail.com>
Co-authored-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>
Signed-off-by: Ramón L. Panadés-Barrueta <rpana92@gmail.com>
Co-authored-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>
Signed-off-by: Ramón L. Panadés-Barrueta <rpana92@gmail.com>
Shortens the GPU install to one line, as asked for in review:

    pip install "monoprop-bench-tools[gpu-cuda12]"

No `[tool.uv] conflicts` pair to go with them. Declaring one does stop the
nonsensical "both extras at once", but uv validates the conflict set eagerly, so
it also makes `uv sync --all-extras` fail for the *whole* workspace -- the form
used by the devcontainer, the VS Code build tasks, and test/qa/bench/setup CI.
Measured either way: declared at the workspace root or in the member, both break
it. Without the pair, root `--all-extras` resolves clean and never pulls CuPy,
while `--extra gpu-cuda12` installs exactly one build.

The lockfile grows by cupy-cuda12x, cupy-cuda13x and cuda-pathfinder (96 -> 99
entries). Nothing installs them unless the extra is asked for.

Assisted-by: GitHubCopilot:claude-opus-5
Comment thread packages/monoprop-bench-tools/pyproject.toml Outdated
Co-authored-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>
Signed-off-by: Roberto Di Remigio Eikås <robertodr@users.noreply.github.com>

@robertodr robertodr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you!

@robertodr
robertodr enabled auto-merge (squash) August 19, 2026 07:41
@robertodr
robertodr requested a lite review from Copilot August 19, 2026 07:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 35 out of 57 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/monoprop-bench-tools/pyproject.toml:40

  • The PR description says there is no GPU extra on monoprop-bench-tools to avoid pulling CuPy (and cuda-pathfinder) into the root lock, but the package now defines gpu-cuda12 / gpu-cuda13 extras (and uv.lock includes cupy-cuda12x, cupy-cuda13x, cuda-pathfinder). Please align the implementation with the stated design decision: either remove these extras (and related docs) or update the PR description/rationale to reflect that the extras (and lock growth) are intentional.

@robertodr
robertodr merged commit 1b7533f into main Aug 19, 2026
33 checks passed
@robertodr
robertodr deleted the refactor/bench-tools-uv-workspace branch August 19, 2026 08:00
@sonarqubecloud

Copy link
Copy Markdown

robertodr pushed a commit that referenced this pull request Aug 19, 2026
🤖 _AI text below_ 🤖

Follow-up to #227.

## The diagnosis (confirmed)

`monoprop_bench_tools` declares the `Typing :: Typed` classifier and is
fully annotated, but it shipped no PEP 561 `py.typed` marker. Since it
resolves as an *installed library* (its source tree lives under
`packages/`, outside the `[tool.pyright] include` set), pyright/Pylance
treat it as untyped and emit `reportMissingTypeStubs` on every import in
`benches/conftest.py`.

`monoprop` itself is unaffected because nanobind's stubgen already
generates a marker (`src/monoprop/bindings/CMakeLists.txt`,
`MARKER_FILE`).

Reproduced and verified with pyright 1.1.408 against the workspace
environment:

Before:
```
benches/conftest.py:44:6 - warning: Stub file not found for "monoprop_bench_tools.memory.cpu" (reportMissingTypeStubs)
benches/conftest.py:50:6 - warning: Stub file not found for "monoprop_bench_tools.models" (reportMissingTypeStubs)
benches/conftest.py:62:10 - warning: Stub file not found for "monoprop_bench_tools.models" (reportMissingTypeStubs)
```

After: 0 warnings.

## The change

One empty file:
`packages/monoprop-bench-tools/src/monoprop_bench_tools/py.typed`.

Also verified the marker actually reaches consumers of the published
distribution — `uv build --package monoprop-bench-tools --wheel`
produces a wheel containing `monoprop_bench_tools/py.typed`, so
hatchling picks it up without any extra `[tool.hatch.build]` include
rule.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation test-in-draft Run CI even in Draft mode

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants