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

DYN-8045: Fix hanged node search when the user types faster than search #15733

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

chubakueno
Copy link
Contributor

@chubakueno chubakueno commented Dec 19, 2024

Purpose

Currently the node search hangs when the user types faster than the time it takes Lucene to provide results because it is searching in the main UI thread. This PR provides a debouncing algorithm and performs searches sequentially outside of the main UI thread for a smoother search experience. Currently there is no support for cancelling previous search tasks in lucenenet so this is a fix around that limitation

Before fix:
2024-12-19 00-33-21

After fix:
2024-12-19 00-35-00

Declarations

Check these if you believe they are true

  • The codebase is in a better state after this PR
  • Is documented according to the standards
  • The level of testing this PR includes is appropriate
  • User facing strings, if any, are extracted into *.resx files
  • All tests pass using the self-service CI.
  • Snapshot of UI changes, if any.
  • Changes to the API follow Semantic Versioning and are documented in the API Changes document.
  • This PR modifies some build requirements and the readme is updated
  • This PR contains no files larger than 50 MB

Release Notes

Prevent node search from hanging during fast typing.

Reviewers

@RobertGlobant20
@QilongTang
@sm6srw

FYIs

@avidit

@chubakueno chubakueno changed the title Fix hanged node search when the user types faster than serach Fix hanged node search when the user types faster than search Dec 19, 2024
@chubakueno chubakueno changed the title Fix hanged node search when the user types faster than search DYN-8045: Fix hanged node search when the user types faster than search Dec 19, 2024
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

See the ticket for this pull request: https://jira.autodesk.com/browse/DYN-8045

Copy link
Contributor

@sm6srw sm6srw left a comment

Choose a reason for hiding this comment

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

LGTM. But I would like to know what @QilongTang thinks about it.

@sm6srw sm6srw requested a review from QilongTang December 19, 2024 20:35
@chubakueno
Copy link
Contributor Author

Failed on test DocsAreLoadedFromHostPathBeforeCorePath, but that test never goes through Search or SearchAndUpdateResults, so failure is unrelated.

@mjkkirschner
Copy link
Member

@QilongTang this seems to overlap with #15726 am I getting that right? How do you want to proceed with these two prs?

@mjkkirschner
Copy link
Member

@QilongTang this seems to overlap with #15726 am I getting that right? How do you want to proceed with these two prs?

@QilongTang after taking a look at this I think I prefer the approach in #15726 - it's behind a feature flag, has tests, avoids locks, and I think is more idiomatic.

I don't know if it solves the issue of the hanging search though - @bendikberg can you verify if it fixes this issue?

@chubakueno
Copy link
Contributor Author

chubakueno commented Dec 20, 2024

Improvements in last commit:

  • Implemented performance improviments in node library search (side panel)
  • Fix library search in case the user uses a combination of two or more modifiers (alt+shift,ctrl+shift,etc)
  • Fix library search when user types an empty space
  • In context menu is now immediately confirmable on enter. This will help eliminate artificial hardcoded delays in UI Automation testing.

@QilongTang this seems to overlap with #15726 am I getting that right? How do you want to proceed with these two prs?

@QilongTang after taking a look at this I think I prefer the approach in #15726 - it's behind a feature flag, has tests, avoids locks, and I think is more idiomatic.

I don't know if it solves the issue of the hanging search though - @bendikberg can you verify if it fixes this issue?

Copy link

github-actions bot commented Dec 20, 2024

UI Smoke Tests

Test: success. 11 passed, 0 failed.
TestComplete Test Result
Workflow Run: UI Smoke Tests
Check: UI Smoke Tests

@chubakueno
Copy link
Contributor Author

Added unit tests for debouncing.

@bendikberg
Copy link

bendikberg commented Dec 20, 2024

@mjkkirschner
The solution I proposed debounces the keypresses so that the search is triggered at a later time, but the searches still run on the UI thread. I have still experienced it blocking the UI while it waits for a search to finish, though not for multiple seconds like the current implementation.

Since @chubakueno 's solution doesn't rely on timeouts and the searches run asynchronously it probably feels even more responsive than mine, which I think is great.

Maybe there is a way to combine the approaches?


namespace Dynamo.Wpf.Utilities
{
public static class JobDebouncer
Copy link
Contributor

Choose a reason for hiding this comment

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

  • can you add some more description to this utility, as to when this should be used? I understand we all know that answer already, but would like to document so everyone and new developers on team also learn to use it.

