Merge pull request #2582 from ludovic-henry/fix-threadpool-starvation
authormonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 9 Feb 2016 23:00:32 +0000 (23:00 +0000)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 9 Feb 2016 23:00:32 +0000 (23:00 +0000)
commit64c5ac3d07bd464461c5b8c80a2d8c85370c12e3
tree4d8d73868ff5801868871cad25947d7a0f967ad8
parent9d35944f55c6ccb71929b5d8470b3a8b51242ffc
parent35c13bfe551d27e882a67031836fbc1a8e6f0fc7
Merge pull request #2582 from ludovic-henry/fix-threadpool-starvation

[threadpool] Improve the monitor thread heuristic

Because the ThreadPool heuristic is optimized for short lived work item, it has more difficulty when executing long lived work item. That case can lead to a starvation of the worker threads: they are all doing work, while there is outstanding request, and these requests are not satisfied because we reached the max number of working thread.

To fix that issue, we have the monitor thread, whose sole job is to unstuck this kind of starvation cases. Unfortunately, it only works when all the worker threads are in the ThreadState.WaitSleepJoin state, which excludes the case of calling an IO operation in a Task. That includes the case of FileStream.BeginRead/Write/... which implementation can be simplified as follows: FileStream.BeginRead(...) -> Task.Run(() => FileStream.Read(...)).

The way we implement it in this commit is: every MONITOR_INTERVAL (500ms here), we check if there is any outstanding request, and if so, we assume that we are in the starvation case, and we simply increase the max number of working thread. Also to reduce the number of false positives, we do that only if there has been no completed work item for more than at least MONITOR_INTERVAL (in case of low CPU usage, more otherwise, see monitor_sufficient_delay_since_last_dequeue). This case is typically the case where we have all working thread stuck in long running work items.

Finally we increase the monitor interval from 100ms to 500ms so we guarantee we do not create more than 2 threads per second in the monitor thread. That is the value used by the old threadpool.