Improve ReaderWriterLockSlim scalability (dotnet/coreclr#13495)
authorKoundinya Veluri <kouvel@users.noreply.github.com>
Wed, 23 Aug 2017 18:01:31 +0000 (11:01 -0700)
committerGitHub <noreply@github.com>
Wed, 23 Aug 2017 18:01:31 +0000 (11:01 -0700)
commit0721ae30b60171ea6d8a660695b558ec7ced2943
tree75ce98d2c7f3f6b69c8d2051ada8673dc8373655
parent123e4513a53d2cccf9ee97017289564f5f7307c6
Improve ReaderWriterLockSlim scalability (dotnet/coreclr#13495)

* Improve ReaderWriterLockSlim scalability

Subset of dotnet/coreclr#13243, fixes dotnet/coreclr#12780

- Prevented waking more than one waiter when only one of them may acquire the lock
- Limited spinning in some cases where it is very unlikely that spinning would help

The _myLock spin lock runs into some bad scalability issues. For example:
1. Readers can starve writers for an unreasonable amount of time. Typically there would be more readers than writers, and it doesn't take many readers to starve a writer. On my machine with 6 cores (12 logical processors with hyperthreading), 6 to 16 reader threads attempting to acquire the spin lock to acquire or release a read lock can starve one writer thread from acquiring the spin lock for several or many seconds. The issue magnifies with more reader threads.
2. Readers and especially writers that hold the RW lock can be starved from even releasing their lock. Releasing an RW lock requires acquiring the spin lock, so releasers are easliy starved by acquirers. How badly they are starved depends on how many acquirers there are, and it doesn't take many to show a very noticeable scalability issue. Often, these acquirers are those that would not be able to acquire the RW lock until one or more releasers release their lock, so the acquirers effectively starve themselves.

This PR does not solve (1), but solves (2) to a degree that could be considered sufficient. dotnet/coreclr#13243 solves (1) and (2) and for (2) it is still better by order-of-magnitude compared with this PR in several cases that I believe are not extreme, but if the complexity of deprioritization is deemed excessive for the goals then of what I tried so far this is the perhaps simplest and most reasonable way to solve (2).

I believe this PR would also be a reasonably low-risk one to port back to .NET Framework.

Commit migrated from https://github.com/dotnet/coreclr/commit/e000977dc11feb3f7f7920a57f0e53f4749377e0
src/coreclr/src/mscorlib/shared/System/Threading/ReaderWriterLockSlim.cs