Breakwater

Backtest / #1032

perf: add __slots__ to Nodes

pypa/packaging#1032 · merged 2026-01-02 · base 842c16cef5 → head c39b6da9ab · ran on Docker

BLOCK

At least one behaviour change looks like an unintended regression.

Counterexamples · 1 class: 1 likely bug

P4

Old pickles break

inputMarker("os_name == 'foo'")
basepickled object loads and compares equal
headload: raises AttributeError
Likely bugvotes: 3 likely-bug

Adding __slots__ to the Node hierarchy changes the object layout, breaking unpickling of instances created by older pickled Marker objects. The PR is a performance refactor with no tests, docs, or changelog noting the compatibility break.

__slots__ = ()
perf: add __slots__ to Nodes

Found by: Ultra's planned example, project's test strings, hostile mutation · also caught by: Mutations of the PR's own test strings, Nemotron plan only

ran onlocal Docker · image bw-pair:f8c16265598b425b

Regression test verified passes on base, errors on head
def test_1032_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('gASVowAAAAAAAACMEXBhY2thZ2luZy5tYXJrZXJzlIwGTWFya2VylJOUKYGUfZSMCF9tYXJrZXJzlF2UjBFwYWNrYWdpbmcuX3BhcnNlcpSMCFZhcmlhYmxllJOUKYGUfZSMBXZhbHVllIwHb3NfbmFtZZRzYmgHjAJPcJSTlCmBlH2UaAyMAj09lHNiaAeMBVZhbHVllJOUKYGUfZRoDIwDZm9vlHNih5Rhc2Iu'))
    assert old is not None  # loading must not raise
Reproduce
uv run breakwater probe --repo https://github.com/pypa/packaging --base 842c16cef598 --head c39b6da9ab11 --target packaging.markers:Marker --backend docker --input "os_name == 'foo'"

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_1032.py

Performance · Marker

No realistic input family measured slower.

Measured in backtest packaging-v2 (same commits, run bt-1032-bd4ecb, image bw-pair:810a13228d4ca505). The semantic results above are from a later run; perf doesn't use the semantic planner, so it was not re-measured.

head slowerhead faster1×1001,00010,000100,000input size (characters)F2F2: 1.00× at ~58 charsF2: 1.00× at ~116 charsF2: 0.99× at ~470 charsF2: 0.99× at ~1,910 charsF2: 1.00× at ~7,826 charsF2: 0.99× at ~31,658 charsF2: 0.99× at ~129,962 chars
  • F2
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
F2large_flat_markerclaimed speedup · plan0.99× – 1.00×0.99 → 0.99neutral

Receipt

TargetBackendImageRun AuditAdjudication
packaging.markers:Markerlocal Dockerbw-pair:f8c16265598b425bbt-1032-961ae1$0.015$0.011

Nemotron cost on Nebius Token Factory. Backend: where the untrusted code ran. local Docker (an image cited by its content-addressed tag). 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.