Skip to content

Commit d850836

Browse files
committed
Add __slots__ to Host and HostConnection classes for memory optimization
This commit introduces __slots__ to the Host and HostConnection classes in cassandra/pool.py to reduce memory footprint of frequently instantiated objects in connection pools and cluster metadata. Changes: - Added __slots__ tuple to Host class with 18 actively used attributes - Added __slots__ tuple to HostConnection class with 17 actively used attributes - Consolidated class documentation from individual attribute docstrings to comprehensive class-level docstrings - Added explicit attribute initialization in __init__ methods to set default values for attributes that previously relied on class variables - Removed unused attributes (listen_address, listen_port) from Host class after comprehensive usage analysis showed they were never used - Fixed trailing whitespace issues in modified code The __slots__ implementation prevents dynamic attribute creation and reduces per-instance memory overhead, which is significant for drivers managing large numbers of hosts and connections. All existing functionality is preserved and tests continue to pass. Memory impact: Each Host instance saves ~2 unused slots, and both classes benefit from __slots__ memory layout optimization. Signed-off-by: Yaniv Kaul <yaniv.kaul@scylladb.com>
1 parent 5994583 commit d850836

1 file changed

Lines changed: 54 additions & 133 deletions

File tree

cassandra/pool.py

Lines changed: 54 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -49,123 +49,31 @@ class NoConnectionsAvailable(Exception):
4949
class Host(object):
5050
"""
5151
Represents a single Cassandra node.
52-
"""
53-
54-
endpoint = None
55-
"""
56-
The :class:`~.connection.EndPoint` to connect to the node.
57-
"""
58-
59-
broadcast_address = None
60-
"""
61-
broadcast address configured for the node, *if available*:
62-
63-
'system.local.broadcast_address' or 'system.peers.peer' (Cassandra 2-3)
64-
'system.local.broadcast_address' or 'system.peers_v2.peer' (Cassandra 4)
65-
66-
This is not present in the ``system.local`` table for older versions of Cassandra. It
67-
is also not queried if :attr:`~.Cluster.token_metadata_enabled` is ``False``.
68-
"""
69-
70-
broadcast_port = None
71-
"""
72-
broadcast port configured for the node, *if available*:
73-
74-
'system.local.broadcast_port' or 'system.peers_v2.peer_port' (Cassandra 4)
75-
76-
It is also not queried if :attr:`~.Cluster.token_metadata_enabled` is ``False``.
77-
"""
78-
79-
broadcast_rpc_address = None
80-
"""
81-
The broadcast rpc address of the node:
82-
83-
'system.local.rpc_address' or 'system.peers.rpc_address' (Cassandra 3)
84-
'system.local.rpc_address' or 'system.peers.native_transport_address (DSE 6+)'
85-
'system.local.rpc_address' or 'system.peers_v2.native_address (Cassandra 4)'
86-
"""
87-
88-
broadcast_rpc_port = None
89-
"""
90-
The broadcast rpc port of the node, *if available*:
91-
92-
'system.local.rpc_port' or 'system.peers.native_transport_port' (DSE 6+)
93-
'system.local.rpc_port' or 'system.peers_v2.native_port' (Cassandra 4)
94-
"""
95-
96-
listen_address = None
97-
"""
98-
listen address configured for the node, *if available*:
99-
100-
'system.local.listen_address'
101-
102-
This is only available in the ``system.local`` table for newer versions of Cassandra. It is also not
103-
queried if :attr:`~.Cluster.token_metadata_enabled` is ``False``. Usually the same as ``broadcast_address``
104-
unless configured differently in cassandra.yaml.
105-
"""
106-
107-
listen_port = None
108-
"""
109-
listen port configured for the node, *if available*:
110-
111-
'system.local.listen_port'
112-
113-
This is only available in the ``system.local`` table for newer versions of Cassandra. It is also not
114-
queried if :attr:`~.Cluster.token_metadata_enabled` is ``False``.
115-
"""
116-
117-
conviction_policy = None
118-
"""
119-
A :class:`~.ConvictionPolicy` instance for determining when this node should
120-
be marked up or down.
121-
"""
122-
123-
is_up = None
124-
"""
125-
:const:`True` if the node is considered up, :const:`False` if it is
126-
considered down, and :const:`None` if it is not known if the node is
127-
up or down.
128-
"""
129-
130-
release_version = None
131-
"""
132-
release_version as queried from the control connection system tables
133-
"""
134-
135-
host_id = None
136-
"""
137-
The unique identifier of the cassandra node
138-
"""
139-
140-
dse_version = None
141-
"""
142-
dse_version as queried from the control connection system tables. Only populated when connecting to
143-
DSE with this property available. Not queried if :attr:`~.Cluster.token_metadata_enabled` is ``False``.
144-
"""
145-
146-
dse_workload = None
147-
"""
148-
DSE workload queried from the control connection system tables. Only populated when connecting to
149-
DSE with this property available. Not queried if :attr:`~.Cluster.token_metadata_enabled` is ``False``.
150-
This is a legacy attribute that does not portray multiple workloads in a uniform fashion.
151-
See also :attr:`~.Host.dse_workloads`.
152-
"""
153-
154-
dse_workloads = None
155-
"""
156-
DSE workloads set, queried from the control connection system tables. Only populated when connecting to
157-
DSE with this property available (added in DSE 5.1).
158-
Not queried if :attr:`~.Cluster.token_metadata_enabled` is ``False``.
159-
"""
160-
161-
_datacenter = None
162-
_rack = None
163-
_reconnection_handler = None
164-
lock = None
16552
166-
_currently_handling_node_up = False
167-
168-
sharding_info = None
53+
Attributes:
54+
endpoint: The :class:`~.connection.EndPoint` to connect to the node.
55+
broadcast_address: broadcast address configured for the node, *if available*
56+
broadcast_port: broadcast port configured for the node, *if available*
57+
broadcast_rpc_address: The broadcast rpc address of the node
58+
broadcast_rpc_port: The broadcast rpc port of the node, *if available*
59+
conviction_policy: A :class:`~.ConvictionPolicy` instance for determining
60+
when this node should be marked up or down.
61+
is_up: :const:`True` if the node is considered up, :const:`False` if it is
62+
considered down, and :const:`None` if it is not known if the node is
63+
up or down.
64+
release_version: release_version as queried from the control connection system tables
65+
host_id: The unique identifier of the cassandra node
66+
dse_version: dse_version as queried from the control connection system tables
67+
dse_workload: DSE workload queried from the control connection system tables
68+
dse_workloads: DSE workloads set, queried from the control connection system tables
69+
"""
70+
__slots__ = (
71+
'endpoint', 'broadcast_address', 'broadcast_port', 'broadcast_rpc_address',
72+
'broadcast_rpc_port', 'conviction_policy', 'is_up', 'release_version',
73+
'host_id', 'dse_version', 'dse_workload', 'dse_workloads', '_datacenter',
74+
'_rack', '_reconnection_handler', 'lock', '_currently_handling_node_up',
75+
'sharding_info'
76+
)
16977

17078
def __init__(self, endpoint, conviction_policy_factory, datacenter=None, rack=None, host_id=None):
17179
if endpoint is None:
@@ -181,6 +89,20 @@ def __init__(self, endpoint, conviction_policy_factory, datacenter=None, rack=No
18189
self.set_location_info(datacenter, rack)
18290
self.lock = RLock()
18391

92+
# Initialize attributes that had default values
93+
self.broadcast_address = None
94+
self.broadcast_port = None
95+
self.broadcast_rpc_address = None
96+
self.broadcast_rpc_port = None
97+
self.is_up = None
98+
self.release_version = None
99+
self.dse_version = None
100+
self.dse_workload = None
101+
self.dse_workloads = None
102+
self._reconnection_handler = None
103+
self._currently_handling_node_up = False
104+
self.sharding_info = None
105+
184106
@property
185107
def address(self):
186108
"""
@@ -374,30 +296,29 @@ def on_exception(self, exc, next_delay):
374296

375297
class HostConnection(object):
376298
"""
377-
When using v3 of the native protocol, this is useddue to the increased in-flight capacity
299+
When using v3 of the native protocol, this is used due to the increased in-flight capacity
378300
of individual connections.
379301
"""
380-
381-
host = None
382-
host_distance = None
383-
is_shutdown = False
384-
shutdown_on_error = False
385-
386-
_session = None
387-
_lock = None
388-
_keyspace = None
389-
390-
# If the number of excess connections exceeds the number of shards times
391-
# the number below, all excess connections will be closed.
392-
max_excess_connections_per_shard_multiplier = 3
393-
394-
tablets_routing_v1 = False
302+
__slots__ = (
303+
'host', 'host_distance', 'is_shutdown', 'shutdown_on_error', '_session', '_lock',
304+
'_keyspace', 'max_excess_connections_per_shard_multiplier', 'tablets_routing_v1',
305+
'_stream_available_condition', '_is_replacing', '_connecting', '_connections',
306+
'_pending_connections', '_excess_connections', '_trash', '_shard_connections_futures',
307+
'advanced_shardaware_block_until'
308+
)
395309

396310
def __init__(self, host, host_distance, session):
397311
self.host = host
398312
self.host_distance = host_distance
313+
self.is_shutdown = False
314+
self.shutdown_on_error = False
399315
self._session = weakref.proxy(session)
400316
self._lock = Lock()
317+
self._keyspace = None
318+
# If the number of excess connections exceeds the number of shards times
319+
# the number below, all excess connections will be closed.
320+
self.max_excess_connections_per_shard_multiplier = 3
321+
self.tablets_routing_v1 = False
401322
# this is used in conjunction with the connection streams. Not using the connection lock because the connection can be replaced in the lifetime of the pool.
402323
self._stream_available_condition = Condition(Lock())
403324
self._is_replacing = False
@@ -453,7 +374,7 @@ def _get_connection_for_routing_key(self, routing_key=None, keyspace=None, table
453374
shard_id = None
454375
if not self._session.cluster.shard_aware_options.disable and self.host.sharding_info and routing_key:
455376
t = self._session.cluster.metadata.token_map.token_class.from_key(routing_key)
456-
377+
457378
shard_id = None
458379
if self.tablets_routing_v1 and table is not None:
459380
if keyspace is None:

0 commit comments

Comments
 (0)