commit 52216d6977f44ffa3fa7e406e6bc4a90ec90e86f Author: Damian Johnson atagar@torproject.org Date: Sat Oct 21 10:37:15 2017 -0700
Don't use lru_cache for connection entry attributes
Interesting. The lru_cache for from_connection works, but the ones for the methods don't. This causes truly horrid performance when you have a ton of connections since it's recalculating the type and lines with every redraw. --- nyx/panel/connection.py | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-)
diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py index 8e5873d..9b3279c 100644 --- a/nyx/panel/connection.py +++ b/nyx/panel/connection.py @@ -91,6 +91,11 @@ class Entry(object): def from_circuit(circuit): return CircuitEntry(circuit)
+ def __init__(self): + self._lines = None + self._type = None + self._is_private_val = None + def get_lines(self): """ Provides individual lines of connection information. @@ -98,7 +103,10 @@ class Entry(object): :returns: **list** of **ConnectionLine** concerning this entry """
- raise NotImplementedError('should be implemented by subclasses') + if self._lines is None: + self._lines = self._get_lines() + + return self._lines
def get_type(self): """ @@ -107,7 +115,10 @@ class Entry(object): :returns: **Category** for the connection's type """
- raise NotImplementedError('should be implemented by subclasses') + if self._type is None: + self._type = self._get_type() + + return self._type
def is_private(self): """ @@ -118,7 +129,10 @@ class Entry(object): :returns: **bool** indicating if connection information is sensive or not """
- raise NotImplementedError('should be implemented by subclasses') + if self._is_private_val is None: + self._is_private_val = self._is_private() + + return self._is_private_val
def sort_value(self, attr): """ @@ -153,13 +167,22 @@ class Entry(object): else: return ''
+ def _get_lines(self): + raise NotImplementedError('should be implemented by subclasses') + + def _get_type(self): + raise NotImplementedError('should be implemented by subclasses') + + def _is_private(self): + raise NotImplementedError('should be implemented by subclasses') +
class ConnectionEntry(Entry): def __init__(self, connection): + super(ConnectionEntry, self).__init__() self._connection = connection
- @lru_cache() - def get_lines(self): + def _get_lines(self): fingerprint, nickname, locale = None, None, None
if self.get_type() in (Category.OUTBOUND, Category.CIRCUIT, Category.DIRECTORY, Category.EXIT): @@ -171,8 +194,7 @@ class ConnectionEntry(Entry):
return [Line(self, LineType.CONNECTION, self._connection, None, fingerprint, nickname, locale)]
- @lru_cache() - def get_type(self): + def _get_type(self): controller = tor_controller()
if self._connection.local_port in controller.get_ports(Listener.OR, []): @@ -201,8 +223,7 @@ class ConnectionEntry(Entry):
return Category.OUTBOUND
- @lru_cache() - def is_private(self): + def _is_private(self): if not CONFIG['show_addresses']: return True
@@ -222,10 +243,10 @@ class ConnectionEntry(Entry):
class CircuitEntry(Entry): def __init__(self, circuit): + super(CircuitEntry, self).__init__() self._circuit = circuit
- @lru_cache() - def get_lines(self): + def _get_lines(self): def line(fingerprint, line_type): address, port, nickname, locale = '0.0.0.0', 0, None, None consensus_tracker = nyx.tracker.get_consensus_tracker() @@ -241,10 +262,10 @@ class CircuitEntry(Entry): header_line = line(self._circuit.path[-1][0] if self._circuit.status == 'BUILT' else None, LineType.CIRCUIT_HEADER) return [header_line] + [line(fp, LineType.CIRCUIT) for fp, _ in self._circuit.path]
- def get_type(self): + def _get_type(self): return Category.CIRCUIT
- def is_private(self): + def _is_private(self): return False