-
Notifications
You must be signed in to change notification settings - Fork 636
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
base: master
Are you sure you want to change the base?
Conversation
dirReader = writer != null ? writer.GetReader(applyAllDeletes: true) : DirectoryReader.Open(indexDir); | ||
Searcher = new(dirReader); | ||
} | ||
|
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.
@RobertGlobant20
I opted to initialize the Searcher (and dirReader) after every index modification that I could find.
Do you think I got them all ?
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, I think all of them were covered.
UI Smoke TestsTest: success. 11 passed, 0 failed. |
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.
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(); |
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 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.
dirReader = writer != null ? writer.GetReader(applyAllDeletes: true) : DirectoryReader.Open(indexDir); | ||
Searcher = new(dirReader); | ||
} | ||
|
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, I think all of them were covered.
Coudl you add a GIF showing the behavior of InCanvas Search and Library Search? |
{ | ||
if (DynamoModel.FeatureFlags?.CheckFeatureFlag("searchbar_debounce", false) ?? false) | ||
{ | ||
searchDebouncer ??= new ActionDebouncer(dynamoViewModel?.Model?.Logger); | ||
} | ||
|
||
if (DynamoModel.FeatureFlags?.CheckFeatureFlag("searchbar_spearate_thread", false) ?? false) |
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.
does this exist?
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.
I have to create it. THanks !
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.
spelling separate
@@ -78,6 +80,10 @@ public bool BrowserVisibility | |||
internal int searchDelayTimeout = 150; | |||
// Feature flags activated debouncer for the search UI. | |||
internal ActionDebouncer searchDebouncer = null; | |||
// Cancel token source used for the node search operations. | |||
internal CancellationTokenSource searchCancelTooken; |
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.
spelling token
}, searchCancelTooken.Token).ContinueWith((t, o) => | ||
{ | ||
// This continuation will execute on the UI thread (forced by using FromCurrentSynchronizationContext()) | ||
searchResults = new List<NodeSearchElementViewModel>(t.Result); |
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.
so, there should never be concurrent access to this collection because we always cancel when a search is performed?
oh, and it's always on the UI thread as you commented... duh.
{ | ||
dirReader = writer != null ? writer.GetReader(applyAllDeletes: true) : DirectoryReader.Open(indexDir); | ||
Searcher = new(dirReader); | ||
} |
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 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 ...
@@ -972,11 +1004,11 @@ private void IsSelectedChanged(object sender, PropertyChangedEventArgs e) | |||
/// </summary> | |||
/// <returns> Returns a list with a maximum MaxNumSearchResults elements.</returns> | |||
/// <param name="search"> The search query </param> | |||
internal IEnumerable<NodeSearchElementViewModel> Search(string search) | |||
internal IEnumerable<NodeSearchElementViewModel> Search(string search, CancellationToken ctk = default) |
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.
can you update the params?
{ | ||
|
||
ctk.ThrowIfCancellationRequested(); |
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.
where do all these get caught?
this seems like a pretty good change, not too hard to reason about. 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(); |
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.
Where is this caught? Why can't the throw
be at the start of the FindModel
function?
|
||
if (DynamoModel.FeatureFlags?.CheckFeatureFlag("searchbar_spearate_thread", false) ?? false) | ||
{ | ||
enableSeachThreading = true; |
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.
enableSearchThreading
@@ -87,7 +87,9 @@ internal FeatureFlagsClient(string userkey, string mobileKey = null, bool testMo | |||
//in tests we want instancing on so we can test it. | |||
{ "graphics-primitive-instancing", LdValue.Of(true) }, | |||
//in tests we want search debouncing on so we can test it. | |||
{ "searchbar_debounce", LdValue.Of(true) } }); | |||
{ "searchbar_debounce", LdValue.Of(true) }, |
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.
Do we still need this?
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
*.resx
filesRelease 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