Repository navigation
Release 1.0.3: store active-section frames as plain tuples - #22
Merged
Merged
Conversation
Constructing the _Frame NamedTuple ran a Python-level __new__ that cost about 190 ns, more than the rest of section entry combined. A plain tuple costs about 30 ns, making entering and exiting a section 20-25% faster across 3.11, 3.14 and free-threaded 3.14t. Behaviour is unchanged. Also refresh the overhead benchmark with 0.1.0, 1.0.2 and 1.0.3 measured back to back, and release the documentation site changes, so the PyPI page gets the shorter README and the Documentation link.
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.
What does this change?
Performance. Every section entry built a
_FrameNamedTuple, whose constructor runs in Python and costs about 190 ns. That's more than the rest of section entry combined; a plain tuple costs about 30 ns._Frameis now a type alias for a plain tuple, unpacked where it's read. It's internal only, so the public API and behaviour are the same.Measured back to back on CPython 3.14.5 (macOS, ARM64), in µs per operation:
It's a similar 13–20% on 3.11 and on free-threaded 3.14t. Reporting paths are unchanged.
I also tried inlining the timer logic into
TimerContext.__enter__. It gained only 2–7%, within noise, so I left it out. What's left of the cost is the lock, theContextVarandperf_countercalls, which the thread and async safety depend on.Docs:
benchmarks/README.mdnow compares 0.1.0, 1.0.2 and 1.0.3, measured one after the other on the same interpreter. The docs overhead page includes this table.Release: bumps
__version__to 1.0.3 and moves the unreleased documentation-site entries into 1.0.3. Publishing it updates the PyPI page with the shorter README and adds theDocumentationlink.Checklist
uv run pytest --covpasses (112 tests, 100% statement and branch coverage). It also passes locally on 3.12, 3.13, 3.14 and 3.14t.uv run ruff checkanduv run ruff format --checkpassuv run basedpyrightpasses (0 errors, 0 warnings)CHANGELOG.mdupdateduv buildandtwine check --strictpass, the wheel reports 1.0.3, and the Sphinx build passes with-W -n.