This is the issue for 1 year old PR dotnet/coreclr#137. Hopefully, it will help to move forward.
SemaphoreSlim uses PulseAll to notify all waiting threads that the Release happened. But, in fact, only few of the waiting threads will exit the lock (according to the value of semaphore currentCount). All other threads will waste the CPU resources just to check the condition and return to the Wait state. That becomes a bottleneck when the number of waiting threads is larger than the number of CPU cores.
The resolution will be to call Pulse according to the number of releaseCount and waitCount (Math.Min(releaseCount, waitCount)).
Performance comparison can be found here: dotnet/coreclr#137 (comment)
and here: dotnet/coreclr#137 (comment)
This is the issue for 1 year old PR dotnet/coreclr#137. Hopefully, it will help to move forward.
SemaphoreSlim uses
PulseAllto notify all waiting threads that the Release happened. But, in fact, only few of the waiting threads will exit the lock (according to the value of semaphorecurrentCount). All other threads will waste the CPU resources just to check the condition and return to the Wait state. That becomes a bottleneck when the number of waiting threads is larger than the number of CPU cores.The resolution will be to call
Pulseaccording to the number ofreleaseCountandwaitCount(Math.Min(releaseCount, waitCount)).Performance comparison can be found here: dotnet/coreclr#137 (comment)
and here: dotnet/coreclr#137 (comment)