Sunday, October 14, 2012

ASP.NET and IIS


New requests are received by HTTP.sys, a kernel driver.  HTTP.sys posts the request to an I/O completion port on which IIS listens.  IIS picks up the request on one of its thread pool threads and calls into ASP.NET where ASP.NET immediately posts the request to the CLR ThreadPool and returns a pending status to IIS.  Next the request is typically executed, although it can be placed in a queue until there are enough resources to execute it.  To execute it, we raise all of the pipeline events and the modules and handlers in the pipeline work on the request, typically while remaining on the same thread, but they can alternatively handle these events asynchronously.  When the last pipeline event completes, the response bytes are sent to the client asynchronously during our final send, and then the request is done and all the context for that request is released.  

In case you're curious, the IIS thread pool has a maximum thread count of 256.  This thread pool is designed in such a way that it does not handle long running tasks well.  The recommendation from the IIS team is to switch to another thread if you’re going to do substantial work, such as done by the ASP.NET ISAPI and/or ASP.NET when running in integrated mode on IIS 7

The standalone ASP-NET worker process (IIS 5.0 and ASP.NET 1.0)





Captured by the IIS executable listening on port 80, an HTTP request was mapped to an IIS extension (named aspnet_isapi.dll) and then forwarded by this component to the ASP.NET worker process via a named pipe. As a result, the request had to go through a double-stage pipeline: the IIS pipeline first and the ASP.NET runtime pipeline next

 The IIS Native Worker Process (IIS 6.0)


IIS 6.0 comes with a predefined executable that serves as the worker process for a bunch of installed applications sharing the same application pool. Application pools are an abstraction you use to group multiple Web applications under the same instance of an IIS native worker process, named w3wp.exe.

There are essentially two distinct runtime environments: one within the IIS process and one within the application pool of any hosted ASP.NET application. The two runtime environments have different capabilities and programming models. Only resources mapped to the ASP.NET ISAPI extension are subjected to the ASP.NET runtime environment; all the others were processed within the simpler IIS machinery.

The WWW publishing service—connects client requests with hosted sites and applications. The WWW service knows how to deal with static requests (for example, images and HTML pages), as well as ASP and ASP.NET requests. For ASP.NET requests, the WWW service forwards the request to the worker process handling the application pool where the target application is hosted.
The IIS worker process loads the aspnet_isapi.dll—a classic IIS extension module—and lets it deal with the CLR and the default ASP.NET request life cycle.

When ASP.NET is hosted on IIS 6.0, the request is handed over to ASP.NET on an IIS I/O thread. ASP.NET immediately posts the request to the CLR ThreadPool and returns HSE_STATUS_PENDING to IIS. This frees up IIS threads, enabling IIS to serve other requests, such as static files. Posting the request to the CLR Threadpool also acts as a queue. The CLR Threadpool automatically adjusts the number of threads according to the workload, so that if the requests are high throughput there will only be 1 or 2 threads per CPU, and if the requests are high latency there will be potentially far more concurrently executing requests than 1 or 2 per CPU. The queuing provided by the CLR Threadpool is very useful, because while the requests are in the queue there is only a very small amount of memory allocated for the request, and it is all native memory. It’s not until a thread picks up the request and begins to execute that we enter managed code and allocate managed memory.

ASP.NET imposes a cap on the number of threads concurrently executing requests. This is controlled by the httpRuntime/minFreeThreads and httpRuntime/minLocalRequestFreeThreads settings. If the cap is exceeded, the request is queued in the application-level queue, and executed later when the concurrency falls back down below the limit.  The performance of these application-level queues is really quite miserable. If you observe that the “ASP.NET Applications\Requests in Application Queue” performance counter is non-zero, you definitely have a performance problem.

The autoConfig setting limits the number of concurrently executing requests per CPU to 12. An application with high latency may want to allow higher concurrency than this, in which case you can disable autoConfig and make the changes yourself.
An Integrated Pipeline Mode (IIS 7.0)








 A new IIS runtime environment nearly identical to that of ASP.NET. When this runtime environment is enabled, ASP.NET requests are authenticated and preprocessed at the IIS level and use the classic managed ASP.NET runtime environment (the environment centered on the managed HttpRuntime object) only to produce the response. The model that basically takes the ASP.NET pipeline out of the CLR closed environment and expands it at the IIS level. The difference now is that whatever request hits IIS is forwarded run through the unified pipeline within the application pool. Application services such as authentication, output caching, state management, and logging are centralized and no longer limited to requests mapped to ASP.NET.

