Microsoft .NET

Version 1

    This template assesses the status and overall performance of Microsoft .NET using Windows Performance Counters.


    Prerequisites: WMI access to the target server.

    Credentials: Windows Administrator on the target server.

    Monitored Components

    Note: You need to set thresholds for counters according to your environment. It is recommended to monitor counters for some period of time to understand potential value ranges and then set the thresholds accordingly. For more information, see http://knowledgebase.solarwinds.com/kb/questions/2415.

     

    Exception Thrown / sec

    This counter returns the total number of managed exceptions thrown per second. As this number increases, performance degrades. Exceptions should not be thrown as part of normal processing. Note, however, that Response.Redirect, Server.Transfer, and Response.End all cause a ThreadAbortException to be thrown multiple times, and a site that relies heavily upon these methods will incur a performance penalty. If you must use Response.Redirect, call Response.Redirect(url, false), which does not call Response.End, and hence does not throw. The downside is that the user code that follows the call to Response.Redirect(url, false) will execute. It is also possible to use a static HTML page to redirect. Microsoft Knowledge Base Article 312629 provides further detail. This monitor should be as low as possible. You must compare this monitor with Requests / sec. Values greater than 5 % of Requests / sec should be investigated, and a new threshold should be set as necessary.


    Filters / sec

    This counter returns the number of .NET exception filters executed per second. An exception filter evaluates regardless of whether an exception is handled. This counter is not an average over time; it displays the difference between the values observed in the last two samples divided by the duration of the sample interval.


    Number of CCWs

    This counter returns the current number of COM callable wrappers (CCWs). A CCW is a proxy for a managed object being referenced from an unmanaged COM client. This counter indicates the number of managed objects referenced by unmanaged COM code. This value must be as low as possible. If this number is high, determine whether you can redesign this part of the application to reduce the number of transitions needed. If you see memory expanding (or not becoming freed when it should have been) and this counter is increasing, this may suggest that unmanaged code is holding on to some of your managed objects, thereby causing memory either not being freed or increasing.


    Number of Stubs

    This counter returns the current number of stubs created by the common language runtime. Stubs are responsible for marshaling arguments and return values from managed to unmanaged code, and vice versa, during a COM interop call or a platform invoke call. This value has to be lower as much as possible. But for calls being made from managed and un-managed and vice-versa, this counter gives an indication to the interaction between COM and managed code. There is always a performance penalty for such interactions.


    Time in Jit (%)

    This counter returns the percentage of elapsed time spent in JIT (just-in-time) compilation since the last JIT compilation phase. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled. This counter should be less than 10%. There can be spikes at this counter but those are acceptable.


    IL Bytes Jitted / sec

    This counter returns the number of MSIL (Microsoft Intermediate Language) bytes that are JIT-compiled per second. This counter is not an average over time; it displays the difference between the values observed in the last two samples divided by the duration of the sample interval. A high value for this performance counter indicates performance overhead. The JIT is a runtime optimizing compiler. You can consider improving the startup time of client applications by compiling your application at install time, using the
    NGEN.exe utility.

    Bytes in Loader Heap

    This counter returns the number of bytes committed by the class loader across all AppDomains. This counter should reach a steady state. If this counter is continuously increasing, monitor the "Current Number of Assemblies" counter. There may be too many assemblies loaded per AppDomain.


    Current Number of Application Domains

    This counter returns the current number of AppDomains loaded in the process. The value of this counter should be the same as the number of Web applications plus 1. The additional AppDomain is the default domain.


    Current Number of Assemblies

    This counter returns the current number of assemblies loaded in the process. By default, ASPX and ASCX files in a directory are "batch" compiled. This typically yields one to three assemblies, depending upon dependencies. For example, if there are ASPX pages with parse-time dependencies on ASCX files, two assemblies will typically be generated. One will contain the ASPX files, the other ASCX files.

    Occasionally, excessive memory consumption is caused by an unusually large number of loaded assemblies. For example, a site that displays news articles will perform better using a small set of ASPX files that obtain the news from a database than it would were a single ASPX file used for each article. Site designers should attempt to generate content dynamically, make use of caching, and reduce the number of ASPX and ASCX pages.

    Assemblies cannot be unloaded from an AppDomain. To prevent excessive memory consumption, the AppDomain is unloaded when the number of re-compilations (ASPX, ASCX, ASAX) exceeds the limit specified by <compilation numRecompilesBeforeAppRestart=/>. Note that if the <%@ page debug=%> attribute is set to true, or if <compilation debug=/> is set to true, batch compilation is disabled.


    Current Number of Classes Loaded

    This counter returns the current number of classes loaded in all assemblies. If this value is too high, consider increasing the physical memory to improve performance.


    Current Logical Threads

    This counter returns the number of current managed thread objects in the application. This counter is not an average over time; it just displays the last observed value. This counter maintains the count of both running and stopped threads. A value that is too high may be a cause of concern.


    Current Physical Threads

    This counter returns the number of native operating system threads created and owned by the common language runtime to act as underlying threads for managed thread objects. This counter's value does not include the threads used by the runtime in its internal operations; it is a subset of the threads in the operating system process. A value that is too high indicates performance bottlenecks. If this value is too high, try to refactor the code to reduce the number of spawned threads to an optimal value.


    Current Recognized Threads

    This counter returns the number of threads that are currently recognized by the runtime; they have a corresponding .NET thread object associated with them. These threads are not created by the CLR. They are created outside the CLR, but have since run inside the CLR at least once. Only unique threads are tracked. Threads with same thread ID re-entering the CLR or recreated after thread exit are not counted twice.


    Contention Rate / sec

    This counter returns the rate at which threads in the runtime unsuccessfully attempt to acquire a managed lock. Sustained nonzero values should cause concern. If this number is increasing, a bottleneck exists in the code. This area in the code is synchronized, so only one thread at a time enters it, but it is being "hammered" by multiple threads that are all attempting to get into this piece of code. To resolve this bottleneck, find this piece of code and determine how you can avoid this situation.

    Current Queue Length

    This counter returns the total number of threads that are currently waiting to acquire a managed lock in the application. You may want to run dedicated tests for a particular piece of code to identify the average queue length for the particular code path. This helps you identify inefficient synchronization mechanisms.


    Number of Bytes in All Heaps

    This counter returns the sum of the Gen 1 Heap Size, Gen 2 Heap Size, and Large Object Heap Size counters. This counter indicates the current memory allocated in bytes on the garbage collection heaps. The value of this counter is always less than the value of Process/Private Bytes, which also includes the native memory allocated for the process by the operating system. If this counter continues to rise, there is a managed leak. Some managed objects are always being referenced and are never collected.


    Number of GC Handles

    This counter returns the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment.


    Time in GC (%)

    This counter returns the percentage of elapsed time that was spent performing a garbage collection since the last garbage collection cycle. This counter usually indicates the work done by the garbage collector to collect and compact memory on behalf of the application. This counter is updated only at the end of every garbage collection. This counter is not an average; its value reflects the last observed value. Lower the value in the range of 5-10% is an acceptable value. There can be spikes at this counter but those are acceptable. There is a temporary suspension of all the threads during this activity. Hence there is a performance overhead we incur. Allocating large strings to cache, heavy string operations etc leave a lot of memory spaces that the GC has to clean up. Avoid such operations.


    Total Runtime Checks

    This counter returns the total number of runtime code access security checks performed since the application started. Runtime code access security checks are performed when a caller demands a particular permission. The runtime check is made on every call by the caller and examines the current thread stack of the caller. When used with the Stack Walk Depth counter, this counter indicates the performance penalty that occurs for security checks.

    Note: By default, this monitor has the Count statistic as difference box checked. It will only show the new number of requests since the last polling period.

     

    Portions of this document were originally created by and are excerpted from the following sources:

    Microsoft TechNet, “TechNet Library,” Copyright © 2012 Microsoft Corporation.  All rights reserved.
    Available at
    http://technet.microsoft.com/en-us/library/9tyc2s04(v=VS.80).aspx.