-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Some improvement for import completion #43548
Conversation
genlu
commented
Apr 21, 2020
•
edited
Loading
edited
- Added 500ms timebox to completion to unimported extension method
- various perf improvements to reduce allocations
- Removed text "experimental" from UI, but kept the experiment code. The plan is to disable this via experiment for all external RTW users while enable it for internal and preview users
|
||
var builder = ArrayBuilder<MatchResult>.GetInstance(); |
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.
💡 You can pass a length to GetInstance
. That may or may not help 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.
it just calls EnsureCapacity underneath
http://sourceroslyn.io/#Microsoft.CodeAnalysis/ArrayBuilder.cs,355
// 1. We need to show items even if they don't match filter text | ||
// 2. No filter is selected | ||
builder.EnsureCapacity(data.InitialSortedList.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.
was this a speculative perf change? or was this driven from some actual data? i have no problem with it either way, i'm just curious.
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 addressing RPS regression caught in validation PR.
Before: +6.3mb LOH allocation
https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_git/VS/pullrequest/278169
After: +610kb LOH allocation
https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_git/VS/pullrequest/278694
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.
@sharwell is your sdgmented array ready?
bdacba4
to
1eab87a
Compare
472e00e
to
f713449
Compare
855017c
to
fad9d46
Compare
Is there a reason we are removing the experiment? I'd like to go over the details with you before making this change. |
@sharwell @CyrusNajmabadi please take a look, thanks |
src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
public IEnumerator<CompletionItem> GetEnumerator() |
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 you actually enumerate this dictionary? if so, you could consider making a struct enumrator so you save on this allocatoin as well.
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, but only once (per completion session), so it's probably no t necessary
@@ -650,6 +627,97 @@ int IEqualityComparer<ImmutableHashSet<string>>.GetHashCode(ImmutableHashSet<str | |||
return hash; | |||
} | |||
|
|||
private class DisplayNameToItemsMap : IEnumerable<CompletionItem> |
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.
considre not directly exposing this as a IEnumerable. will prevent anything from going through teh interface-dispatch pathways 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.
What do you mean by this? I'm passing this to ArrayBuilder.AddRange(), so I think the interface is required?
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.
ah ok. another option would be for you to enumerate this yourself, calling ArrayBuilder.Add.
But if this is only one allocation, it's nbd.
// Either the timebox is not enabled, so we need to wait until the operation for complete, | ||
// or there's no timeout, and we now have all completion items ready. | ||
var items = await getItemsTask.ConfigureAwait(false); | ||
nestedTokenSource.Cancel(); |
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 cancellation necessary? you only get here if the computation succeeded, so why do we need to cancel anything?
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.
you are right, this can only cancels the Delay task
@@ -23,16 +23,19 @@ internal abstract partial class AbstractTypeImportCompletionService | |||
public Checksum Checksum { get; } | |||
|
|||
private ImmutableArray<TypeImportCompletionItemInfo> ItemInfos { get; } | |||
private int PublicItemCount { get; } |
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.
doc.
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.
Added doc. We need to exact number of items we are dealing with, since some of the optimization rely on this knowledge to avoid allocation from calls to Resize
@@ -159,6 +178,9 @@ public void AddItem(INamedTypeSymbol symbol, string containingNamespace, bool is | |||
CompletionItemFlags.CachedAndExpanded, | |||
extensionMethodData: null); | |||
|
|||
if (isPublic) | |||
_publicItemCount++; |
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.
need this all doc'ed. i couldn't really undrestand what was going on.
Looking good overall. Some things i'm not sure i understand just yet. |
201c293
to
8ae23d3
Compare
@CyrusNajmabadi Any more comments on this? |
Ping @CyrusNajmabadi |
can try to get to this tomorrow. please pping me then. |
Ping @sharwell as well |
@@ -577,7 +577,7 @@ | |||
<value>When on multiple lines</value> | |||
</data> | |||
<data name="Show_items_from_unimported_namespaces" xml:space="preserve"> | |||
<value>Show items from unimported namespaces (experimental)</value> | |||
<value>Show items from unimported namespaces</value> |
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.
By removing the 'experiment' flag, does that mean we are plan to use the cancellation data to see if we can enable this by default for all users?
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 feature has been stabilized for a few releases, so functionally we think we are ready to move it out of the experimental state. However, current implementation still incurs too much of perf hit for many users to justify enabling it by default. Various things contributed to this, e.g. OOP cost, some existing editor APIs is not designed for handling large amount of items, etc. We will keep making improvement and monitoring the telemetry, hopefully we can turn it on by default in a future release.
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 just have a few questions about the user scenarios after this change.
The optimization parts LGTM, (but I don't know how many real benefits it would have). I saw you have posted some memory data around this change. Would it also bring perf benefits? (I am guessing it might help GC)
Port #43548 from master-vs-deps to master