The use of threads is a bit different. First of all, the application-level queues are no more.  But perhaps the biggest difference is that in IIS 6.0, or ISAPI mode, ASP.NET restricts the number of threads concurrently executing requests, but in IIS 7.5 and 7.0 integrated mode, ASP.NET restricts the number of concurrently executing requests. The difference only matters when the requests are asynchronous (the request either has an asynchronous handler or a module in the pipeline completes asynchronously). Obviously if the reqeusts are synchronous, then the number of concurrently executing requests is the same as the number of threads concurrently executing requests, but if the requests are asynchronous then these two numbers can be quite different as you could have far more reqeusts than threads.

The request is still handed over to ASP.NET on an IIS I/O thread.  And ASP.NET immediately posts the request to the CLR Threadpool and returns pending. Finally, once the request is picked up by a thread from the CLR Threadpool, we check to see how many requests are currently executing. If the count is too high, the request is queued in a global (process-wide) queue. This global, native queue performs much better than the application-level queues used when we’re running in ISAPI mode (same as on IIS 6.0).

So for IIS 7.0 integrated mode, a DWORD named MaxConcurrentRequestsPerCPU within HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0 determines the number of concurrent requests per CPU. By default, it does not exist and the number of requests per CPU is limited to 12. If you’re curious to see how much faster ASP.NET requests execute without the thread switch, you can set the value to 0. This will cause the request to execute on the IIS I/O thread, without switching to a CLR Threadpool thread.

However, and this is important, if your application consists of primarily or entirely asynchronous requests, the default MaxConcurrentReqeustsPerCPU limit of 12 will be too restrictive for you, especially if the requests are very long running. In this case, I do recommend setting MaxConcurrentRequestsPerCPU to a very high number.  In fact, in v4.0, we have changed the default for MaxConcurrentRequestsPerCPU to 5000.

As a final remark, please note that the processModel/requestQueueLimit configuration limits the maximum number of requests in the ASP.NET system for IIS 6.0, IIS 7.0, and IIS 7.5. This number is exposed by the "ASP.NET/Requests Current" performance counter, and when it exceeds the limit (default is 5000) we reject requests with a 503 status (Server Too Busy).

http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx
http://blogs.msdn.com/b/tmarq/archive/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications.aspx

Sunday, June 6, 2010

XPathDocument vs XmlDocument

XmlDocument
XPathDocument
- Based on W3C DOM Model
- Loads entire Xml in memory
- Read/Write
- Slower than XPathDocument
- Support for XPath/XSLT
- Supports both XPathNavigator and DOM interfaces
- Based on XPath Data Model
- Loads entire Xml in memory
- Read Only
- Faster than XmlDocument
- Optimized support for XPath/XSLT
- Supports only XPathNavigator interfaces


XmlDocument is based on the W3C XML DOM, which is an object model that basically covers all XML syntaxes, including low-level syntax sugar such as entities, CDATA sections, DTD, notations, etc. That's a document-centric model and it allows for full fidelity when loading/saving XML documents.

XPathDocument is based on an XPath 1.0 data model that is a read-only XML Infoset-compatible data-centric object model that covers only semantically significant parts of XML, leaving out insignificant syntax details - no DTD, no entities, no CDATA, no adjacent text nodes, only significant data expressed as a tree with seven types of nodes.

Simple and lightweight. That's why XPathDocument is a preferred data store for read-only scenarios, especially with XPath or XSLT involved.

Saturday, June 5, 2010

Reading an Xml

1. Parsing the XML 1.0 byte stream

a. XmlTextReader : Parses the XML 1.0 Byte Stream and the complexities of the XML 1.0 syntax by serving up the document as a logical-tree structure through higher-level APIs.

- Performance
- Memory
- Traversal
- Operation
- XPath
- XSLT
- Fastest
- Most efficient as only one node needs to be in memory
- Forward Only
- Read Only
- No
- No

2. Processing the Logical Tree via XML APIs

i. Streaming

a. XmlReader

- Models read an Xml as a forward-only, linear stream of nodes.
- XmlReader allows the client to pull the nodes one at a time much like the firehose cursor model in data access technology.


