Skip to content
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

Fix group search performance #3553

Merged
merged 5 commits into from
Jan 3, 2018
Merged

Fix group search performance #3553

merged 5 commits into from
Jan 3, 2018

Conversation

halirutan
Copy link
Collaborator

@halirutan halirutan commented Dec 20, 2017

This includes currently 2 changes:
Fixes #2852

  1. The input field for the group search is delayed now. It waits until the user has finished typing and starts the search afterward. This increases the usability and prevents lags during typing.
  2. The RecursiveTreeElement caches the current predicate so that branches of the group tree are not tested over and over again. This is an ugly solution so far but we need to test if this or something similar (but beautiful) boosts the performance considerably.

  • Change in CHANGELOG.md described
  • Tests created for changes
  • Screenshots added (for bigger UI changes)
  • Manually tested changed features in running JabRef
  • Check documentation status (Issue created for outdated help page at help.jabref.org?)
  • If you changed the localization: Did you run gradle localizationUpdate?

Copy link
Member

@tobiasdiez tobiasdiez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The delayed search is a good idea and the code related to it looks fine to me.

A few days ago I also had a look at the stupid search algorithm, which tests children again and again. While this is definitely a brute force method, I don't think it is the reason for the performance problems. In the end the test is String.contains, which runs in a few nano-seconds for our small string sizes. So you have to run it a few 10k times in order to get a noticeable delay, which is hard to reach even if the algorithm is multiplicative in the size of children. I suspect that the main problem is the use of the childrenFactory in the showNode method. It means that in addition to this brute-force algorithm we are also recreating the tree over and over again instead of just traversing it. The creation of nodes is expensive since the hit counter triggers a run over all entries. @halirutan based on your experience with the performance investigation, is my observation correct?

viewModel.filterTextProperty().bind(searchField.textProperty());
// We try to to prevent publishing changes in the searchfield directly to the search task that takes some time
// for larger group structures.
final Timer searchTask = FxTimer.create(Duration.ofMillis(400), () -> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, it makes sense to extract this code to a helper method in BindingsHelper.

// We try to to prevent publishing changes in the searchfield directly to the search task that takes some time
// for larger group structures.
final Timer searchTask = FxTimer.create(Duration.ofMillis(400), () -> {
LOGGER.info("Run Search " + searchField.getText());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think debug level is enough.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That log is really only for testing so that I could inspect when a new search was triggered and if my "reset the timer on new key" does actually work. This will be removed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the log level be changed to "debug" and the logging settings adjusted accordingly for you?

@halirutan
Copy link
Collaborator Author

@tobiasdiez

The creation of nodes is expensive since the hit counter triggers a run over all entries. @halirutan based on your experience with the performance investigation, is my observation correct?

I guess, this is what I saw this morning in the profiler. I didn't investigate further, but I was surprised that I saw constructor-hits. I thought the group-tree is static until it is changed by adding/deleting nodes but instead it seems the tree is rebuilt. I haven't worked through the whole implementation because there is a lot of stuff in it I haven't worked with before JabRef. This is another reason why I had the hope someone could join on this branch because I don't feel confident to implement a good fix for this fundamental flaw in the design.

@koppor koppor changed the title Fix group search performance (WIP!) [WIP] Fix group search performance Dec 22, 2017
@tobiasdiez tobiasdiez changed the title [WIP] Fix group search performance Fix group search performance Dec 27, 2017
@tobiasdiez tobiasdiez added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label Dec 27, 2017
@tobiasdiez
Copy link
Member

Ok, I think I found a solution which reuses the children, does not need to store the predicate but nonetheless has a good performance.

Copy link
Member

@lenhard lenhard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested this locally with our large testing library. The improvement is really impressive, great work :) I have to say that the bindings code is quite hard to get, as always, but since it seems to work I am happy with.

I think this needs a changelog entry (it's a change that users will notice) and then it can be merged.

@halirutan
Copy link
Collaborator Author

@lenhard Have you seen the comment in the issue this PR should solve?

@tobiasdiez Unfortunately the new version is not working as expected. While it still filters the groups, when a filtered group is selected, the associated entries are not updated accordingly in the main table view. This was not the case with the previous version..

@lenhard
Copy link
Member

lenhard commented Jan 3, 2018

@halirutan Sorry, I did not look at the issue again and just tested for performance, not correctness. Of course that bug should be fixed before merging.

@tobiasdiez
Copy link
Member

Bug fixed -> merge! 😃

@tobiasdiez tobiasdiez merged commit f61f641 into master Jan 3, 2018
@tobiasdiez tobiasdiez deleted the fix-GroupSearchPerformance branch January 3, 2018 19:13
@halirutan
Copy link
Collaborator Author

Great!

@Siedlerchr Siedlerchr mentioned this pull request Apr 12, 2018
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants