Skip to content

use __slots__ where possible#2856

Closed
albertedwardson wants to merge 1 commit intoKludex:mainfrom
albertedwardson:slots
Closed

use __slots__ where possible#2856
albertedwardson wants to merge 1 commit intoKludex:mainfrom
albertedwardson:slots

Conversation

@albertedwardson
Copy link
Copy Markdown

Summary

this breaks weakrefs, but I believe the objects in question shouldn't be weakref`ed anyway

Checklist

  • I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.

@albertedwardson albertedwardson changed the title use __slots__ wjere possible use __slots__ where possible Mar 17, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 17, 2026

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing albertedwardson:slots (91da498) with main (02bed6f)

Open in CodSpeed

Copy link
Copy Markdown
Contributor

@hrv-dys hrv-dys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The __slots__ additions make sense for the protocol classes — these are instantiated per-connection, so reducing per-instance memory overhead adds up under load.

A few things:

  1. ServerState as a @dataclass(slots=True) — clean conversion. The field(default_factory=...) for the mutable defaults (set, list) is correct and avoids the classic mutable-default-argument footgun.

  2. FlowControl as a dataclass — the __post_init__ to call self._is_writable_event.set() is a nice touch. However, I notice repr=False, eq=False on both dataclasses — is that to avoid accidentally comparing or printing these in hot paths? Might be worth a brief comment for future readers.

  3. The limit_max_requests change from @functools.cached_property to __init__ assignment — this is necessary because __slots__ and cached_property don't play well together (cached_property needs __dict__). The rename to _limit_max_requests() as a regular method called in __init__ is a reasonable workaround. Just want to flag: this changes the laziness — it's now computed eagerly at construction time. In practice this shouldn't matter since Server.__init__ is called once, but it's a behavioral change worth noting.

  4. H11Protocol and HttpToolsProtocol slots lists — I spot-checked these against the __init__ methods and they look complete. If a future PR adds an attribute and forgets to update __slots__, it'll silently fall through to a per-instance __dict__ (unless I'm wrong and asyncio.Protocol doesn't define __dict__?). Actually, since the base asyncio.Protocol doesn't use __slots__, subclasses still get __dict__. So the slots here act as a performance hint rather than a strict contract. That's fine, just worth being aware of.

Tests pass with only pre-existing failures (websockets deprecation warnings unrelated to this PR).

@albertedwardson
Copy link
Copy Markdown
Author

@hrv-dys unfortunately llm didn't catch that my changes with @dataclass changes the __init__ signature

self.write_paused = False
self._is_writable_event = asyncio.Event()
_transport: asyncio.Transport
read_paused: bool = False
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

init=False or don't use dataclasses at all

@albertedwardson
Copy link
Copy Markdown
Author

can be closed in favour of #2697 that already introduces slots

or maybe just deffered until the mentioned one will be merged

@albertedwardson albertedwardson marked this pull request as draft March 27, 2026 06:29
@Kludex
Copy link
Copy Markdown
Owner

Kludex commented Apr 18, 2026

@albertedwardson I think if we can find meaningful proof of performance improvement then it's worth it, otherwise I would prefer to close it for the time being. Thanks for the push tho.

@Kludex Kludex closed this Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants