-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optim/no refresh on hidden pane #530
Optim/no refresh on hidden pane #530
Conversation
GTG/gtk/browser/main_window.py
Outdated
@@ -1285,9 +1285,12 @@ def on_dismiss_task(self, widget=None): | |||
def apply_filter_on_panes(self, filter_name, refresh=True, parameters=None): | |||
""" Apply filters for every pane: active tasks, closed tasks """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this docstring a lie now? (and the one in unapply_filter_on_panes too)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well yeah, I'll adjust the docstring, but indeed, by default with the force_refresh=False
all pane won't be applied filters upon.
GTG/gtk/browser/main_window.py
Outdated
for pane in self.vtree_panes: | ||
vtree = self.req.get_tasks_tree(name=pane, refresh=False) | ||
vtree.apply_filter(filter_name, refresh=refresh, parameters=parameters) | ||
vtree.apply_filter(filter_name, | ||
refresh=current_pane == pane, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given how important this seems to be to maintain somewhat decent performance, I think it might be good to add some comment(s) in the code to explain the gotchas / warn people to only refresh the currently shown pane to cut down the performance impact massively, avoiding potential future naïve code mistakes?
Wow so... if I understand correctly, you're saying the app was asking liblarch to refresh "All tasks" + "Actionable" + "Closed" everytime you click a tag in the sidebar? Interesting finding, that explains why toggling the Workview in 0.3.x was slow but it isn't in 0.4+; Silly question though: what happens now when you switch between panes, it will have to refilter the view, which means switching between panes will no longer be instantaneous? We might be bringing back an old problem I guess, unless there's a way for the filtering to happen first in the current view, and then "asynchronously, in the background" do it for the 2 other views as well... |
From what I've seen while trying to check the performance, yes. I thought that was intentional ("switching tabs is fast now"), and also thought of doing something similar to this PR (but with your async suggestion), but I ultimately wanted to rather fix the "underlying" issue first (current unsuccessfully). |
Yup.
Same here, hence the PR and the open question. Although, in the call to liblarch, the
I didn't see issues while testing around but that's mainly what I was worried about indeed. |
I tried this out with your liblarch branch, and I saw a 2x improvement with various operations when running the "bryce" sample data set ( Git master
With your optimizations branch
Note: performance gains on the "bryce" dataset are 2x rather than the potential 3x, because that dataset doesn't have more than 1 closed tasks in it, so from a data perspective it's almost as if it only had two panes in practice. |
Ok so this time it should be good I've dropped the previous logic of unapplying one by one every filter. We now reset the whole bunch since there is no performance gain in not doing so (no |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, but I want to test it for myself.
GTG/gtk/browser/main_window.py
Outdated
except InvalidQuery: | ||
log.debug("Invalid query %r", query) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No exception details? (e
in the old code)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, got dropped in the heat of the rewrite, i'll add it back again.
GTG/gtk/browser/main_window.py
Outdated
for filter_ in filters: | ||
is_last = filter_ == filters[-1] | ||
if filter_ == SEARCH_TAG: | ||
self._try_filter_by_query(search, refresh=is_last) | ||
else: | ||
vtree.apply_filter(filter_, refresh=is_last) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why awkwardly filter_
and not just filter
(no _
)?
I also don't like the is_last
thingy, but I guess you used it to let liblarch decide whenever it really should refilter (https://github.com/getting-things-gnome/liblarch/blob/8c90053b9a3593706cdf082353b4146ff79a8f55/liblarch/filteredtree.py#L611-L631). Maybe add a comment and/or something in the commit message about this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, filter
is a python reserved keyword, and it's not recommended as a rule to override reserved names, as for filter_
especially, it's the PEP8 recommended behavior.. But I can find a synonym.
I'm not a big fan of the is_last
thingy either, and I'd rather prefer explicitly call for refilter()
. Better yet, a new liblarch
method allowing to apply multiple filters at once. But since I didn't want to alter too much of the liblarch
API and still wanted to limit calls I thought of this. But yeat, a comment is indeed needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, filter is a python reserved keyword, and it's not recommended as a rule to override reserved names, as for filter_ especially, it's the PEP8 recommended behavior.. But I can find a synonym.
But filter
is a built-in function (or class as the python3 interpreter says), not a reserved keyword from what I can see. I can redefine it at least in the python REPL, so I'm sure it isn't a keyword.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes indeed, keyword and not built-in function, sorry about the mix up.
But to me it's still overriding a declared value. From experience it may lead to some complicated debugging. So yeah I usually follow the PEP8 recommendation about keywords on that too.
But since it's important I'll use the name from the ViewTree.apply_filter
function.
GTG/gtk/browser/main_window.py
Outdated
# only reseting filters if applieds filters are different from current | ||
# ones, leaving a chance for liblarch to make the good call on wether | ||
# to refilter or not |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that important but somewhat annoys me:
reseting → resetting
applieds → the applied
wether → whether
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments are important :) Fixed !
GTG/gtk/browser/main_window.py
Outdated
# Browsing and applying filters. For performance optimization, only | ||
# allowing liblarch to trigger a refresh on last item. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't really say why you couldn't just do refilter
. Maybe append "This way, liblarch can prevent refreshing in certain situations rather than refilter all the time. (also see resetting above)"
or "... last item, possibly preventing a refilter (see above when resetting)"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I'll edit that. But truth is, I can't call on ViewTree.refilter()
because there is no such method. ViewTree
doesn't proxy that method to FilteredTree
and I don't know why at all. This is what I meant in the second part of that comment.
426687b
to
d98b56c
Compare
Instead of refreshing all three trees (`active`, `workview` and `closed`) on startup, search and every tag selection, only refresh the one currently displayed.
d98b56c
to
76b507c
Compare
Looks good to me, switching seems to work as intended. However, it takes longer to start, around 50s instead of 37s on current master (when the "Open" view is selected), and seems to be rather consistent. On top of longer startup time, it'll refresh when switching views/tabs directly after startup, so it looks like it force refreshes or something. |
Hum I'm not sure I get how you obtain those figures. Is there a defined way to measure these ? Especially the startup time, all I could come up with was to measure the time for Note : for the patch to actually improve perf you have to have On
|
…n_select_tag is called right after
After the previous comment from @Neui I got curious about startup time (wasn't really the subject of the PR at first), and I saw that @@ -409,8 +406,6 @@ class MainWindow(Gtk.ApplicationWindow):
self.vtree_panes['closed'].connect('key-press-event', clsd_tsk_key_prs)
self.vtree_panes['closed'].connect('cursor-changed', self.on_cursor_changed)
- self.closedtree.apply_filter(self.get_selected_tags()[0], refresh=True)
-
b_signals = BackendSignals()
b_signals.connect(b_signals.BACKEND_FAILED, self.on_backend_failed)
b_signals.connect(b_signals.BACKEND_STATE_TOGGLED, self.remove_backend_infobar) salvaging another second on my test (9s on master, 6s previously, roughly 5s here). And since the method |
Sorry for not being more specific. In this case I just ran
Makes sense, I forgot to apply it. I'll try it with that patch later/this evening (GMT).
I'd be ok to put that into another PR. |
but only on the current one, reseting others filters
Well I missed it, so I did it now. GTG refreshes when waking up/new day occurs. I took an bit different route and enabled the developer console (in the extensions), opened it (from the menu top right), One thing I noticed was that when switching to the "closed" tab (that is big since I disabled task cleanup), it takes around 18s (from clicking until responding/changing the view visually). Since master already "filters" the tab, it seems a bit odd to me that this PR takes a bit longer (12s startup + 18s switch = 30s). Not too bad though. I'll review the new code changes soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me and works.
I've tested this again and the issue I had seen before seems gone. Performance is a net improvement (see my updated benchmark results in #402 (comment) if you're curious), I'm excited and looking forward to further optimizations you may come up with! So I will now merge this as-is, and hope @diegogangl won't encounter too many (if any) conflicts with his big WIP branches ;) |
Depends on getting-things-gnome/liblarch#22 won't
self.refilter
on non-displayed tree, cutting by 3 the display time when selecting a tag.Context
When selecting a tag with around 150 tasks, the process time gets up to 1s5. Mainly I found that a lot of callbacks are called in
liblarch
but as I don't fully understand that library, I didn't do much on that side.I did witness though, that for all three panes the
apply_filter
function, each times, calls onrefilter
. That last one browse the tree in lots of ways.Although, and that's where I have doubts, all three
refilter
aren't necessary, and it's only needed for the displayed pane.The fix is to only trigger the refresh for the active pane.