Skip to content

Remove lock allocation from SafeSocketHandle on Windows#32275

Merged
stephentoub merged 1 commit intodotnet:masterfrom
stephentoub:lockalloc
Feb 14, 2020
Merged

Remove lock allocation from SafeSocketHandle on Windows#32275
stephentoub merged 1 commit intodotnet:masterfrom
stephentoub:lockalloc

Conversation

@stephentoub
Copy link
Member

@stephentoub stephentoub commented Feb 14, 2020

The first time a Socket is used, we bind its handle to the ThreadPool for overlapped I/O. In order to avoid this happening on multiple threads concurrently if multiple threads concurrently race to perform this initialization, we take a lock. We currently allocate an object and store it for the lifetime of the Socket, purely to do this one-time synchronization, after which the object is useless. While in general we prefer not to lock on this on exposed objects (in order to avoid any issues that might occur from an external consumer also locking on the same object), the chances of someone locking on this object are slim to none, and even if they did, it wouldn't make any difference once the socket was already initialized, and even if the socket wasn't yet initialized, it would only be a one-time contention, without lock ordering concerns. (Completely degenerate code could take and never release a lock on a socket's SafeHandle prior to first use, and that would then block that Socket from operating, but such code could also cause problems by just closing the exposed handle, and the answer would be the same: don't do that.)

On the same test as in #32271...

Before:
image

After:
image
(this still includes the allocations removed in #32271)

cc: @dotnet/ncl

The first time a Socket is used, we bind its handle to the ThreadPool for overlapped I/O.  In order to avoid this happening on multiple threads concurrently if multiple threads concurrently race to perform this initialization, we take a lock.  We currently allocate an object and store it for the lifetime of the Socket, purely to do this one-time synchronization, after which the object is useless.  While in general we prefer not to lock on `this` (in order to avoid any issues that might occur from an external consumer also locking on the same object), the chances of someone locking on this object are slim to none, and even if they did, it wouldn't make any difference once the socket was already initialized, and even if the socket wasn't yet initialized, it would only be a one-time contention, without lock ordering concerns.
@stephentoub stephentoub added this to the 5.0 milestone Feb 14, 2020
@stephentoub stephentoub merged commit eedeeb6 into dotnet:master Feb 14, 2020
@stephentoub stephentoub deleted the lockalloc branch February 14, 2020 16:12
@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants