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

Change AsyncLazy from NonReentrantLock to a simple monitor enter #73941

Merged
merged 4 commits into from
Jun 11, 2024

Conversation

CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi commented Jun 11, 2024

Addresses expensive lock contention in AsyncLazy (a core type with a fair amount of contention). From:

image

to:

image

Note: TakeLock itself went from:

image

to

image

(effectively basically nothing).

I can only conclude our NonreentrantLock is simply terrible :)

--

Kicked off build here: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=9710024&view=results

@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner June 11, 2024 17:59
@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 11, 2024
@CyrusNajmabadi
Copy link
Member Author

Probably good to get a distinct speedometer pass on this.

@jasonmalinowski
Copy link
Member

@CyrusNajmabadi Does anything indicate that SemaphoreSlim just won't be spinning and instead is just being more async?

Your screenshot might also not be accurate there: the "before" in TakeLock is the System.__Canon one, but the last screenshot is the one specialized on an enum, which I would imagine would be cheap. I'd expect there's another frame somewhere else which is the thing really to compare with. If you can't find the frame at all then I'd imagine something is wrong with your trace as I can't imagine TakeLock would disappear entirely!

@sharwell
Copy link
Member

Also the first pair of images shows an increase in the Inc column.

Copy link
Member

@sharwell sharwell left a comment

Choose a reason for hiding this comment

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

My main concern here relates to the use of a static field (the documentation for the change to a static field states that contention was not measured to be a problem). However, in review I noticed that there is no use of asynchronous functionality for this lock. Therefore, I propose we update this to use Monitor's functionality and make it equivalent to the current NonReentrantLock.

@CyrusNajmabadi
Copy link
Member Author

Therefore, I propose we update this to use Monitor's functionality and make it equivalent to the current NonReentrantLock.

i don't know what this means. We use the benefic of cancellable blocking wait on the lock. SemaphoreSlim works much better for this case.

If you'd like to work on an alternate here. Go for it.

@sharwell
Copy link
Member

I have concerns about the specific supporting data provided in the initial post above. If it turns out that contention is a problem on this path despite prior documentation to the contrary that needs to be resolved, I would suggest an approach like shown in 8e56c49 instead of the one here.

@CyrusNajmabadi
Copy link
Member Author

Contention can be negligible while this PR still being beneficial. For one, we're comparing the runtime's optimized semaphore impl, with our ancient, complex, sync primitive that was written for the workspace when we ran into a reentrancy problem (in the workspace) a decade ago). We used this as an acceptable type for AsyncLazy, but it was just the tool we had at the time.

@CyrusNajmabadi
Copy link
Member Author

Comparing before/after:

image

image

It just seems like a NonreentrantLock is not very good. And why would it be? We didn't ever invest in making it good. But it's not 10 years ago. We can move to battle-tested, highly performance runtime primitives that supplant these cases.

@CyrusNajmabadi CyrusNajmabadi changed the title Change AsyncLazy from NonReentrantLock to SemaphoreSlim Change AsyncLazy from NonReentrantLock to a simple monitor enter Jun 11, 2024
@CyrusNajmabadi CyrusNajmabadi requested a review from sharwell June 11, 2024 19:58
@CyrusNajmabadi CyrusNajmabadi enabled auto-merge June 11, 2024 20:40
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