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

Remove double array allocation in SemanticTokens #74271

Merged

Conversation

ToddGrun
Copy link
Contributor

@ToddGrun ToddGrun commented Jul 4, 2024

This code was calling ArrayBuilder.ToArray, which would always allocate a new array as a result. Additionally, the arraybuilder itself would end up being large enough that it wouldn't end up going back into the pool. Thus, two large array were allocated on many calls into this method.

There really is no need for this method to use ArrayBuilder, as the code that ends up owning the resultant array doesn't attempt to put it back into a pool.

This shows up as about 0.5% of allocation in devenv in the customer profile I'm looking at, half of which should be removed by this change.

image

This code was calling ArrayBuilder.ToArray, which would always allocate a new array as a result. Additionally, the arraybuilder itself would end up being large enough that it wouldn't end up going back into the pool. Thus, two large array were allocated on many calls into this method.

There really is no need for this method to use ArrayBuilder, as the code that ends up owning the resultant array doesn't attempt to put it back into a pool.

This shows up as about 0.5% of allocation in devenv in the customer profile I'm looking at, half of which should be removed by this change.
@ToddGrun ToddGrun requested a review from a team as a code owner July 4, 2024 14:51
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Infrastructure untriaged Issues and PRs which have not yet been triaged by a lead labels Jul 4, 2024
@ToddGrun ToddGrun marked this pull request as draft July 4, 2024 16:41
@ToddGrun
Copy link
Contributor Author

ToddGrun commented Jul 4, 2024

There's an issue here, didn't notice that currentClassifiedSpanIndex was modified inside the loop, outside of normal loop incrementing

@ToddGrun ToddGrun marked this pull request as ready for review July 4, 2024 21:10
@ToddGrun
Copy link
Contributor Author

ToddGrun commented Jul 4, 2024

There's an issue here, didn't notice that currentClassifiedSpanIndex was modified inside the loop, outside of normal loop incrementing

Switched back to a pool, as the array size isn't known before the loop. Instead of ArrayBuilder, which doesn't pool array bigger than 128 elements, used a separate ObjectPool<List>

@ToddGrun
Copy link
Contributor Author

ToddGrun commented Jul 15, 2024

@dotnet/roslyn-ide -- ptal

@@ -243,23 +245,31 @@ private static void ConvertMultiLineToSingleLineSpans(SourceText text, Segmented

var tokenTypeMap = SemanticTokensSchema.GetSchema(supportsVisualStudioExtensions).TokenTypeMap;

using var _ = ArrayBuilder<int>.GetInstance(5 * classifiedSpans.Count, out var data);
for (var currentClassifiedSpanIndex = 0; currentClassifiedSpanIndex < classifiedSpans.Count; currentClassifiedSpanIndex++)
var data = s_tokenListPool.Allocate();
Copy link
Member

Choose a reason for hiding this comment

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

if you use .GetPooledObject you can use a using.

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

signing off on the idea. but we do have a cleaner pattern here that doesn't need try/finally.

}
finally
{
data.Clear();
Copy link
Member

Choose a reason for hiding this comment

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

i am fine not clearing an list of ints.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, went ahead and switched to GetPooledObject. Clearing will now occur upon retrieval from the pool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Infrastructure untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants