-
Notifications
You must be signed in to change notification settings - Fork 635
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
Node Search performance improvements #12056
Conversation
@@ -105,8 +105,7 @@ | |||
Text="{Binding Path=SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" | |||
MinWidth="200" | |||
CaretBrush="{StaticResource CommonSidebarTextColor}" | |||
Margin="26,0,0,-1" | |||
TextChanged="OnSearchTextBoxTextChanged" /> | |||
Margin="26,0,0,-1"/> |
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.
For some reason the twoWay Binding to "SearchText" + TextChanged="OnSearchTextBoxTextChanged" causes 2 TextChanged events to be triggered for every input character
So I changed it so that we only bind the Text control to the "SearchText" Path.
When the text is changed, the "SearchText" property's setter will be called...and that is when we will execute the Search command
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.
could this also be fixed by making this a one way binding?
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.
Changing around the binding types broke other parts of the UI (ex. making it one way did not update the Textbox initial value "Search" anymore)
@@ -13,6 +13,7 @@ namespace Dynamo.Search | |||
public class SearchDictionary<V> | |||
{ | |||
private ILogger logger; | |||
private static int LIMIT_SEARCH_TAG_SIZE = 100; |
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.
could this be too small for some localized searches?
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.
Maybe...the value is definitely up for debate. I wonder if it would actually be best to warn the user if this limit is surpassed (I am not sure when or where)
I can take a look at the tags we got from Jostein to get a better idea of how many characters there are in a "normal" situation
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.
Increased to 300
@@ -342,7 +343,7 @@ internal void RebuildTagDictionary() | |||
tagAndWeight => | |||
new | |||
{ | |||
Tag = tagAndWeight.Key, | |||
Tag = tagAndWeight.Key.Substring(0, tagAndWeight.Key.Length > LIMIT_SEARCH_TAG_SIZE ? LIMIT_SEARCH_TAG_SIZE : tagAndWeight.Key.Length), |
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.
is this actually useful at this point? Does the cost of all these extra conditional operations undo the potential savings?
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.
Same q here.
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...after all search tags have been added/removed RebuildTagDictionary
is called only once.
Performance penalty here should be negligible, compared to the constant searches on each text change.
subPatternsList.Insert(0, query); | ||
subPatterns = (subPatternsList).ToArray(); | ||
|
||
if (subPatterns.Length > 1)// More than one word |
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.
👍
@pinzart90 it looks good after the tests pass, can I ask you to manually check that regular library search still works? |
@pinzart do we have any metrics on how much better search is before and after this 🙏 ? |
var subPatternsList = subPatterns.ToList(); | ||
subPatternsList.Insert(0, query); | ||
subPatterns = (subPatternsList).ToArray(); |
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.
Could you explain with an example? If the query is all elements of category
, the subpatterns list will be ["all", "elements", "of", "category"]
, then the subpatterns list will now be ["all elements of category", "all", "elements", "of", "category"]
?
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.
that is correct.
I think the logic behind it was to look for the full text first (a match with the full text should have the highest priority).
@mjkkirschner I am working now on adding a performance test...and I will also check that existing functionality is not broken |
Here are some numbers @Amoursol With Fix "all elements of category" 5 times: Without Fix "all elements of category" 5 times: With Fix "category" 5 times: Without Fix "category" 5 times: |
Assert.AreEqual(results.Count(), 20); | ||
|
||
int timeLimit = 260;//ms | ||
Assert.IsTrue(Math.Abs(stopwatch.ElapsedMilliseconds - timeLimit) < 0.2 * timeLimit, $"Search time should be within a range of +/- 20% of {timeLimit}ms but we got {stopwatch.ElapsedMilliseconds}ms"); |
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.
Still might be a bit flaky ...
@@ -13,6 +13,7 @@ namespace Dynamo.Search | |||
public class SearchDictionary<V> | |||
{ | |||
private ILogger logger; | |||
private static int LIMIT_SEARCH_TAG_SIZE = 300; |
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 all agree that 300 characters is good enough ?
Should we increase ?
Looking through the search tags we got from Jostein, I found the following:
- The longest search tag is 899 characters
- There are 34 search tags (out of 6525) that are over 300 characters
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.
ALso this limit will be used in the Package Search window as well..(using package descriptions)
We could use another limit for Package Search ....
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.
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.
This is fine by me but I'm still confused - these search tags from Jostein look like node descriptions. I'm curious if the entire description is used as a search tag, then what's the benefit of the search tags included in the <search></search>
XML?
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.
@aparajit-pratap it's to inject extra search terms without adding them to the description.
So I can add box
to the search terms for Cuboid - without needing to add box
to the description.
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.
@pinzart90 what do you think about making this a hidden preference? I know it's more work, and kind of a pain, but it let's users tweak it if they run into trouble.
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.
@mjkkirschner I added a new assembly config for it
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.
oh, sorry @pinzart90 - I was not clear, by hidden preference -I just meant a preference in the dynamosettings.xml with no analog in the UI to control it. This is fine as well, users can still modify this if we want them to test something.
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.
@mjkkirschner if you think there is good enough reason to move to Preferences, then I can do that
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 think it would be a good idea to move it to the preference settings file so we have all preferences in one place. That is usually the one file where all such user preferences go.
Ok awesome, so that looks to be roughly a:
That's pretty epic! We can discuss further works after 2.13 drops :) Thanks Tibi. |
@@ -214,8 +214,6 @@ internal void Filter() | |||
} | |||
strBuilder.Append(", "); | |||
} | |||
|
|||
Analytics.LogPiiInfo("Filter-categories", strBuilder.ToString().Trim()); |
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.
When is this triggered?
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.
Analytics.LogPiiInfo is deprecated and actually does not log anything anymore. I just cleaned up the SearchViewModel class ...I do not think performance is affected by this though..
@@ -13,6 +13,7 @@ namespace Dynamo.Search | |||
public class SearchDictionary<V> | |||
{ | |||
private ILogger logger; | |||
private static int LIMIT_SEARCH_TAG_SIZE = 300; |
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.
This is fine by me but I'm still confused - these search tags from Jostein look like node descriptions. I'm curious if the entire description is used as a search tag, then what's the benefit of the search tags included in the <search></search>
XML?
try | ||
{ | ||
// Look up search tag limit in the assembly configuration | ||
var assemblyConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location); |
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.
Is this the DynamoCore.dll.config
file?
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
Simplify search to improve performance
Changes:
Note:
Difference between culture sensitive and ordinal serarch:
https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#string-comparisons-that-use-the-current-culture
I would opt for OrdinalIgnoreCase because we get better performance...and the order of the returned results is not really a deal breaker (I think...)