Module: deluge
Branch: chunked-sessionproxy-and-gtkui-speedups
Commit: cf79402ce7f3ea67d8f9c7d4bca342cc5211a6d4

Author: Pedro Algarvio <pe...@algarvio.me>
Date:   Mon May 16 05:57:36 2011 +0100

GTK UI loading speedup.

Limit the amount of data queried to the daemon to the torrents actually visible 
in the torrentview, those that are not visible, won't be queried until scrolled 
into a visible position. This speedup together with the chunked session proxy, 
makes the initial data requested from the daemon from ~35MB to about ~10MB for 
my > 800 torrents. And the time loading it has also dramatically dropped.

---

 deluge/ui/gtkui/torrentview.py |   70 +++++++++++++++++++++++++++++++++------
 deluge/ui/sessionproxy.py      |    4 +-
 2 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py
index 4fc5ce3..8a4db16 100644
--- a/deluge/ui/gtkui/torrentview.py
+++ b/deluge/ui/gtkui/torrentview.py
@@ -254,8 +254,8 @@ class TorrentView(listview.ListView, component.Component):
                              tooltip=_("Torrent is shared between other Deluge 
"
                                        "users or not."))
 
-        # Set filter to None for now
-        self.filter = None
+        # Set filter and prev_filter to None for now
+        self.filter = self.prev_filter = None
 
         ### Connect Signals ###
         # Connect to the 'button-press-event' to know when to bring up the
@@ -360,15 +360,33 @@ class TorrentView(listview.ListView, component.Component):
 
         # Request the statuses for all these torrent_ids, this is async so we
         # will deal with the return in a signal callback.
+        if self.prev_filter != self.filter:
+            self.prev_filter = self.filter
+            component.get("SessionProxy").get_torrents_status(
+                self.filter, status_keys
+            ).addCallback(self._on_get_torrents_status, diff=False)
+            return
+
+        # Grab current filter
+        current_filter = self.filter
+        # Get the current ids from the filter if any
+        torrent_ids = list(current_filter.get('id', []))
+        # Add the torrent ids from the visible rows in the torrents treeview
+        torrent_ids.extend(
+            self.get_visible_torrents(only_seen_in_treeview=True)
+        )
+        current_filter['id'] = list(set(torrent_ids))
+        # Get the status updates for the above torrent ids
         component.get("SessionProxy").get_torrents_status(
-            self.filter, status_keys).addCallback(self._on_get_torrents_status)
+            current_filter, status_keys
+        ).addCallback(self._on_get_torrents_status, diff=True)
 
     def update(self):
         if self.got_state:
             # Send a status request
             gobject.idle_add(self.send_status_request)
 
-    def update_view(self, columns=None):
+    def update_view(self, columns=None, from_diff=False):
         """Update the view.  If columns is not None, it will attempt to only
         update those columns selected.
         """
@@ -379,11 +397,13 @@ class TorrentView(listview.ListView, component.Component):
         for row in self.liststore:
             torrent_id = row[self.columns["torrent_id"].column_indices[0]]
 
-            if not torrent_id in status.keys():
+            if torrent_id not in status:
                 row[filter_column] = False
             else:
                 row[filter_column] = True
-                if torrent_id in self.prev_status and status[torrent_id] == 
self.prev_status[torrent_id]:
+                if torrent_id in self.prev_status and \
+                    status[torrent_id] == self.prev_status[torrent_id] and \
+                                                                not from_diff:
                     # The status dict is the same, so do not update
                     continue
 
@@ -404,12 +424,32 @@ class TorrentView(listview.ListView, component.Component):
                                           row_value, e)
 
         component.get("MenuBar").update_menu()
+        if not from_diff:
+            self.prev_status = status
 
-        self.prev_status = status
+    def _on_get_torrents_status(self, status, diff=False):
+        """
+        Callback function for get_torrents_status().  'status' should be a
+        dictionary of {torrent_id: {key, value}}.
+        """
+        if diff:
+            update_required = False
+            self.status.update(status)
+            for torrent_id in status.iterkeys():
+                if torrent_id not in self.prev_status:
+                    update_required = True
+                elif self.status[torrent_id] != self.prev_status[torrent_id]:
+                    update_required = True
+            self.prev_status = self.status.copy()   # A copy is required for
+                                                    # diff's to actually be
+                                                    # different
+
+            if update_required:
+                def update_with_diff():
+                    self.update_view(from_diff=True)
+                gobject.idle_add(update_with_diff)
+            return
 
-    def _on_get_torrents_status(self, status):
-        """Callback function for get_torrents_status().  'status' should be a
-        dictionary of {torrent_id: {key, value}}."""
         self.status = status
         if self.status == self.prev_status and self.prev_status:
             # We do not bother updating since the status hasn't changed
@@ -498,7 +538,15 @@ class TorrentView(listview.ListView, component.Component):
         except:
             return {}
 
-    def get_visible_torrents(self):
+    def get_visible_torrents(self, only_seen_in_treeview=False):
+        if only_seen_in_treeview:
+            first_seen, last_seen = self.treeview.get_visible_range()
+            model = self.treeview.get_model()
+            return [
+                model[n][self.get_column_index('torrent_id')[0]] for n in
+                range(first_seen[0], last_seen[0]+1)
+            ]
+
         return self.status.keys()
 
     ### Callbacks ###
diff --git a/deluge/ui/sessionproxy.py b/deluge/ui/sessionproxy.py
index 3041630..34ea5fe 100644
--- a/deluge/ui/sessionproxy.py
+++ b/deluge/ui/sessionproxy.py
@@ -79,7 +79,7 @@ class SessionProxy(component.Component):
 
     def start(self):
         def on_get_session_state(torrent_ids):
-            for torrent_ids_chunk in self.__get_list_in_chunks(torrent_ids, 2):
+            for torrent_ids_chunk in self.__get_list_in_chunks(torrent_ids):
                 torrent_ids_chunk = list(torrent_ids_chunk)
                 print 'querying status for chunk', torrent_ids_chunk
                 d = client.core.get_torrents_status(
@@ -292,7 +292,7 @@ class SessionProxy(component.Component):
                 self.cache_times.setdefault(key, {}).update({k:t})
         return status
 
-    def __get_list_in_chunks(self, list_to_chunk, chunk_size=20):
+    def __get_list_in_chunks(self, list_to_chunk, chunk_size=30):
         """
         Yield successive n-sized chunks from list_to_chunk.
         """

-- 
You received this message because you are subscribed to the Google Groups 
"deluge-commit" group.
To post to this group, send email to deluge-commit@googlegroups.com.
To unsubscribe from this group, send email to 
deluge-commit+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/deluge-commit?hl=en.

Reply via email to