ii. Traversal Oriented

a. XmlNode (XmlDocument)

- Built on top of XmlReader


- Performance
- Memory
- Traversal
- Operation
- XPath
- XSLT
- 2 to 3x slower than XmlTextReader
- Loads entire Xml/Tree Structure in Memory
- Full Traversal
- Read/Write
- Yes
- No

b. XPathNavigator

- Uses a cursor model, which gives the underlying implementation more options in terms of how the tree is actually stored.

- Performance
- Memory
- Traversal
- Operation
- XPath
- XSLT
- Faster than XmlDocument
- More efficient than XmlDocument
- Full Traversal
- Read Only
- Yes
- Yes

3. Choosing which class


  • What kind of reader should I use?
    Use XmlTextReader if:
    * Performance is your highest priority and…
    * You don't need XSD/DTD validation and…
    * You don't need XSD type information at runtime and…
    * You don't need XPath/XSLT services

    Use XmlValidatingReader if:

    * You need XSD/DTD validation or…
    * You need XSD type information at runtime or…
  • Should I load the tree into memory?

    Use the DOM if:

    * Productivity is your highest priority or…
    * You need XPath services or…
    * You need to update the document (read/write)
  • XmlDocument or XPathDocument?
    * You need to execute an XSLT transformation or…
    * You want to leverage an implementation (like XPathDocument)

Sunday, May 30, 2010

Thread Synchronization

Threads need to communicate with each other in two basic situations:

1. When you have multiple threads accessing a shared resource in such a way that the resource does not become corrupt

2. When one thread needs to notify one or more other threads that a specific task has been completed

User Mode

1. Interlocked Methods

a. These methods are extremely fast and easy to use.

b. The System.Threading.Interlocked class defines a bunch of static methods that can atomically modify a variable in a thread-safe way.

 public static class Interlocked {
// Atomically performs (location++)
public static Int32 Increment(ref Int32 location);
// Atomically performs (location--)
public static Int32 Decrement(ref Int32 location);
// Atomically performs (location1 += value)
// Note: value can be a negative number allowing subtraction
public static Int32 Add(ref Int32 location1, Int32 value);
// Atomically performs (location1 = value)
public static Int32 Exchange(ref Int32 location1, Int32 value);
// Atomically performs the following:
// if (location1 == comparand) location1 = value
public static Int32 CompareExchange(ref Int32 location1,
Int32 value, Int32 comparand);
}

2. Critical Sections

A critical section is a small section of code that requires exclusive access to some shared resource before the code can execute.

Implemented in .NET using the Monitor class.

 private void SomeMethod() {
lock (this) {
// Access object here...
}
}
private void SomeMethod() {
Object temp = this;
Monitor.Enter(temp);
try {
// Access object here...
}
finally {
Monitor.Exit(temp);
}
}

3. ReaderWriterLock

There is a very common thread synchronization problem known as the multiple-reader/
single-writer problem.

a. When one thread is writing to the data, no other thread can write to the data.
b. When one thread is writing to the data, no other thread can read from the data.
c. When one thread is reading from the data, no other thread can write to the data.
d. When one thread is reading from the data, other threads can also read from the data.

Should never ever use the class.

Note : Monitor and ReaderWriterLock methods allow synchronization of threads running
only in a single AppDomain.

Kernel Mode

1. Kernel objects can be used to synchronize threads that are running in different AppDomains or in different processes.

2. Whenever a thread waits on a kernel object, the thread must always transition from user mode to kernel mode (1000 CPU cycles), causing the thread to incur a performance hit.

3. WaitHandle class is a simple class whose sole purpose is to wrap a Windows kernel object.

.NET Roadmap


Component200220032004200520062007200820092010
.NET1.01.12.03.03.53.5 SP14.0
Visual StudioVS.NETVS.NET 2003VS.NET 2005VS.NET 2008VS.NET 2010

Sunday, April 5, 2009

What's new in ASP.NET 2.0 ?

1. Webparts

There is a very nice webcast available on MSDN.

Wednesday, December 31, 2008

Microsoft Virtualization - Summary

Nice images that I copied from one of the Webcasts





1. How does licensing work for virtualization ?

To make it easy, with the DataCenter edition, you can have unlimited licenses and includes the license for the host OS.