Use slots in attrs classes where possible (#8296)

slots use less memory (and attribute access is faster) while slightly
limiting the flexibility of the class attributes. This focuses on objects
which are instantiated "often" and for short periods of time.
This commit is contained in:
Patrick Cloke 2020-09-14 12:50:06 -04:00 committed by GitHub
parent d2a3eb04a4
commit aec294ee0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 33 additions and 50 deletions

1
changelog.d/8296.misc Normal file
View file

@ -0,0 +1 @@
Use slotted classes where possible.

View file

@ -76,7 +76,7 @@ def create_issuing_service(reactor, acme_url, account_key_file, well_known_resou
)
@attr.s
@attr.s(slots=True)
@implementer(ICertificateStore)
class ErsatzStore:
"""

View file

@ -1235,7 +1235,7 @@ class AuthHandler(BaseHandler):
return urllib.parse.urlunparse(url_parts)
@attr.s
@attr.s(slots=True)
class MacaroonGenerator:
hs = attr.ib()

View file

@ -1201,7 +1201,7 @@ def _one_time_keys_match(old_key_json, new_key):
return old_key == new_key_copy
@attr.s
@attr.s(slots=True)
class SignatureListItem:
"""An item in the signature list as used by upload_signatures_for_device_keys.
"""

View file

@ -86,7 +86,7 @@ from synapse.visibility import filter_events_for_server
logger = logging.getLogger(__name__)
@attr.s
@attr.s(slots=True)
class _NewEventInfo:
"""Holds information about a received event, ready for passing to _handle_new_events

View file

@ -46,7 +46,7 @@ class MappingException(Exception):
"""Used to catch errors when mapping the SAML2 response to a user."""
@attr.s
@attr.s(slots=True)
class Saml2SessionData:
"""Data we track about SAML2 sessions"""

View file

@ -89,14 +89,12 @@ class TimelineBatch:
events = attr.ib(type=List[EventBase])
limited = attr.ib(bool)
def __nonzero__(self) -> bool:
def __bool__(self) -> bool:
"""Make the result appear empty if there are no updates. This is used
to tell if room needs to be part of the sync result.
"""
return bool(self.events)
__bool__ = __nonzero__ # python3
# We can't freeze this class, because we need to update it after it's instantiated to
# update its unread count. This is because we calculate the unread count for a room only
@ -114,7 +112,7 @@ class JoinedSyncResult:
summary = attr.ib(type=Optional[JsonDict])
unread_count = attr.ib(type=int)
def __nonzero__(self) -> bool:
def __bool__(self) -> bool:
"""Make the result appear empty if there are no updates. This is used
to tell if room needs to be part of the sync result.
"""
@ -127,8 +125,6 @@ class JoinedSyncResult:
# else in the result, we don't need to send it.
)
__bool__ = __nonzero__ # python3
@attr.s(slots=True, frozen=True)
class ArchivedSyncResult:
@ -137,26 +133,22 @@ class ArchivedSyncResult:
state = attr.ib(type=StateMap[EventBase])
account_data = attr.ib(type=List[JsonDict])
def __nonzero__(self) -> bool:
def __bool__(self) -> bool:
"""Make the result appear empty if there are no updates. This is used
to tell if room needs to be part of the sync result.
"""
return bool(self.timeline or self.state or self.account_data)
__bool__ = __nonzero__ # python3
@attr.s(slots=True, frozen=True)
class InvitedSyncResult:
room_id = attr.ib(type=str)
invite = attr.ib(type=EventBase)
def __nonzero__(self) -> bool:
def __bool__(self) -> bool:
"""Invited rooms should always be reported to the client"""
return True
__bool__ = __nonzero__ # python3
@attr.s(slots=True, frozen=True)
class GroupsSyncResult:
@ -164,11 +156,9 @@ class GroupsSyncResult:
invite = attr.ib(type=JsonDict)
leave = attr.ib(type=JsonDict)
def __nonzero__(self) -> bool:
def __bool__(self) -> bool:
return bool(self.join or self.invite or self.leave)
__bool__ = __nonzero__ # python3
@attr.s(slots=True, frozen=True)
class DeviceLists:
@ -181,13 +171,11 @@ class DeviceLists:
changed = attr.ib(type=Collection[str])
left = attr.ib(type=Collection[str])
def __nonzero__(self) -> bool:
def __bool__(self) -> bool:
return bool(self.changed or self.left)
__bool__ = __nonzero__ # python3
@attr.s
@attr.s(slots=True)
class _RoomChanges:
"""The set of room entries to include in the sync, plus the set of joined
and left room IDs since last sync.
@ -227,7 +215,7 @@ class SyncResult:
device_one_time_keys_count = attr.ib(type=JsonDict)
groups = attr.ib(type=Optional[GroupsSyncResult])
def __nonzero__(self) -> bool:
def __bool__(self) -> bool:
"""Make the result appear empty if there are no updates. This is used
to tell if the notifier needs to wait for more events when polling for
events.
@ -243,8 +231,6 @@ class SyncResult:
or self.groups
)
__bool__ = __nonzero__ # python3
class SyncHandler:
def __init__(self, hs: "HomeServer"):
@ -2038,7 +2024,7 @@ def _calculate_state(
return {event_id_to_key[e]: e for e in state_ids}
@attr.s
@attr.s(slots=True)
class SyncResultBuilder:
"""Used to help build up a new SyncResult for a user
@ -2074,7 +2060,7 @@ class SyncResultBuilder:
to_device = attr.ib(type=List[JsonDict], default=attr.Factory(list))
@attr.s
@attr.s(slots=True)
class RoomSyncResultBuilder:
"""Stores information needed to create either a `JoinedSyncResult` or
`ArchivedSyncResult`.

View file

@ -311,7 +311,7 @@ def _parse_cache_control(headers: Headers) -> Dict[bytes, Optional[bytes]]:
return cache_controls
@attr.s()
@attr.s(slots=True)
class _FetchWellKnownFailure(Exception):
# True if we didn't get a non-5xx HTTP response, i.e. this may or may not be
# a temporary failure.

View file

@ -76,7 +76,7 @@ MAXINT = sys.maxsize
_next_id = 1
@attr.s(frozen=True)
@attr.s(slots=True, frozen=True)
class MatrixFederationRequest:
method = attr.ib()
"""HTTP method

View file

@ -217,11 +217,9 @@ class _Sentinel:
def record_event_fetch(self, event_count):
pass
def __nonzero__(self):
def __bool__(self):
return False
__bool__ = __nonzero__ # python3
SENTINEL_CONTEXT = _Sentinel()

View file

@ -59,7 +59,7 @@ class RegistryProxy:
yield metric
@attr.s(hash=True)
@attr.s(slots=True, hash=True)
class LaterGauge:
name = attr.ib(type=str)
@ -205,7 +205,7 @@ class InFlightGauge:
all_gauges[self.name] = self
@attr.s(hash=True)
@attr.s(slots=True, hash=True)
class BucketCollector:
"""
Like a Histogram, but allows buckets to be point-in-time instead of

View file

@ -164,11 +164,9 @@ class _NotifierUserStream:
class EventStreamResult(namedtuple("EventStreamResult", ("events", "tokens"))):
def __nonzero__(self):
def __bool__(self):
return bool(self.events)
__bool__ = __nonzero__ # python3
class Notifier:
""" This class is responsible for notifying any listeners when there are

View file

@ -383,7 +383,7 @@ class CachesStream(Stream):
the cache on the workers
"""
@attr.s
@attr.s(slots=True)
class CachesStreamRow:
"""Stream to inform workers they should invalidate their cache.
@ -441,7 +441,7 @@ class DeviceListsStream(Stream):
told about a device update.
"""
@attr.s
@attr.s(slots=True)
class DeviceListsStreamRow:
entity = attr.ib(type=str)

View file

@ -102,7 +102,7 @@ for endpoint, globs in _oembed_globs.items():
_oembed_patterns[re.compile(pattern)] = endpoint
@attr.s
@attr.s(slots=True)
class OEmbedResult:
# Either HTML content or URL must be provided.
html = attr.ib(type=Optional[str])

View file

@ -678,7 +678,7 @@ def resolve_events_with_store(
)
@attr.s
@attr.s(slots=True)
class StateResolutionStore:
"""Interface that allows state resolution algorithms to access the database
in well defined way.

View file

@ -35,7 +35,7 @@ if TYPE_CHECKING:
from synapse.handlers.e2e_keys import SignatureListItem
@attr.s
@attr.s(slots=True)
class DeviceKeyLookupResult:
"""The type returned by get_e2e_device_keys_and_signatures"""

View file

@ -969,7 +969,7 @@ def _action_has_highlight(actions):
return False
@attr.s
@attr.s(slots=True)
class _EventPushSummary:
"""Summary of pending event push actions for a given user in a given room.
Used in _rotate_notifs_before_txn to manipulate results from event_push_actions.

View file

@ -23,7 +23,7 @@ from synapse.types import JsonDict
from synapse.util import json_encoder, stringutils
@attr.s
@attr.s(slots=True)
class UIAuthSessionData:
session_id = attr.ib(type=str)
# The dictionary from the client root level, not the 'auth' key.

View file

@ -638,7 +638,7 @@ def _get_or_create_schema_state(txn, database_engine):
return None
@attr.s()
@attr.s(slots=True)
class _DirectoryListing:
"""Helper class to store schema file name and the
absolute path to it.

View file

@ -22,7 +22,7 @@ from synapse.api.errors import SynapseError
logger = logging.getLogger(__name__)
@attr.s
@attr.s(slots=True)
class PaginationChunk:
"""Returned by relation pagination APIs.

View file

@ -45,7 +45,7 @@ def unwrapFirstError(failure):
return failure.value.subFailure
@attr.s
@attr.s(slots=True)
class Clock:
"""
A Clock wraps a Twisted reactor and provides utilities on top of it.

View file

@ -42,7 +42,7 @@ response_cache_evicted = Gauge(
response_cache_total = Gauge("synapse_util_caches_response_cache:total", "", ["name"])
@attr.s
@attr.s(slots=True)
class CacheMetric:
_cache = attr.ib()