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

Avoid allocations in AbstractSyntaxIndex<>.GetIndexAsync #74075

Merged
merged 1 commit into from
Jun 21, 2024

Conversation

sharwell
Copy link
Member

Further improves a scenario that also suggested it will be improved by #73493.

Based on allocations observed in AB#2090900.

@sharwell sharwell requested a review from a team as a code owner June 20, 2024 13:29
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Jun 20, 2024
s_documentToIndex.TryAdd(document, index);
s_documentIdToIndex.AddOrUpdate(document.Id, index);
#else
// Avoid capturing index on the fast path by making a copy for the slow path
Copy link
Contributor

Choose a reason for hiding this comment

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

// Avoid capturing index on the fast path by making a copy for the slow path

Could this be moved to a local fn to avoid the allocation instead?

Copy link
Member Author

@sharwell sharwell Jun 20, 2024

Choose a reason for hiding this comment

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

It could, but it wouldn't be less net code. Creating a temporary local is pretty standard practice for this.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, I've never noticed it done this way whereas I've seen it done the other way a couple times.

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.

The NET part lgtm. I don't get the value in the local copy. We'll still have the closure allocation there afaict

@sharwell
Copy link
Member Author

The NET part lgtm. I don't get the value in the local copy. We'll still have the closure allocation there afaict

The problem isn't the closure allocation when used. The problem is it still creates a closure allocation for index when s_documentToIndex.TryGetValue returns true, and these lambdas are never used.

@CyrusNajmabadi
Copy link
Member

How does the local copy help there? Can you show the il diff? Thanks!

@sharwell
Copy link
Member Author

Here's a SharpLab example:

https://sharplab.io/#v2:C4LglgNgPgAgTARgLACgYAYAEMEDoBKArgHbBgC2AprgMID25ADpJQE4DKbAbmAMaUBnANyoM2BAFYRKUQGZscTDUwBvVJg2ZGrMFwCGwSuIBsmVpT0ATOsQgBPJTctgyNvRADqFgNYAVPQBGEJQAPHQBAFaUvMAANJjhUTEA/AB8mAIA+ta8hFSkvnQAksSWlAAemAC8mMSUAO4AFACU0uqa2nSGMZSWJtgAHJgAau6ElDDGYZHRwGmYAOKUwCVl5QCCAnbEvI3tmpqJs5g5eZSkzfuqVwcA9LeYnEZgAGaY9Ubu5lYOvHq8AAtepg9MRMGBShV3i4AZhgACwAITmBzDETnRcvlgODIeVcBoim8BHR3kY/mCIoQBMAbpp7tgAOzg7H1GG1ElWZyuYjud50VjeXC0jSvTCNACEWVOWMKqwquF8rDsS2Aowg40a0vOcQShGx+lYOLWzUuKAOBzUZvN1oha2q2AAnItlnLyh5+d42JttrtmrQbC8wABzQjmdb1PQuRovdwCSitYXm0WNW1Qqo1YiECAQU3WvOaGBMzPZtpW/MaekABTojCzBiMdFDmD+gME0PhcIRSMsBj0QrL5fp6xgABZm3pGMBQxCg0aoTZO0YY9StAZYQEHOQ9N4ZyDmzWHC9+YuMhA6PVV/DEwcpRizgVirjcCq1RqtaR4plqulU+UEwODgAX1QRNCzncppCAkCB06bpDD6HBTBgIZXwmKYjhSdIVVdehGDsb0dj2ADDhmNF32AXNNEtfN6SecE3g+EEIG+Sxfn+IE+lBcD21heFEWRVFsXI8D8UwQkMhJRjyUwSlqUTekwJcHj2RBSwuTANwID5AV+3zZNJWyO8ZUfNYFSVF8xkoTUjO1eJG31PRDV/E1E2o8sRVxe0YCdbDcXdAUvS2Qi/XoYhAxDMMIyjGMIDjf93JFN4U089NaizHNrzzMDiwgUsEswKsazrQxdUNFsgSRVkOz47te10hKh1HcdJ2nYhZ1/BIwXhJc9BXRg10wDdMC3Hc2r3XgD0wI9DW609z0vAFMo0A1wNwhwal/SCEtvTFtVlJ8LPVKzyM/b9VoPeK82AmRiI0RTcS2jRrquWDZmBRDsHQ0i5iwl0/I9QKfRaRMqnSSZcAAMVYBh8EELNgGmJIfsaOoLww4AWn/a6gA===

The key difference is the "original" code has a newobj before calling TryGetValue:

IL_000a: ldarg.0
IL_000b: newobj instance void C/'<>c__DisplayClass1_0'::.ctor()
// ... omitted for brevity ...
IL_002b: callvirt instance bool class [System.Runtime]System.Runtime.CompilerServices.ConditionalWeakTable`2<object, object>::TryGetValue(!0, !1&)
IL_0030: brtrue IL_00d9

While the "copy" code only has it after calling TryGetValue:

IL_0017: callvirt instance bool class [System.Runtime]System.Runtime.CompilerServices.ConditionalWeakTable`2<object, object>::TryGetValue(!0, !1&)
IL_001c: brtrue IL_00cd

// sequence point: hidden
IL_0021: ldarg.0
IL_0022: newobj instance void C/'<>c__DisplayClass2_0'::.ctor()

@dotnet dotnet deleted a comment from azure-pipelines bot Jun 21, 2024
@sharwell sharwell enabled auto-merge June 21, 2024 15:23
@sharwell sharwell merged commit e0873fa into dotnet:main Jun 21, 2024
25 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Jun 21, 2024
@jjonescz jjonescz modified the milestones: Next, 17.11 P3 Jun 24, 2024
@sharwell sharwell deleted the reduced-allocs branch July 16, 2024 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE 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