-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Speed up progression searches by using the navigate-to index #54382
Conversation
// to. | ||
spanStart = sourceText.Length; | ||
} | ||
var span = NavigateToUtilities.GetBoundedSpan(_searchResult.NavigableItem, sourceText); |
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.
extracted the above into a helper to use in progression as well.
return result; | ||
} | ||
} | ||
=> NavigateToUtilities.GetKindsProvided(_workspace.CurrentSolution); |
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.
similar. this moved to a common locatino so Progressin could use it.
src/VisualStudio/Core/Def/Implementation/Progression/ProgressionOptions.cs
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/Progression/ProgressionOptions.cs
Show resolved
Hide resolved
private static string GetIconString(Glyph glyph) | ||
{ | ||
return glyph switch | ||
{ | ||
Glyph.ClassPublic or Glyph.ClassProtected or Glyph.ClassPrivate or Glyph.ClassInternal => IconHelper.GetIconName("Class", GetAccessibility(glyph, Glyph.ClassPublic)), | ||
Glyph.ConstantPublic or Glyph.ConstantProtected or Glyph.ConstantPrivate or Glyph.ConstantInternal => IconHelper.GetIconName("Field", GetAccessibility(glyph, Glyph.ConstantPublic)), | ||
Glyph.DelegatePublic or Glyph.DelegateProtected or Glyph.DelegatePrivate or Glyph.DelegateInternal => IconHelper.GetIconName("Delegate", GetAccessibility(glyph, Glyph.DelegatePublic)), | ||
Glyph.EnumPublic or Glyph.EnumProtected or Glyph.EnumPrivate or Glyph.EnumInternal => IconHelper.GetIconName("Enum", GetAccessibility(glyph, Glyph.EnumPublic)), | ||
Glyph.EnumMemberPublic or Glyph.EnumMemberProtected or Glyph.EnumMemberPrivate or Glyph.EnumMemberInternal => IconHelper.GetIconName("EnumMember", GetAccessibility(glyph, Glyph.EnumMemberPublic)), | ||
Glyph.ExtensionMethodPublic or Glyph.ExtensionMethodProtected or Glyph.ExtensionMethodPrivate or Glyph.ExtensionMethodInternal => IconHelper.GetIconName("Method", GetAccessibility(glyph, Glyph.ExtensionMethodPublic)), | ||
Glyph.EventPublic or Glyph.EventProtected or Glyph.EventPrivate or Glyph.EventInternal => IconHelper.GetIconName("Event", GetAccessibility(glyph, Glyph.EventPublic)), | ||
Glyph.FieldPublic or Glyph.FieldProtected or Glyph.FieldPrivate or Glyph.FieldInternal => IconHelper.GetIconName("Field", GetAccessibility(glyph, Glyph.FieldPublic)), | ||
Glyph.InterfacePublic or Glyph.InterfaceProtected or Glyph.InterfacePrivate or Glyph.InterfaceInternal => IconHelper.GetIconName("Interface", GetAccessibility(glyph, Glyph.InterfacePublic)), | ||
Glyph.MethodPublic or Glyph.MethodProtected or Glyph.MethodPrivate or Glyph.MethodInternal => IconHelper.GetIconName("Method", GetAccessibility(glyph, Glyph.MethodPublic)), | ||
Glyph.ModulePublic or Glyph.ModuleProtected or Glyph.ModulePrivate or Glyph.ModuleInternal => IconHelper.GetIconName("Module", GetAccessibility(glyph, Glyph.ModulePublic)), | ||
Glyph.PropertyPublic or Glyph.PropertyProtected or Glyph.PropertyPrivate or Glyph.PropertyInternal => IconHelper.GetIconName("Property", GetAccessibility(glyph, Glyph.PropertyPublic)), | ||
Glyph.StructurePublic or Glyph.StructureProtected or Glyph.StructurePrivate or Glyph.StructureInternal => IconHelper.GetIconName("Structure", GetAccessibility(glyph, Glyph.StructurePublic)), | ||
_ => null, | ||
}; |
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.
Anyway to instead reuse GetTags
?
public static ImmutableArray<string> GetTags(Glyph glyph) |
and also:
private static Accessibility GetAccessibility(ImmutableArray<string> tags) |
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.
yup. THat seems nice. Thanks!
@@ -208,7 +208,7 @@ private static Glyph GetGlyph(string tag, ImmutableArray<string> allTags) | |||
return Glyph.None; | |||
} | |||
|
|||
private static Accessibility GetAccessibility(ImmutableArray<string> tags) | |||
public static Accessibility GetAccessibility(ImmutableArray<string> tags) |
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.
public static Accessibility GetAccessibility(ImmutableArray<string> tags) | |
public static Accessibility GetAccessibility(this ImmutableArray<string> tags) |
very nit here, but I would expect this to be an extension like the others in the 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.
nooooooooooooooooooooooooooooooooooooo do not make highly specific extension methods on widely used types like this.
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'm not a fan of extending random collections. For example, you could have an ImmutableArray in many different contexts. Having this .GetAccessibility extension show up for all of those seems wonky to me :)
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.
almost all static types called XXXExtensions though are extension methods. Should it move instead?
NavigateToItemKind.Constant or | ||
NavigateToItemKind.EnumItem or | ||
NavigateToItemKind.Field => CodeNodeCategories.Field, |
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.
NavigateToItemKind.Constant or | |
NavigateToItemKind.EnumItem or | |
NavigateToItemKind.Field => CodeNodeCategories.Field, | |
NavigateToItemKind.Constant or | |
NavigateToItemKind.EnumItem or | |
NavigateToItemKind.Field => CodeNodeCategories.Field, |
This is definitely a style preference, but I find it hard to know that items are linked to a single thing in switch expressions without the indentation.
var groupName = glyph switch | ||
{ | ||
Glyph.ClassPublic or Glyph.ClassProtected or Glyph.ClassPrivate or Glyph.ClassInternal => "Class", | ||
Glyph.ConstantPublic or Glyph.ConstantProtected or Glyph.ConstantPrivate or Glyph.ConstantInternal => "Field", |
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 use the same glyph for constants and fields?
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.
Yup! As per GetOrCreateNodeForFieldAsync it looks like we only distinguish fields and enum-members in progression.
The current progression search system works by literally walking the entire solution, producing compilations for all projects and symbols for every symbol therein. This is pretty terrible as it's enormously costly and uses a ton of ram. On my machine it takes a full 2 minutes to search Roslyn.sln and uses at least a GB of ram.
This PR introduces a new implementation of progression search that sits on top of the NavigateTo search index instead. This brings search time down <4 seconds, and uses around 900mb less memory. This also benefits from:
However, this change is not a pure win. The way progression search works today is that all entries are backed by real symbols. This means that the presented nodes can expose commands (like 'find all callers'). These continue to work for normal progression items. However, this is not supported for tehse new search results (as they're not backed by a real symbol anymore).
The progression team is going to investigate though how often (if ever) these advanced commands are used on search results. We hypothesize that very few people will be affected by this, but we would like data to be sure. So, in the meantime, this will be off by default.