perf: fast native RangeSet mutation with selectable locking - #20
Merged
Conversation
josephjohncox
force-pushed
the
perf/native-result-construction
branch
from
July 22, 2026 21:36
b317ec6 to
c750778
Compare
Trusted validation-free native result builders, cached bound native mutators with a construction-time contract probe, collapsed authoritative add/discard (no adapter frame or per-op isinstance), a user-selectable locking level (synchronized=True default; unsynchronized skips the per-op lock protocol), and a fully-native scalar release/reserve surface that returns only the changed length. cpp_boundary, Apple M5 Max, 30-sample hot-path benchmark: add/discard MutationResult synchronized 1.54M/s unsynchronized 1.65M/s scalar release/reserve synchronized 4.32M/s unsynchronized 5.06M/s plain-native floor 7.9M/s The unsynchronized scalar surface is ~5.5x the default add/discard and within ~65% of the raw-native floor, exactly geometry-consistent.
josephjohncox
force-pushed
the
perf/native-result-construction
branch
from
July 22, 2026 21:37
c750778 to
0995217
Compare
This was referenced Jul 22, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes the
cpp_boundary-backedRangeSetmutation hot path much faster and adds a fully-native scalar mutation surface with a user-selectable locking level. Four compounding changes, all preserving the exact publicMutationResult/Span/IntervalResultfrozen-dataclass contracts and every existing invariant (half-open signed-int geometry, failure atomicity, reentrancy protection, deterministic ordering, and snapshot/mutation consistency in synchronized mode).Baseline
add/discardwas 0.92 M ops/s. The new fully-native scalar unsynchronized path reaches ~5.06 M ops/s — about 5.5× the default and within ~65% of the raw-native floor.Changes
domain._native_span/_native_mutation_result). The native manager only emits int64 geometry it has already validated, so re-runningSpan.__post_init__on every returned delta was pure overhead. The builders construct the same frozen-dataclass instances (equal value, hash, ordering, repr, pickle) without that redundant validation. PublicSpan(...)construction still validates.add/discard. The authoritative path caches the bound nativerelease_with_delta/reserve_with_deltaat construction — behind a fail-closed contract probe — and skips theBackendAdapterwrapper frame plus the per-opisinstancecheck.synchronized).RangeSet(..., synchronized=True)(default),create_range_set(..., synchronized=True), andBackendRegistry.create(..., synchronized=True)keep the reentrant lock and full thread-safety.synchronized=Falseskips the per-opwith self._lock:protocol on the hot path entirely (its__enter__/__exit__calls, not lock contention, were the cost); the caller then owns all cross-thread synchronization and snapshot/mutation consistency. Both hot and non-hot paths use the same lock object, so synchronized mutual exclusion is intact.RangeSet.release(span) -> int(free/add semantics) andRangeSet.reserve(span, *, require_covered=False) -> int(occupy/discard semantics) return only the changed length, build noMutationResult, and are exactly geometry-consistent withadd/discard. They require an authoritative geometry-only range set and raise a clearValueErrorotherwise — never a silent fallback. Oncpp_boundarythey use dedicated native scalar mutators (release_delta_length/reserve_delta_length); other authoritative backends derive the exact changed length from the delta.Measured (cpp_boundary, Apple M5 Max, macOS 26.5.1, CPython 3.12.7, 30-sample hot-path benchmark)
add/discard(MutationResult), synchronizedadd/discard(MutationResult), unsynchronizedrelease/reserve, synchronizedrelease/reserve, unsynchronizedIntervalManager)Two levers compound: dropping eager
MutationResult/Spanconstruction is the larger win (~3× overadd/discard);synchronized=Falsethen removes the per-op lock protocol (~4.3M → ~5.06M). Scoped evidence for one interface family, one restorative workload, one host, one timing layer — not a universal claim. Reaching the literal 7.9M floor would require dropping the residual RangeSet bookkeeping (reentrancy guard,_total_free, cache invalidation), which would sacrifice the invariants above.New public API
RangeSet(..., synchronized=True),RangeSet.synchronizedRangeSet.release(span) -> int,RangeSet.reserve(span, *, require_covered=False) -> intcreate_range_set(..., synchronized=True),BackendRegistry.create(..., synchronized=True)BackendAdapter.supports_scalar_delta,release_delta_length,reserve_delta_lengthRangeSetProtocol.release,.reserveIntervalManager.release_delta_length,reserve_delta_lengthCorrectness & evidence
tests/unit/test_rangeset_scalar_hotpath.py: scalar vsMutationResultdifferential across every authoritative stable backend, boundary/negative/int64-extreme/no-op cases, both locking levels, single-threaded agreement, concurrent-consistency under synchronized mode, construction-probe fail-closed, capability guards, atomicity on domain/overflow and injected result-construction failure, and exact frozen-dataclass identity (trusted-built spans equal validated ones; public construction still validates).test_native_core_contract.pyatomicity injection to the real trusted-builder allocation point (domain._object_new), proving result materialization precedes the native mutation.tests/performance/rangeset_hotpath_benchmark.py+scripts/verify_rangeset_hotpath_benchmark.py+test_rangeset_hotpath_benchmark_artifact.py: canonical JSON/Markdown/SHA-256 triplet with strict duplicate-key/non-finite/exact-type rejection and source/runtime/binary provenance; same-instance correctness validated outside timing.docs/performance.md: "Locking levels and the fully-native scalar path" section with the measured table and the explicit unsynchronized concurrency contract;Justfilebenchmark-hotpathrecipe.Validation
mypy treemendousclean (114 files); Ruff check + format clean;git diff --checkclean.Boundaries preserved
add/discard/MutationResult/Span/IntervalResultpublic semantics or types.synchronized=Falseis opt-in and its concurrency contract is documented explicitly.