  • There are also a few other instances using deboucer in our code, can you unify the usage?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a class summary description. The PR as currently is already unifies both library (sidebar) and incontext node search into using the debouncer, but I can't find more instances of a debouncer being used in c# code (there are some in html/js webview code though).

Copy link
Contributor

@QilongTang QilongTang left a comment

Choose a reason for hiding this comment

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

Overall, looks solid. The things worries me most are that we have a couple instances in Dynamo leveraging debouncer differently in Dynamo (mostly around search), it would be good to unify the usage. Off course, the change in this PR to have a utility class for deboucer is a great start!

@QilongTang
Copy link
Contributor

@QilongTang this seems to overlap with #15726 am I getting that right? How do you want to proceed with these two prs?

Yeah I noticed, do we want to test both in build and pick or combine the approach somehow? I do like the fact the debouncer becomes utility in this PR


if (luceneSearchUtility != null)
if (luceneSearchUtility == null) return null;
lock (luceneSearchUtility)
Copy link
Member

@mjkkirschner mjkkirschner Dec 20, 2024

Choose a reason for hiding this comment

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

is this still required in addition to the search operations taking a lock out on the queue token?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The lock is in case Search is used in parallel. As of now that could only happen if the user searches in the library and workspace simultaneously, since both have independent serial queues. We could mandate a unified search queue (for library, inCanvasSearch, and in the future) or have this lock to allow several search queues in parallel.

@@ -0,0 +1,80 @@
//https://github.com/gentlee/SerialQueue/blob/master/SerialQueue/SerialQueue.cs
Copy link
Member

Choose a reason for hiding this comment

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

@QilongTang do we need to update the about box for this?

@mjkkirschner
Copy link
Member

@QilongTang this seems to overlap with #15726 am I getting that right? How do you want to proceed with these two prs?

Yeah I noticed, do we want to test both in build and pick or combine the approach somehow? I do like the fact the debouncer becomes utility in this PR

yeah, I'm not sure.

I still think that anything that introduces locks, or await etc should be behind a feature flag because Dynamo is not thread safe makes all sorts of assumptions, and runs in different threading contexts (Revit, sandbox etc) and I would want a way to turn this (or the other PR) off in released code. That might be overkill but it's not that hard to do in the other PR, it might be harder here.

A single denouncer utility is useful, I definitely appreciate having less ways of doing things, not more.

The serial queue code seems small enough to take on, but I'd be curious about built in types that could do the same.

@chubakueno
Copy link
Contributor Author

@QilongTang this seems to overlap with #15726 am I getting that right? How do you want to proceed with these two prs?

Yeah I noticed, do we want to test both in build and pick or combine the approach somehow? I do like the fact the debouncer becomes utility in this PR

yeah, I'm not sure.

I still think that anything that introduces locks, or await etc should be behind a feature flag because Dynamo is not thread safe makes all sorts of assumptions, and runs in different threading contexts (Revit, sandbox etc) and I would want a way to turn this (or the other PR) off in released code. That might be overkill but it's not that hard to do in the other PR, it might be harder here.

A single denouncer utility is useful, I definitely appreciate having less ways of doing things, not more.

The serial queue code seems small enough to take on, but I'd be curious about built in types that could do the same.

Closest built in type that i have evaluated is ActionBlock in System.Threading.Tasks.Dataflow, but it needs an standing thread to Post() jobs to and overall didn't find it a good fit, though I'm open to other options.

@RobertGlobant20
Copy link
Contributor

@mjkkirschner The solution I proposed debounces the keypresses so that the search is triggered at a later time, but the searches still run on the UI thread. I have still experienced it blocking the UI while it waits for a search to finish, though not for multiple seconds like the current implementation.

Since @chubakueno 's solution doesn't rely on timeouts and the searches run asynchronously it probably feels even more responsive than mine, which I think is great.

Maybe there is a way to combine the approaches?

@chubakueno based in this comment, if the search is being executed asynchronously, is there a guarantee that the search results are always from the last character typed (I mean all the characters that you already typed )?

@chubakueno
Copy link
Contributor Author

chubakueno commented Dec 26, 2024

@mjkkirschner The solution I proposed debounces the keypresses so that the search is triggered at a later time, but the searches still run on the UI thread. I have still experienced it blocking the UI while it waits for a search to finish, though not for multiple seconds like the current implementation.
Since @chubakueno 's solution doesn't rely on timeouts and the searches run asynchronously it probably feels even more responsive than mine, which I think is great.
Maybe there is a way to combine the approaches?

@chubakueno based in this comment, if the search is being executed asynchronously, is there a guarantee that the search results are always from the last character typed (I mean all the characters that you already typed )?

Yes the last search is always from the last character typed. It may have to wait for a single pending search to execute (without blocking the UI thread), but last character typed is always last search.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants