Breakwater

Sandboxes / #1116

perf: Overhaul _cmpkey to remove use of custom objects

pypa/packaging#1116 · merged 2026-03-11 · base baa9ea8c7f → head f2bbd4f578 · ran on Sandboxes

BLOCK

At least one behaviour change looks like an unintended regression.

Known regressions in this PR

Counterexamples · 1 class: 1 likely bug

P4

Old pickles break

known regression: old-pickles-fail-to-load
inputVersion("0")
basepickled object loads and compares equal
headload: raises ModuleNotFoundError
Likely bugvotes: 3 likely-bug

The PR removes the `_structures` module and its `Infinity`/`NegativeInfinity` sentinel classes, which were used in the comparison key (`_cmpkey`) of `Version` objects. Pickled `Version` objects from the old version may contain references to these sentinel classes in their cached `_key_cache`. Unpickling them in the new version fails with `ModuleNotFoundError` because the module no longer exists. This is an unintended regression for users who rely on pickling `Version` objects across versions; the PR presents itself as a performance refactor and does not mention pickling compatibility in tests,

-@typing.final
-class InfinityType:

Found by: project's test strings, hostile mutation · also caught by: Mutations of the PR's own test strings

ran onToken Factory Sandboxes · image e7fbcc0c-cc99-4f27-9713-ec040778674e

Regression test verified passes on base, errors on head
def test_1116_p4_base_head_load_0():
    """Breakwater P4: base behaviour pinned (found by differential testing; label: likely-bug)."""
    import base64
    import pickle
    # pickled by the base version (lazy caches warmed first)
    old = pickle.loads(base64.b64decode('gASVygAAAAAAAACMEXBhY2thZ2luZy52ZXJzaW9ulIwHVmVyc2lvbpSTlCmBlE59lCiMBF9kZXaUTowGX2Vwb2NolEsAjApfa2V5X2NhY2hllChLACmMFXBhY2thZ2luZy5fc3RydWN0dXJlc5SMDEluZmluaXR5VHlwZZSTlCmBlGgIjBROZWdhdGl2ZUluZmluaXR5VHlwZZSTlCmBlGgLaA50lIwGX2xvY2FslE6MBV9wb3N0lE6MBF9wcmWUTowIX3JlbGVhc2WUSwCFlHWGlGIu'))
    assert old is not None  # loading must not raise
Reproduce
uv run breakwater probe --repo https://github.com/pypa/packaging --base baa9ea8c7fa7 --head f2bbd4f57864 --target packaging.version:Version --backend contree --input "0"

Regression tests

1 of 1 classes have a generated pytest that pins the old behaviour. Each passed on the base commit and failed on the head commit in the sandbox before it was offered.

Download test_1116.py

Performance · Version

No realistic input family measured slower.

head slowerhead faster1×1001,00010,000input size (characters)F1F1: 1.00× at ~34 charsF1: 1.00× at ~48 charsF1: 0.99× at ~146 charsF1: 1.00× at ~578 charsF1: 1.00× at ~2,620 charsF1: 0.99× at ~11,118 charsF1: 1.00× at ~51,054 chars
  • F1
Head/base cachegrind instructions per call, by input size (log-log). Each line is one input family Nemotron proposed; points above 1× are where the "faster" code does more work.
FamilyInputsRatio range Slope base → headVerdict
F1Complex version strings with epoch, pre, post, dev, and local segments that require full regex parsing (non-simple) and are compared repeatedly. The new regex uses possessive quantifiers (Python 3.11+) to avoid backtracking, and the new _cmpkey uses integer ranks for faster tuple comparison.claimed speedup · plan0.99× – 1.00×0.85 → 0.85neutral

Receipt

TargetBackendImageRun AuditAdjudication
packaging.version:VersionToken Factory Sandboxese7fbcc0c-cc99-4f27-9713-ec040778674ebt-1116-7a94ad$0.23$0.046

Nemotron cost on Nebius Token Factory. Backend: where the untrusted code ran. Token Factory Sandboxes (a microVM branched from a kept image, cited by its UUID). Every image is content-addressed (repo at each commit + harness), so every card re-runs from the image and seed 0. Raw data: audit, adjudication.