summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Brown <paul90brown@gmail.com>2021-12-14 10:03:11 +0000
committerGitHub <noreply@github.com>2021-12-14 16:03:11 +0600
commitbe6b5ededa5654ca43cea67927667456e32523a3 (patch)
tree24a6c70780ff1dd8707bc86f59097d97dde615f1
parentfb162f2232a81440bf9032ec8a0cbf299e73d3d5 (diff)
downloadpy-amqp-be6b5ededa5654ca43cea67927667456e32523a3.tar.gz
reduce memory usage of Connection (#377)
* reduce memory usage of Connection * allow ValueError on _used_channel_ids.remove
-rw-r--r--amqp/channel.py6
-rw-r--r--amqp/connection.py22
-rw-r--r--t/unit/test_connection.py6
3 files changed, 22 insertions, 12 deletions
diff --git a/amqp/channel.py b/amqp/channel.py
index b271820..77cfaab 100644
--- a/amqp/channel.py
+++ b/amqp/channel.py
@@ -150,7 +150,11 @@ class Channel(AbstractChannel):
connection, self.connection = self.connection, None
if connection:
connection.channels.pop(channel_id, None)
- connection._avail_channel_ids.append(channel_id)
+ try:
+ connection._used_channel_ids.remove(channel_id)
+ except ValueError:
+ # channel id already removed
+ pass
self.callbacks.clear()
self.cancel_callbacks.clear()
self.events.clear()
diff --git a/amqp/connection.py b/amqp/connection.py
index 9917ec7..3e9097f 100644
--- a/amqp/connection.py
+++ b/amqp/connection.py
@@ -267,7 +267,7 @@ class Connection(AbstractChannel):
self.on_unblocked = on_unblocked
self.on_open = ensure_promise(on_open)
- self._avail_channel_ids = array('H', range(self.channel_max, 0, -1))
+ self._used_channel_ids = array('H')
# Properties set in the Start method
self.version_major = 0
@@ -482,18 +482,20 @@ class Connection(AbstractChannel):
self._transport = self.connection = self.channels = None
def _get_free_channel_id(self):
- try:
- return self._avail_channel_ids.pop()
- except IndexError:
- raise ResourceError(
- 'No free channel ids, current={}, channel_max={}'.format(
- len(self.channels), self.channel_max), spec.Channel.Open)
+ for channel_id in range(1, self.channel_max):
+ if channel_id not in self._used_channel_ids:
+ return channel_id
+
+ raise ResourceError(
+ 'No free channel ids, current={}, channel_max={}'.format(
+ len(self.channels), self.channel_max), spec.Channel.Open)
def _claim_channel_id(self, channel_id):
- try:
- return self._avail_channel_ids.remove(channel_id)
- except ValueError:
+ if channel_id in self._used_channel_ids:
raise ConnectionError(f'Channel {channel_id!r} already open')
+ else:
+ self._used_channel_ids.append(channel_id)
+ return channel_id
def channel(self, channel_id=None, callback=None):
"""Create new channel.
diff --git a/t/unit/test_connection.py b/t/unit/test_connection.py
index a2997e6..03f0258 100644
--- a/t/unit/test_connection.py
+++ b/t/unit/test_connection.py
@@ -1,6 +1,7 @@
import re
import socket
import warnings
+from array import array
from unittest.mock import Mock, call, patch
import pytest
@@ -347,8 +348,11 @@ class test_Connection:
self.conn.collect()
self.conn.collect()
+ def test_get_free_channel_id(self):
+ assert self.conn._get_free_channel_id() == 1
+
def test_get_free_channel_id__raises_IndexError(self):
- self.conn._avail_channel_ids = []
+ self.conn._used_channel_ids = array('H', range(1, self.conn.channel_max))
with pytest.raises(ResourceError):
self.conn._get_free_channel_id()