Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Use slots in attrs classes where possible (#8296)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
clokep committed Sep 14, 2020
1 parent d2a3eb0 commit aec294e
Show file tree
Hide file tree
Showing 22 changed files with 33 additions and 50 deletions.
1 change: 1 addition & 0 deletions changelog.d/8296.misc
@@ -0,0 +1 @@
Use slotted classes where possible.
2 changes: 1 addition & 1 deletion synapse/handlers/acme_issuing_service.py
Expand Up @@ -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:
"""
Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/auth.py
Expand Up @@ -1235,7 +1235,7 @@ def add_query_param_to_url(url: str, param_name: str, param: Any):
return urllib.parse.urlunparse(url_parts)


@attr.s
@attr.s(slots=True)
class MacaroonGenerator:

hs = attr.ib()
Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/e2e_keys.py
Expand Up @@ -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.
"""
Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/federation.py
Expand Up @@ -86,7 +86,7 @@
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
Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/saml_handler.py
Expand Up @@ -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"""

Expand Down
34 changes: 10 additions & 24 deletions synapse/handlers/sync.py
Expand Up @@ -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
Expand All @@ -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.
"""
Expand All @@ -127,8 +125,6 @@ def __nonzero__(self) -> bool:
# else in the result, we don't need to send it.
)

__bool__ = __nonzero__ # python3


@attr.s(slots=True, frozen=True)
class ArchivedSyncResult:
Expand All @@ -137,38 +133,32 @@ 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:
join = attr.ib(type=JsonDict)
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:
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -243,8 +231,6 @@ def __nonzero__(self) -> bool:
or self.groups
)

__bool__ = __nonzero__ # python3


class SyncHandler:
def __init__(self, hs: "HomeServer"):
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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`.
Expand Down
2 changes: 1 addition & 1 deletion synapse/http/federation/well_known_resolver.py
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion synapse/http/matrixfederationclient.py
Expand Up @@ -76,7 +76,7 @@
_next_id = 1


@attr.s(frozen=True)
@attr.s(slots=True, frozen=True)
class MatrixFederationRequest:
method = attr.ib()
"""HTTP method
Expand Down
4 changes: 1 addition & 3 deletions synapse/logging/context.py
Expand Up @@ -217,11 +217,9 @@ def add_database_scheduled(self, sched_sec):
def record_event_fetch(self, event_count):
pass

def __nonzero__(self):
def __bool__(self):
return False

__bool__ = __nonzero__ # python3


SENTINEL_CONTEXT = _Sentinel()

Expand Down
4 changes: 2 additions & 2 deletions synapse/metrics/__init__.py
Expand Up @@ -59,7 +59,7 @@ def collect():
yield metric


@attr.s(hash=True)
@attr.s(slots=True, hash=True)
class LaterGauge:

name = attr.ib(type=str)
Expand Down Expand Up @@ -205,7 +205,7 @@ def _register_with_collector(self):
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
Expand Down
4 changes: 1 addition & 3 deletions synapse/notifier.py
Expand Up @@ -164,11 +164,9 @@ def new_listener(self, token: StreamToken) -> _NotificationListener:


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
Expand Down
4 changes: 2 additions & 2 deletions synapse/replication/tcp/streams/_base.py
Expand Up @@ -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.
Expand Down Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion synapse/rest/media/v1/preview_url_resource.py
Expand Up @@ -102,7 +102,7 @@
_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])
Expand Down
2 changes: 1 addition & 1 deletion synapse/state/__init__.py
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/databases/main/end_to_end_keys.py
Expand Up @@ -35,7 +35,7 @@
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"""

Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/databases/main/event_push_actions.py
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/databases/main/ui_auth.py
Expand Up @@ -23,7 +23,7 @@
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.
Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/prepare_database.py
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/relations.py
Expand Up @@ -22,7 +22,7 @@
logger = logging.getLogger(__name__)


@attr.s
@attr.s(slots=True)
class PaginationChunk:
"""Returned by relation pagination APIs.
Expand Down
2 changes: 1 addition & 1 deletion synapse/util/__init__.py
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion synapse/util/caches/__init__.py
Expand Up @@ -42,7 +42,7 @@
response_cache_total = Gauge("synapse_util_caches_response_cache:total", "", ["name"])


@attr.s
@attr.s(slots=True)
class CacheMetric:

_cache = attr.ib()
Expand Down

0 comments on commit aec294e

Please sign in to comment.