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

Improve UI responsiveness when doing node search #15773

Merged
merged 10 commits into from
Feb 3, 2025
Merged

Conversation

pinzart90
Copy link
Contributor

@pinzart90 pinzart90 commented Jan 22, 2025

Purpose

Run the canvas search in a separate thread to improve UI responsiveness.
This PR was created as an alternative to #15733

Summary of changes:
Moved the Lucene IndexSearcher initialization. Previously it was recreated on every search. Now it is created only after the index is modified.
Run in canvas search in a separate thread (thread pool)
Introduced a cancellation token throughout the search operations
New searches will cancel old ones and only update the UI if the search was successful(not cancelled)
These changes will be under a new feature flag

Left to do:
Add tests
Add to library view search and others (pm search, autocomplete )?

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

(FILL ME IN) Brief description of the fix / enhancement. Use N/A to indicate that the changes in this pull request do not apply to Release Notes. Mandatory section

Reviewers

(FILL ME IN) Reviewer 1 (If possible, assign the Reviewer for the PR)

(FILL ME IN, optional) Any additional notes to reviewers or testers.

FYIs

(FILL ME IN, Optional) Names of anyone else you wish to be notified of

dirReader = writer != null ? writer.GetReader(applyAllDeletes: true) : DirectoryReader.Open(indexDir);
Searcher = new(dirReader);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@RobertGlobant20
I opted to initialize the Searcher (and dirReader) after every index modification that I could find.
Do you think I got them all ?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, I think all of them were covered.

Copy link

github-actions bot commented Jan 22, 2025

UI Smoke Tests

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

Copy link
Contributor

@RobertGlobant20 RobertGlobant20 left a comment

Choose a reason for hiding this comment

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

LGTM with one comment

@@ -627,6 +641,7 @@ internal void AddNodeTypeToSearchIndex(NodeSearchElement node, Document doc)
SetDocumentFieldValue(doc, nameof(LuceneConfig.NodeFieldsEnum.Parameters), node.Parameters ?? string.Empty);

writer?.AddDocument(doc);
InitializeIndexSearcher();
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if this specific call is needed due that usually after a node info is indexed (or all the nodes info were indexed ) we call CommitWriterChanges() - and this call is already calling the InitializeIndexSearcher() method.

Copy link
Contributor

Choose a reason for hiding this comment

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

This call is causing Dynamo startup to balloon to more than a minute.
image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should have a perf test for this

dirReader = writer != null ? writer.GetReader(applyAllDeletes: true) : DirectoryReader.Open(indexDir);
Searcher = new(dirReader);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, I think all of them were covered.

@RobertGlobant20
Copy link
Contributor

Coudl you add a GIF showing the behavior of InCanvas Search and Library Search?

