Sunday, February 04, 2007

.NET Application Performance and Scalability: Threading Explained

another extract from: ScaleNet

Threading Explained
ASP.NET processes requests by using threads from the .NET thread pool. The thread
pool maintains a pool of threads that have already incurred the thread initialization
costs. Therefore, these threads are easy to reuse. The .NET thread pool is also self tuning.

It monitors CPU and other resource utilization, and it adds new threads or
trims the thread pool size as needed. You should generally avoid creating threads
manually to perform work. Instead, use threads from the thread pool. At the same
time, it is important to ensure that your application does not perform lengthy
blocking operations that could quickly lead to thread pool starvation and rejected
HTTP requests.

Formula for Reducing Contention
The formula for reducing contention can give you a good empirical start for tuning
the ASP.NET thread pool. Consider using the Microsoft product group-recommended
settings that are shown in Table 6.1 if the following conditions are true:
● You have available CPU.
● Your application performs I/O bound operations such as calling a Web method or
accessing the file system.
● The ASP.NET Applications/Requests in Application Queue performance counter
indicates that you have queued requests.
280 Improving .NET Application Performance and Scalability

Table 6.1: Recommended Threading Settings for Reducing Contention
Configuration setting Default value (.NET Framework 1.1) Recommended value

maxconnection 2 12 * #CPUs
maxIoThreads 20 100
maxWorkerThreads 20 100
minFreeThreads 8 88 * #CPUs
minLocalRequestFreeThreads 4 76 * #CPUs

To address this issue, you need to configure the following items in the
Machine.config file. Apply the recommended changes that are described in the
following section, across the settings and not in isolation. For a detailed description of each of these settings, see “Thread Pool Attributes” in Chapter 17, “Tuning .NET Application Performance.”

● Set maxconnection to 12 * # of CPUs. This setting controls the maximum number
of outgoing HTTP connections that you can initiate from a client. In this case,
ASP.NET is the client. Set maxconnection to 12 * # of CPUs.

● Set maxIoThreads to 100. This setting controls the maximum number of I/O
threads in the .NET thread pool. This number is automatically multiplied by the
number of available CPUs. Set maxloThreads to 100.

● Set maxWorkerThreads to 100. This setting controls the maximum number of
worker threads in the thread pool. This number is then automatically multiplied
by the number of available CPUs. Set maxWorkerThreads to 100.

● Set minFreeThreads to 88 * # of CPUs. This setting is used by the worker process
to queue all the incoming requests if the number of available threads in the thread
pool falls below the value for this setting. This setting effectively limits the number of requests that can run concurrently to maxWorkerThreads — minFreeThreads.
Set minFreeThreads to 88 * # of CPUs. This limits the number of concurrent
requests to 12 (assuming maxWorkerThreads is 100).

● Set minLocalRequestFreeThreads to 76 * # of CPUs. This setting is used by the
worker process to queue requests from localhost (where a Web application sends
requests to a local Web service) if the number of available threads in the thread
pool falls below this number. This setting is similar to minFreeThreads but it only
applies to localhost requests from the local computer. Set
minLocalRequestFreeThreads to 76 * # of CPUs.

Note: The recommendations that are provided in this section are not rules. They are a starting point. Test to determine the appropriate settings for your scenario. If you move your application to a new computer, ensure that you recalculate and reconfigure the settings based on the number of CPUs in the new computer.
Chapter 6: Improving ASP.NET Performance 281 If your ASPX Web page makes multiple calls to Web services on a per-request basis, apply the recommendations.

The recommendation to limit the ASP.NET runtime to 12 threads for handling
incoming requests is most applicable for quick-running operations. The limit also
reduces the number of context switches. If your application makes long-running
calls, first consider the design alternatives presented in the “Avoid Blocking on Long-Running Tasks” section. If the alternative designs cannot be applied in your scenario, start with 100 maxWorkerThreads, and keep the defaults for minFreeThreads. This ensures that requests are not serialized in this particular scenario. Next, if you see high CPU utilization and context-switching when you test your application, test by reducing maxWorkerThreads or by increasing minFreeThreads.

The following occurs if the formula has worked:
● CPU utilization increases.

● Throughput increases according to the ASP.NET Applications\Requests/Sec
performance counter.

● Requests in the application queue decrease according to the ASP.NET
Applications/Requests in Application Queue performance counter. If using the recommended settings does not improve your application performance, you may have a CPU bound scenario. By adding more threads you increase thread context switching. For more information, see “ASP.NET Tuning” in Chapter 17, “Tuning .NET Application Performance.”

More Information
For more information, see Knowledge Base article 821268, “PRB: Contention, Poor
Performance, and Deadlocks When You Make Web Service Requests from ASP.NET
Applications,” at http://support.microsoft.com/default.aspx?scid=kb;en-us;821268.

