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

[Performance] Reduce allocations in PENamedTypeSymbol.EnsureTypeParametersAreLoaded #70766

Merged
merged 3 commits into from
Nov 13, 2023

Conversation

Youssef1313
Copy link
Member

@Youssef1313 Youssef1313 commented Nov 10, 2023

  • Fast path for zero arity. Just use empty immutable array directly.
    • This code path shouldn't need to use any of the interlocked APIs since the empty array is always the same instance.
  • Use ArrayBuilder instead of an array. Converting an array to immutable array involves allocating another array and copying from the old to the new one. By using ArrayBuilder, a single array is only ever created.
  • We could go further and add two more specialized code paths for one element and two element cases, and use ImmutableArray.Create(element1) and ImmutableArray.Create(element1, element2) respectively, which would be even more efficient than ArrayBuilder. I'm not sure though if it's worth doing it that way.

@Youssef1313 Youssef1313 requested a review from a team as a code owner November 10, 2023 20:21
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Nov 10, 2023
@ghost ghost added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label Nov 10, 2023
@Youssef1313
Copy link
Member Author

@AlekseyTs

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

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

Special casing doesn't really seem worth it to me for this case. If future perf traces indicate that it would be a real improvement, we can look at it at that point.

var moduleSymbol = ContainingPEModule;

// If this is a nested type generic parameters in metadata include generic parameters of the outer types.
int firstIndex = _genericParameterHandles.Count - _arity;

TypeParameterSymbol[] ownedParams = new TypeParameterSymbol[_arity];
Copy link
Member

Choose a reason for hiding this comment

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

@333fred avoiding this unnecessary allocation on every type does seem like a nice to have.

Copy link
Member

Choose a reason for hiding this comment

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

Huh?

@@ -2658,19 +2658,26 @@ private void EnsureTypeParametersAreLoaded()
{
if (_lazyTypeParameters.IsDefault)
{
if (_arity == 0)
{
_lazyTypeParameters = ImmutableArray<TypeParameterSymbol>.Empty;
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 10, 2023

Choose a reason for hiding this comment

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

_lazyTypeParameters = ImmutableArray.Empty;

Strictly speaking, this assignment is not guaranteed to be atomic. Please use ImmutableInterlocked.InterlockedInitialize. #Closed

Copy link
Contributor

@AlekseyTs AlekseyTs Nov 10, 2023

Choose a reason for hiding this comment

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

As an alternative, we could check arity and assign this way inside the constructor. There is a guarantee that there is no race with any other thread there,

Copy link
Member

Choose a reason for hiding this comment

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

I would prefer that approach myself.

Copy link
Member Author

Choose a reason for hiding this comment

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

I would prefer that approach myself.

I assume "that" refers to the second comment? 2456a06

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 1)

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Nov 10, 2023

This code path shouldn't need to use any of the interlocked APIs since the empty array is always the same instance.

The interlocked API is also used to make the assignment atomic. In that sense, it really doesn't matter whether we are trying to assign the same instance underneath or not. What we are trying to avoid as well is partial assignment.

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (commit 3)

@AlekseyTs AlekseyTs merged commit 8db6849 into dotnet:main Nov 13, 2023
@ghost ghost added this to the Next milestone Nov 13, 2023
@AlekseyTs
Copy link
Contributor

@Youssef1313 Thank you for the contribution.

@Youssef1313 Youssef1313 deleted the reduce-allocations-in-penamedtype branch November 13, 2023 17:42
@RikkiGibson RikkiGibson modified the milestones: Next, 17.9 P2 Nov 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Community The pull request was submitted by a contributor who is not a Microsoft employee. 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.

5 participants