Initial GTK UI Speedups.

The speedups work is being separated into 2 different phases and possibly branches. The idea is to have this minimal speedup merged into master as soon as possible since it's pretty simple. Reduces initial data transfer to about 10% of what was previously being transfered when client connected.
The second phase is regarding row updates, ie, reduce them to what's actually being seen. This part is way more tricky.
This commit is contained in:
Pedro Algarvio 2011-06-09 13:41:10 +01:00
parent 5112ed48d1
commit ce9b540b97
2 changed files with 35 additions and 19 deletions

View File

@ -88,7 +88,7 @@ def cell_data_statusicon(column, cell, model, row, data):
"""Display text with an icon""" """Display text with an icon"""
try: try:
icon = ICON_STATE[model.get_value(row, data)] icon = ICON_STATE[model.get_value(row, data)]
#Supress Warning: g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed #Suppress Warning: g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
if cell.get_property("pixbuf") != icon: if cell.get_property("pixbuf") != icon:
@ -111,7 +111,7 @@ def cell_data_trackericon(column, cell, model, row, data):
else: else:
icon = create_blank_icon() icon = create_blank_icon()
#Supress Warning: g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed #Suppress Warning: g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
if cell.get_property("pixbuf") != icon: if cell.get_property("pixbuf") != icon:
@ -411,8 +411,7 @@ class TorrentView(listview.ListView, component.Component):
self.treeview.connect("key-release-event", self.on_key_press_event) self.treeview.connect("key-release-event", self.on_key_press_event)
# Connect to the 'changed' event of TreeViewSelection to get selection # Connect to the 'changed' event of TreeViewSelection to get selection
# changes. # changes.
self.treeview.get_selection().connect("changed", self.treeview.get_selection().connect("changed", self.on_selection_changed)
self.on_selection_changed)
self.treeview.connect("drag-drop", self.on_drag_drop) self.treeview.connect("drag-drop", self.on_drag_drop)
self.treeview.connect("key-press-event", self.on_key_press_event) self.treeview.connect("key-press-event", self.on_key_press_event)
@ -431,7 +430,15 @@ class TorrentView(listview.ListView, component.Component):
"""Start the torrentview""" """Start the torrentview"""
# We need to get the core session state to know which torrents are in # We need to get the core session state to know which torrents are in
# the session so we can add them to our list. # the session so we can add them to our list.
component.get("SessionProxy").get_torrents_status({}, []).addCallback(self._on_session_state) # Only get the status fields required for the visible columns
status_fields = []
for listview_column in self.columns.values():
if listview_column.column.get_visible():
if not listview_column.status_field:
continue
status_fields.extend(listview_column.status_field)
component.get("SessionProxy").get_torrents_status(
{}, status_fields).addCallback(self._on_session_state)
def _on_session_state(self, state): def _on_session_state(self, state):
self.treeview.freeze_child_notify() self.treeview.freeze_child_notify()

View File

@ -58,7 +58,7 @@ class SessionProxy(component.Component):
component.Component.__init__(self, "SessionProxy", interval=5) component.Component.__init__(self, "SessionProxy", interval=5)
# Set the cache time in seconds # Set the cache time in seconds
# This is how long data will be valid before refetching from the core # This is how long data will be valid before re-fetching from the core
self.cache_time = 1.5 self.cache_time = 1.5
# Hold the torrents' status.. {torrent_id: [time, {status_dict}], ...} # Hold the torrents' status.. {torrent_id: [time, {status_dict}], ...}
@ -72,16 +72,25 @@ class SessionProxy(component.Component):
client.register_event_handler("TorrentAddedEvent", self.on_torrent_added) client.register_event_handler("TorrentAddedEvent", self.on_torrent_added)
def start(self): def start(self):
def on_torrent_status(status): def on_get_session_state(torrent_ids):
# Save the time we got the torrent status for torrent_id in torrent_ids:
t = time.time() # Let's at least store the torrent ids with empty statuses
for key, value in status.iteritems(): # so that upcoming queries or status updates don't throw errors.
self.torrents[key] = [t, value] self.torrents.setdefault(torrent_id, [time.time(), {}])
self.cache_times[key] = {} self.cache_times.setdefault(torrent_id, {})
for ikey in value.iterkeys(): # These initial keys are the ones used for the visible columns(by
self.cache_times[key][ikey] = t # default) on the GTK UI torrent view. If either the console-ui
# or the web-ui needs additional keys, add them here;
return client.core.get_torrents_status({}, [], True).addCallback(on_torrent_status) # There's NO need to fetch every bit of status information from
# core if it's not going to be used. Additional status fields
# will be queried later, for example, when viewing the status tab
# of a torrent.
inital_keys = [
'queue', 'state', 'name', 'total_wanted', 'progress', 'state',
'download_payload_rate', 'upload_payload_rate', 'eta'
]
self.get_torrents_status({'id': torrent_ids}, inital_keys)
return client.core.get_session_state().addCallback(on_get_session_state)
def stop(self): def stop(self):
client.deregister_event_handler("TorrentStateChangedEvent", self.on_torrent_state_changed) client.deregister_event_handler("TorrentStateChangedEvent", self.on_torrent_state_changed)
@ -134,7 +143,7 @@ class SessionProxy(component.Component):
keys = self.torrents[torrent_id][1].keys() keys = self.torrents[torrent_id][1].keys()
for key in keys: for key in keys:
if time.time() - self.cache_times[torrent_id][key] > self.cache_time: if time.time() - self.cache_times[torrent_id].get(key, 0.0) > self.cache_time:
keys_to_get.append(key) keys_to_get.append(key)
if not keys_to_get: if not keys_to_get:
@ -243,8 +252,8 @@ class SessionProxy(component.Component):
def on_torrent_state_changed(self, torrent_id, state): def on_torrent_state_changed(self, torrent_id, state):
if torrent_id in self.torrents: if torrent_id in self.torrents:
self.torrents[torrent_id][1]["state"] = state self.torrents[torrent_id][1].setdefault("state", state)
self.cache_times[torrent_id]["state"] = time.time() self.cache_times.setdefault(torrent_id, {}).update(state=time.time())
def on_torrent_added(self, torrent_id, from_state): def on_torrent_added(self, torrent_id, from_state):
self.torrents[torrent_id] = [time.time() - self.cache_time - 1, {}] self.torrents[torrent_id] = [time.time() - self.cache_time - 1, {}]