{
dirReader = writer != null ? writer.GetReader(applyAllDeletes: true) : DirectoryReader.Open(indexDir);
Searcher = new(dirReader);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure if I should lock this, expecting concurrent access to Searcher
All the indexing changes will probably not happen while a user is actively searching ...

{

ctk.ThrowIfCancellationRequested();
Copy link
Member

Choose a reason for hiding this comment

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

where do all these get caught?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These get caught by the Task object that wraps the parent caller

Task.Run(() =>
{
   return Search(query, searchCancelToken.Token);
}

@mjkkirschner
Copy link
Member

this seems like a pretty good change, not too hard to reason about.
Any idea if concurrent tests are going to cause issues, I remember some kind of past problem with locked index files.

Do you know if Lucene is itself spinning up new threads or using the thread pool, or touts itself as thread safe, or at least not requiring the main thread?

Also, it just makes me think there's probably something interesting we can do with anticipating searches and performing them in parallel using autocomplete info in the future.

{
var result = Entries.Where(e => {
if (e.Name.Replace(" ", string.Empty).Equals(nodeName) && e.FullCategoryName.Equals(nodeCategory))
{
ctk.ThrowIfCancellationRequested();
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is this caught? Why can't the throw be at the start of the FindModel function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to short circuit the Where operation as well.
I will actually move it above the if, just to make the operation finish faster in case the if condition is not met

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will put on at the beginning too

@pinzart90
Copy link
Contributor Author

this seems like a pretty good change, not too hard to reason about. Any idea if concurrent tests are going to cause issues, I remember some kind of past problem with locked index files.

Do you know if Lucene is itself spinning up new threads or using the thread pool, or touts itself as thread safe, or at least not requiring the main thread?

Also, it just makes me think there's probably something interesting we can do with anticipating searches and performing them in parallel using autocomplete info in the future.

Thread safety

/// <para/><a name="thread-safety"></a><p><b>NOTE</b>: 
/// <see cref="IndexSearcher"/> instances are completely
/// thread safe, meaning multiple threads can call any of its
/// methods, concurrently.  If your application requires
/// external synchronization, you should <b>not</b>
/// synchronize on the <see cref="IndexSearcher"/> instance;
/// use your own (non-Lucene) objects instead.</p>

Copy link
Contributor

@chubakueno chubakueno left a comment

Choose a reason for hiding this comment

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

Please check the InitializeIndexSearcher call

@@ -627,6 +641,7 @@ internal void AddNodeTypeToSearchIndex(NodeSearchElement node, Document doc)
SetDocumentFieldValue(doc, nameof(LuceneConfig.NodeFieldsEnum.Parameters), node.Parameters ?? string.Empty);

writer?.AddDocument(doc);
InitializeIndexSearcher();
Copy link
Contributor

Choose a reason for hiding this comment

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

This call is causing Dynamo startup to balloon to more than a minute.
image

@pinzart90
Copy link
Contributor Author

Please check the InitializeIndexSearcher call

Yeah, I am going to revert that part of the changes. It seems the indexing is affected even when doing searches (or weights of results, or something similar)

@chubakueno
Copy link
Contributor

Please check the InitializeIndexSearcher call

Yeah, I am going to revert that part of the changes. It seems the indexing is affected even when doing searches (or weights of results, or something similar)

Wrote up a quick fix #15797 . Normally i'd send it to the PR author's repo but this is in DynamoDS's so sent it another PR.

@pinzart90 pinzart90 requested a review from chubakueno February 3, 2025 16:24
@pinzart90
Copy link
Contributor Author

Please check the InitializeIndexSearcher call

Yeah, I am going to revert that part of the changes. It seems the indexing is affected even when doing searches (or weights of results, or something similar)

Wrote up a quick fix #15797 . Normally i'd send it to the PR author's repo but this is in DynamoDS's so sent it another PR.

THanks, that fixed the leftover failures

@chubakueno
Copy link
Contributor

chubakueno commented Feb 3, 2025

Happy to hear that, should we include the ticket number into this PR? DYN-8045. Closed the other PR #15733 .

Please check the InitializeIndexSearcher call

Yeah, I am going to revert that part of the changes. It seems the indexing is affected even when doing searches (or weights of results, or something similar)

Wrote up a quick fix #15797 . Normally i'd send it to the PR author's repo but this is in DynamoDS's so sent it another PR.

THanks, that fixed the leftover failures

@pinzart90
Copy link
Contributor Author

@pinzart90 pinzart90 merged commit 6fbe022 into master Feb 3, 2025
23 of 24 checks passed
@pinzart90 pinzart90 deleted the searchbar_threading branch February 3, 2025 20:20
johnpierson added a commit to johnpierson/Dynamo that referenced this pull request Feb 4, 2025
* Bring back search performance improvement (DynamoDS#15789)

* Stabilize tests pt2 (DynamoDS#15779)

* DYN-7268 Improve UX when IDSDK is not installed on system running Dynamo (DynamoDS#15790)

* Improve UI responsiveness when doing node search (DynamoDS#15773)

Co-authored-by: chubakueno <[email protected]>

---------

Co-authored-by: pinzart90 <[email protected]>
Co-authored-by: Ashish Aggarwal <[email protected]>
Co-authored-by: chubakueno <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants