Skip to content

feat(py): use the sysmon coverage core on Python 3.12+ - #1534

Draft
xangcastle wants to merge 1 commit into
mainfrom
sysmon-coverage-core
Draft

xangcastle wants to merge 1 commit into
mainfrom
sysmon-coverage-core

Conversation

@xangcastle

Copy link
Copy Markdown
Member

What

start_coverage() now drives coveragepy through a per-process rcfile instead of constructor kwargs, which lets it:

  • select core = sysmon (the sys.monitoring / PEP 669 backend) on Python 3.12+, falling back to coveragepy's default core on older interpreters;
  • give every test process its own data_file under TEST_TMPDIR, so shards or chdir tests running concurrently out of one directory no longer race on the default .coverage database.

write_lcov() additionally tolerates coverage.exceptions.NoSource alongside NoDataError, writing an empty LCOV rather than failing an otherwise passing test.

Why

The sysmon core is markedly cheaper than the C tracer under bazel coverage. In a large monorepo consuming these rules the same change (carried as a local patch against the pre-launcher_env template) cut wall-clock of instrumented py_pytest_test targets by roughly a quarter to a third relative to the default core, across tests ranging from a few seconds to half a minute.

coveragepy only exposes the core choice through configuration ([run] core), hence the rcfile.

Notes for review

  • The NoSource tolerance mirrors the downstream patch. It is debatable upstream since it can hide a genuinely broken manifest; happy to drop it into a separate PR if preferred.
  • e2e/cases/coverage-drivers runs on 3.10, 3.11 and 3.12 and should cover both branches of the version gate. Not run locally yet; relying on CI.
  • sysmon needs coveragepy >= 7.4.0; the e2e lock pins 7.15.2.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 4802cf7f-9439-4bfd-a703-605cae85a97e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@aspect-workflows

aspect-workflows Bot commented Sep 8, 2026

Copy link
Copy Markdown

✨ Aspect Workflows Tasks

📅 Tue Sep 8 19:38:36 UTC 2026

✅ 44 successful tasks

  • ✅ buildifier · ⏱ 19s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ gazelle · ⏱ 17.2s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ test-e2e-bazel-8 [test] · ⏱ 6m 50s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (319/319 passed · 246 cached)
  • ✅ test-e2e-bazel-9 [test] · ⏱ 6m 34s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (309/309 passed)
  • ✅ test-e2e-crossbuild-bazel-8 [test] · ⏱ 4m 34s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (26/26 passed)
  • ✅ test-e2e-crossbuild-bazel-9 [test] · ⏱ 5m 1s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (26/26 passed)
  • ✅ test-e2e-interpreter-build-config-bazel-8 [test] · ⏱ 19.5s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-e2e-interpreter-build-config-bazel-9 [test] · ⏱ 1m 16s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-e2e-interpreter-input-validation-bazel-8 [test] · ⏱ 17.8s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-e2e-interpreter-input-validation-bazel-9 [test] · ⏱ 1m 46s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-e2e-interpreter-runtime-metadata-bazel-8 [test] · ⏱ 28.3s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (2/2 passed)
  • ✅ test-e2e-interpreter-runtime-metadata-bazel-9 [test] · ⏱ 38.3s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (2/2 passed)
  • ✅ test-e2e-interpreter-toolchain-settings-bazel-8 [test] · ⏱ 20.8s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-e2e-interpreter-toolchain-settings-bazel-9 [test] · ⏱ 1m 3s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-e2e-rules-proto-grpc-python-bazel-8 [test] · ⏱ 2m 7s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-e2e-rules-proto-grpc-python-bazel-9 [test] · ⏱ 1m 18s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-e2e-rules-python-interop-bazel-8 [test] · ⏱ 49.1s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (15/15 passed)
  • ✅ test-e2e-rules-python-interop-bazel-9 [test] · ⏱ 1m 7s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (15/15 passed)
  • ✅ test-e2e-rules-python-provider-compat-bazel-8 [test] · ⏱ 23.5s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (4/4 passed)
  • ✅ test-e2e-rules-python-provider-compat-bazel-9 [test] · ⏱ 1m 22s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (4/4 passed)
  • ✅ test-examples-debugger-bazel-8 [test] · ⏱ 29.6s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-debugger-bazel-9 [test] · ⏱ 1m 26s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-dev_deps-bazel-8 [test] · ⏱ 29.7s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-dev_deps-bazel-9 [test] · ⏱ 1m 13s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-django-bazel-8 [test] · ⏱ 22.2s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed · 1 cached)
  • ✅ test-examples-django-bazel-9 [test] · ⏱ 1m 35s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed · 1 cached)
  • ✅ test-examples-multi_version-bazel-8 [test] · ⏱ 34s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (2/2 passed)
  • ✅ test-examples-multi_version-bazel-9 [test] · ⏱ 1m 5s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (2/2 passed)
  • ✅ test-examples-protobuf-bazel-8 [test] · ⏱ 1m 17s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-protobuf-bazel-9 [test] · ⏱ 2m 3s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-py_binary-bazel-8 [test] · ⏱ 24.8s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed · 1 cached)
  • ✅ test-examples-py_binary-bazel-9 [test] · ⏱ 1m 32s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed · 1 cached)
  • ✅ test-examples-py_pex_binary-bazel-8 [test] · ⏱ 20.5s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed · 1 cached)
  • ✅ test-examples-py_pex_binary-bazel-9 [test] · ⏱ 1m 31s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed · 1 cached)
  • ✅ test-examples-py_venv-bazel-8 [test] · ⏱ 26.3s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (3/3 passed)
  • ✅ test-examples-py_venv-bazel-9 [test] · ⏱ 1m 14s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (3/3 passed)
  • ✅ test-examples-pytest-bazel-8 [test] · ⏱ 39.6s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (11/11 passed)
  • ✅ test-examples-pytest-bazel-9 [test] · ⏱ 1m · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (11/11 passed)
  • ✅ test-examples-uv_pip_compile-bazel-8 [test] · ⏱ 29.7s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-uv_pip_compile-bazel-9 [test] · ⏱ 1m 23s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-virtual_deps-bazel-8 [test] · ⏱ 24s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-examples-virtual_deps-bazel-9 [test] · ⏱ 1m 5s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (1/1 passed)
  • ✅ test-root-bazel-8 [test] · ⏱ 14m 11s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (369/369 passed)
  • ✅ test-root-bazel-9 [test] · ⏱ 17m 47s · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (368/368 passed)

⏱ Last updated Tue Sep 8 19:56:34 UTC 2026 · 📊 GitHub API quota 1,309/15,000 (9% used, resets in 23m)
🚀 Powered by Aspect CLI (v2026.28.2)  |  Aspect Build · X · LinkedIn · YouTube

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

py_binary startup benchmark

Version Mean (ms) Median (ms) ± stddev vs BCR vs main Build (s)
BCR 1.11.7 (baseline) 160.804 160.453 ±1.741 1.67
HEAD main 57.238 57.286 ±0.672 -64.3% 1.85
This PR 57.512 57.427 ±2.045 -64.2% +0.2% 1.64

Measured with hyperfine --warmup 5 --runs 50 --shell=none on Linux
Gate: PR vs HEAD main median (threshold: 10%, and must exceed the 2×SE noise floor, here 1.1%). BCR is shown only as a historical baseline.
Build time: cold bazel build //:bench with isolated output base, no disk cache; external repos prefetched so network is excluded.

sys.path quality

Version sys.path entries distinct site-packages roots duplicate realpaths
BCR 1.11.7 (baseline) 6 1 0
HEAD main 7 2 0
This PR 7 2 0

sys.path quality measured by bench_syspath inside the assembled venv. Duplicate realpaths indicate symlink redundancy; many distinct site-packages roots suggest an inefficient venv layout.

Bazel analysis benchmark

Version Mean (ms) Median (ms) ± stddev vs BCR vs main Targets Actions
BCR 2.0.0-alpha.6 (baseline) 1362.763 1236.274 ±255.101 304 13746
HEAD main 1346.330 1257.699 ±257.527 +1.7% 304 13546
This PR 1432.548 1335.636 ±267.412 +8.0% +6.2% 304 13546

Measured with hyperfine --warmup 1 --runs 10 on Linux
Gate: PR vs HEAD main median (threshold: 10%, and must exceed the 2×SE noise floor, here 18.7%). BCR is shown only as a historical baseline.
Command: warm-server bazel build --nobuild //workspace/..., analysis cache discarded each run via a fresh --action_env value; no disk cache.

py_image_layer benchmark

Scenario Version Mean (s) Median (s) ± stddev Actions vs BCR vs main
Analysis BCR 2.0.0-alpha.6 (baseline) 0.69 0.66 ±0.12 747
Analysis HEAD main 0.69 0.67 ±0.15 725 +1.3%
Analysis This PR 0.69 0.67 ±0.12 725 +1.9% +0.6%
1p Source Change BCR 2.0.0-alpha.6 (baseline) 0.69 0.67 ±0.06 4
1p Source Change HEAD main 0.70 0.68 ±0.10 5 +2.2%
1p Source Change This PR 0.72 0.70 ±0.11 5 +4.9% +2.7%
3p Source Change BCR 2.0.0-alpha.6 (baseline) 0.80 0.79 ±0.05 5
3p Source Change HEAD main 0.84 0.84 ±0.05 6 +6.9%
3p Source Change This PR 0.84 0.85 ±0.06 6 +7.1% +0.2%

Measured with hyperfine on Linux, building //workspace:image_layers (10 binaries, ~30-wheel dep pool, grouped first-party/pip/interpreter tier) with isolated output base, no disk cache.
Scenarios: analysis = warm-server bazel build --nobuild, re-analyzed each run via a fresh --action_env value; incrementals run against a built state with warm analysis: source = append to the last package's lib.py, wheel = rewrite click post_install_patches content.
Actions: for Analysis, the total action count behind the image target from aquery deps(...); for incrementals, actions re-executed for the mutation, from a single instrumented run's BEP build metrics (deterministic; per-mnemonic breakdown in the *-actions.json artifacts). Informational only, not gated.
Gate: PR vs HEAD main median per scenario (threshold: 10%, and must exceed the 2×SE noise floor). BCR is shown only as a historical baseline.

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