From 52cd8f4b226f22f78eae997212073011716cdd08 Mon Sep 17 00:00:00 2001
From: mathieui <mathieui@mathieui.net>
Date: Mon, 22 Aug 2016 01:29:07 +0200
Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20trigger=20presence=20events=20o?=
 =?UTF-8?q?n=20MUC=20presence?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Specifically, previously, each MUC would be added as a roster item, and
then each join presence would be counted as a resource of that item,
triggering 1 to 5 events and more backend logic in slixmpp.

As a result, joining big rooms is tremendously slow, (JID() calls,
event() calls, __getitem__ calls for nothing), and takes RAM (a quick
tracemalloc tells me around 1 MiB for 3500 participants, i.e. 2 big IRC
rooms). Those resources may not necessarily be cleaned properly, leading
to memory leaks on long-term usage.

This is a micro-optimization that adds an attribute to roster items so
that MUC room events can be ignored safely while not affecting common
roster usage.
---
 slixmpp/basexmpp.py         | 3 +++
 slixmpp/plugins/xep_0045.py | 1 +
 slixmpp/roster/single.py    | 1 +
 3 files changed, 5 insertions(+)

diff --git a/slixmpp/basexmpp.py b/slixmpp/basexmpp.py
index 3cc299b2..e5f5f0b1 100644
--- a/slixmpp/basexmpp.py
+++ b/slixmpp/basexmpp.py
@@ -752,6 +752,9 @@ class BaseXMPP(XMLStream):
 
         Update the roster with presence information.
         """
+        if self.roster[presence['from']].ignore_updates:
+            return
+
         if not self.is_component and not presence['to'].bare:
             presence['to'] = self.boundjid
 
diff --git a/slixmpp/plugins/xep_0045.py b/slixmpp/plugins/xep_0045.py
index f6f48891..8ab51784 100644
--- a/slixmpp/plugins/xep_0045.py
+++ b/slixmpp/plugins/xep_0045.py
@@ -160,6 +160,7 @@ class XEP_0045(BasePlugin):
         got_online = False
         if pr['muc']['room'] not in self.rooms.keys():
             return
+        self.xmpp.roster[pr['from']].ignore_updates = True
         entry = pr['muc'].get_stanza_values()
         entry['show'] = pr['show']
         entry['status'] = pr['status']
diff --git a/slixmpp/roster/single.py b/slixmpp/roster/single.py
index 62fbca41..3961cddf 100644
--- a/slixmpp/roster/single.py
+++ b/slixmpp/roster/single.py
@@ -56,6 +56,7 @@ class RosterNode(object):
         self.xmpp = xmpp
         self.jid = jid
         self.db = db
+        self.ignore_updates = False
         self.auto_authorize = True
         self.auto_subscribe = True
         self.last_status = None