Skip to content

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

Draft
Panadestein wants to merge 1 commit into
mainfrom
refactor/bench-tools-uv-workspace
Draft

refactor(bench): 📦 release the benchmark harness as monoprop-bench-tools#227
Panadestein wants to merge 1 commit 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
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.

2 participants