How can I improve the performance of ASP.NET by adjusting the CLR thread throttling properties?
This post applies to: .NET 2.0, 3.0 & 3.5.
The CLR uses an adjustable threshold property called minWorkerThreads and minIoThreads to control when to introduce throttling to thread creation. The idea behind the delay is to prevent a burst in request load from quickly creating additional threads that will later lead to excessive thread context switching and negatively impact performance.
In ASP.NET, the CLR defaults both the minWorkerThreads and minIoThreads properties to 1. This number is then multiplied by the number of logical processors you have so a 2 core server with default settings (minWorkerThreads=1, minIoThreads=1) would have a worker thread minimum limit of 2 and completion port minimum limit of 2. I would recommend changing both properties to a number between 1 – 50. The best way that I have found to determine the optimal number of minWorkerThreads is to take a user mode process dump of the W3wp.exe process during typical load and use the Worker Threads Total from the !threadpool command as a starting point.
Here is an example of the !threadpool command output:
0:000> .loadby sos mscorwks
0:000> !threadpool
CPU utilization 38%
Worker Thread: Total: 160 Running: 24 Idle: 136 MaxLimit: 3200 MinLimit: 32
Work Request in Queue: 0
--------------------------------------
Number of Timers: 70
--------------------------------------
Completion Port Thread:Total: 3 Free: 3 MaxFree: 96 CurrentLimit: 3 MaxLimit: 3200 MinLimit: 32
So if your web site typically runs with a worker thread total of 160, then 160 divided by the number of logical processors would be a great place to set minWorkerThreads and minIoThreads to. So in the example above, with 32 logical processors, the minWorkerThreads and minIoThreads should be set to 5 (5 * 32 cores = 160 which is the current worker thread total).
After setting the value to 5, understand that this will not automatically create 160 threads nor guarantee to maintain 160 threads while the process is running. What this will actually do is allow the process to create up to 160 threads before introducing throttling to thread creation. Think of these properties as if they were named minWorkerThreadsBeforeThrottling and minIoThreadsBeforeThrottling. A word of caution; if you change the minimum threads to a value greater than the maximum (default is 100) then the value will be ignored and the default minimum of 1 thread will be used.
File: Machine.config
<configuration>
<system.web>
<processModel minWorkerThreads="5" minIoThreads="5" />
</system.web>
</configuration>
There are times then you need to adjust the CLR threading in code rather than in the Machine.config. Here is an example in C#:
const int MinimumClrThreads = 5; //use this value to control the threads
//get number of logical processors to simulate default asp.net behavior
int logicalProcessors = System.Environment.ProcessorCount;
int minWorkerThreads = MinimumClrThreads * logicalProcessors;
int minIoThreads = MinimumClrThreads * logicalProcessors;
//set the minumum number of worker and IO threads
ThreadPool.SetMinThreads(minWorkerThreads, minIoThreads);
For more information on the ProcessModelSection class:
https://msdn.microsoft.com/en-us/library/system.web.configuration.processmodelsection.aspx