proj/pkgcore/snakeoil:master commit in: /, src/snakeoil/klass/
"Arthur Zamarin" <[email protected]>
| Newsgroups | gmane.linux.gentoo.cvs |
|---|---|
| Message-ID | <1786137609.9ea8b9d99bf77a8b7cffc9a1c3cba8abafd9b9ec.arthurzam@gentoo> |
commit: 9ea8b9d99bf77a8b7cffc9a1c3cba8abafd9b9ec
Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Fri Aug 7 21:20:09 2026 +0000
Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Fri Aug 7 21:20:09 2026 +0000
URL: https://gitweb.gentoo.org/proj/pkgcore/snakeoil.git/commit/?id=9ea8b9d9
klass.immutable: inline the mutation block into the autowrapper
__allow_mutation_wrapper__ entered __allow_mutation__ via `with`, so every
auto wrapped __init__ built a generator, drove it through __enter__ and
__exit__, and tore it down - all to set one contextvar and reset it. Do
that directly in the wrapper instead. __allow_mutation__ itself is
untouched and still the way to open a mutation block by hand; nothing
overrides it, so the wrapper was it's only caller.
Semantics are identical: same contextvar, same id(instance), same reset in
a finally. Construction of small immutable instances gets cheaper, the
saving being a fixed cost per call rather than per attribute:
StrExactMatch 0.047s -> 0.031s 1.53x
PackageRestriction 0.128s -> 0.111s 1.16x
atom 0.212s -> 0.195s 1.09x
19602 restriction trees 0.270s -> 0.236s 1.15x
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>
NEWS.rst | 4 ++++
src/snakeoil/klass/immutable.py | 7 ++++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/NEWS.rst b/NEWS.rst
index 9898052..556a36d 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -23,6 +23,10 @@ snakeoil 0.11.4 (unreleased)
serialization. Dropping it makes serializing slotted objects ~4x faster
(Arthur Zamarin, #117)
+- ``snakeoil.klass.immutable.Simple``: methods auto wrapped in a mutation block
+ no longer build and drive a ``@contextmanager`` generator per call. Creating
+ small immutable instances is up to 1.5x faster (Arthur Zamarin)
+
snakeoil 0.11.3 (2026-07-30)
----------------------------
diff --git a/src/snakeoil/klass/immutable.py b/src/snakeoil/klass/immutable.py
index 8d0c972..e47d967 100644
--- a/src/snakeoil/klass/immutable.py
+++ b/src/snakeoil/klass/immutable.py
@@ -122,8 +122,13 @@ class Simple:
def __allow_mutation_wrapper__(cls, functor):
@functools.wraps(functor)
def f(instance, *args, **kwargs):
- with cls.__allow_mutation__(instance):
+ # __allow_mutation__ inlined; building and driving it's generator is
+ # the dominant cost of creating small immutable instances.
+ last = _immutable_allow_mutations.set(id(instance))
+ try:
return functor(instance, *args, **kwargs)
+ finally:
+ _immutable_allow_mutations.reset(last)
f.__disable_mutation_autowrapping__ = True # pyright: ignore[reportAttributeAccessIssue] # it's already wrapped.
return f