Threading Guidelines
This section discusses guidelines that you can use to help improve threading
efficiency in ASP.NET. The guidelines include the following:

● Tune the thread pool by using the formula to reduce contention.

● Consider minIoThreads and minWorkerThreads for burst load.

● Do not create threads on a per-request basis.

● Avoid blocking threads.

● Avoid asynchronous calls unless you have additional parallel work.

282 Improving .NET Application Performance and Scalability
Tune the Thread Pool by Using the Formula to Reduce Contention
If you have available CPU and if requests are queued, configure the ASP.NET
thread pool. For more information about how to do this, see “Formula for Reducing
Contention” in the preceding “Threading Explained” section. The recommendations
in “Threading Explained” are a starting point.

When your application uses the common language runtime (CLR) thread pool,
it is important to tune the thread pool correctly. Otherwise, you may experience
contention issues, performance problems, or possible deadlocks. Your application
may be using the CLR thread pool if the following conditions are true:

● Your application makes Web service calls.

● Your application uses the WebRequest or HttpWebRequest classes to make outgoing Web requests.

● Your application explicitly queues work to the thread pool by calling the
QueueUserWorkItem method.

More Information

For more information, see Knowledge Base article 821268, “PRB: Contention, Poor
Performance, and Deadlocks When You Make Web Service Requests from ASP.NET
Applications,” at http://support.microsoft.com/default.aspx?scid=kb;en-us;821268.

Consider minIoThreads and minWorkerThreads for Burst Load
If your application experiences burst loads where there are prolonged periods of
inactivity between the burst loads, the thread pool may not have enough time to
reach the optimal level of threads. A burst load occurs when a large number of users
connect to your application suddenly and at the same time. The minIoThreads and
minWorkerThreads settings enable you to configure a minimum number of worker
threads and I/O threads for load conditions.

At the time of this writing, you need a supported fix to configure these settings.
For more information, see the following Knowledge Base articles:

● 810259, “FIX: SetMinThreads and GetMinThreads API Added to Common
Language Runtime ThreadPool Class,” at http://support.microsoft.com
/default.aspx?scid=kb;en-us;810259

● 827419, “PRB: Sudden Requirement for a Larger Number of Threads from
the ThreadPool Class May Result in Slow Computer Response Time,” at
http://support.microsoft.com/default.aspx?scid=kb;en-us;827419
Chapter 6: Improving ASP.NET Performance 283

Do Not Create Threads on a Per-Request Basis
Creating threads is an expensive operation that requires initialization of both
managed and unmanaged resources. You should avoid manually creating threads
on each client request for server-based applications such as ASP.NET applications
and Web services.

Consider using asynchronous calls if you have work that is not CPU bound that
can run in parallel with the call. For example, this might include disk I/O bound
or network I/O bound operations such as reading or writing files, or making calls
to another Web method.

You can use the infrastructure provided by the .NET Framework to perform
asynchronous operations by calling the Beginsynchronous and Endsynchronous
methods (where synchronous represents the synchronous method name). If this
asynchronous calling pattern is not an option, then consider using threads from the
CLR thread pool. The following code fragment shows how you queue a method to
run on a separate thread from the thread pool.

WaitCallback methodTarget = new WaitCallback(myClass.UpdateCache);
bool isQueued = ThreadPool.QueueUserWorkItem(methodTarget);

Avoid Blocking Threads
Any operation that you perform from an ASP.NET page that causes the current
request thread to block means that one less worker thread from the thread pool is
available to service other ASP.NET requests. Avoid blocking threads.
Avoid Asynchronous Calls Unless You Have Additional Parallel Work
Make asynchronous calls from your Web application only when your application
has additional parallel work to perform while it waits for the completion of the
asynchronous calls, and the work performed by the asynchronous call is not CPU
bound. Internally, the asynchronous calls use a worker thread from the thread pool;
in effect, you are using additional threads.
At the same time that you make asynchronous I/O calls, such as calling a Web
method or performing file operations, the thread that makes the call is released so
that it can perform additional work, such as making other asynchronous calls or
performing other parallel tasks. You can then wait for completion of all of those tasks.

Making several asynchronous calls that are not CPU bound and then letting them run
simultaneously can improve throughput. 284 Improving .NET Application Performance and Scalability

More Information
For more information about ASP.NET threading and asynchronous communication,
see “ASP.NET Pipeline: Use Threads and Build Asynchronous Handlers in Your
Server-Side Web Code” at http://msdn.microsoft.com/msdnmag/issues/03/06/Threading
/default.aspx.

No comments:

Shared Cache - .Net Caching made easy

All information about Shared Cache is available here: http://www.sharedcache.com/. Its free and easy to use, we provide all sources at codeplex.

Facebook Badge