The Microsoft .NET Framework is an integral part of Exchange 2007. Most Exchange 2007 components have been completely rewritten in managed code based on this framework. Managed code offers some significant advantages over unmanaged code, such as the ability to compile applications in real time, so that you do not worry about running your applications on different architectures or platforms. Managed code also provides the ability to manage memory efficiently. Microsoft .NET connection software uses common language runtime (CLR) to allow easier coding in different languages because they share the same runtime. Any code that you develop with a language compiler that targets the runtime is called managed code, as mentioned in Common Language Runtime Overview.
Building or compiling applications in real time has advantages, such as an increase in performance while this compilation is occurring. During the Exchange installation process, Exchange components are precompiled, which significantly increases installation time. However, the result is increased performance on the server because the initial load time will now be much less. These binaries, after being compiled, are stored in the global assembly cache (GAC) on the local computer. This precompilation process is called NGEN. For more information about NGEN, see Native Image Generator (Ngen.exe).
Exchange 2007 has other dependencies such as Windows kernel and .NET CLR memory management. This is one of the more crucial aspects of Exchange that you must monitor, because if memory is not being managed correctly or is getting severely fragmented, excessive paging could occur, causing an undesired increase in processing power, which significantly impacts overall client latencies.
Monitoring the counters in the following table can help determine if managed applications are causing excessive garbage collection. Garbage collection is essentially a way within CLR to free memory for objects that are no longer being used. If you need to free large amounts of memory over long periods of time, memory constraints are likely, either because not enough memory is available on the server or an application consumes more than its share of memory because of a memory leak. For more information about automatic memory management for CLR, see Automatic Memory Management.
Use the counters listed in the following table to help identify underlying .NET Framework issues.
|
Counter
|
Expected values
|
|---|
|
.NET CLR Memory(*)\% Time in GC
Shows when garbage collection has occurred. When the counter exceeds the threshold, it indicates that CPU is cleaning up and is not being used efficiently for load. Adding memory to the server would improve this situation.
If this counter increases to a high value, there might be some objects that are surviving Gen 1 garbage collections and being promoted to Gen 2. Gen 2 collections require a full global catalog for clean up. Add other .NET memory counters to determine if this is the case.
|
Should be below 10% on average.
|
|
.NET CLR Exceptions(*)\# of Excepts Thrown / sec
Displays the number of exceptions thrown per second. These include both .NET exceptions and unmanaged exceptions that get converted into .NET exceptions. For example, the null pointer reference exception in unmanaged code would get thrown again in managed code as a .NET System.NullReferenceException; this counter includes both handled and unhandled exceptions. Exceptions should only occur in rare situations and not in the normal control flow of the program. This counter was designed as an indicator of potential performance problems due to a large (>100 sec) rate of exceptions thrown. 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.
|
Should be less than 5% of total RPS (Web Server(_Total)\Connection Attempts/sec * .05).
|
|
.NET CLR Memory(*)\# Bytes in all Heaps
Shows the sum of four other counters: Gen 0 Heap Size, Gen 1 Heap Size, Gen 2 Heap Size, and the Large Object Heap Size. This counter indicates the current memory allocated in bytes on the GC Heaps.
These regions of memory are of type MEM_COMMIT. (For details, see Platform SDK documentation for VirtualAlloc.) The value of this counter is always less than the value of Process\Private Bytes, which counts all MEM_COMMIT regions for the process. Private Bytes minus # Bytes in all Heaps is the number of bytes committed by unmanaged objects.
Used to monitor possible memory leaks or excessive memory usage of managed or unmanaged objects.
|
Not applicable.
|