I am doing a lot of work with clients and internal teams that are running software services for weeks and even months at a time and who end up needing assistance in understanding why a particular process or service is gradually consuming more and more memory. Anyone who has been active in supporting application will immediately recognize that Performance Monitor is your best bet (perfmon).

So to avoid repeating myself a dozen time I thought I could list the steps here:

  1. Hit Windows Key + R to bring up the Run dialog box.
  2. Type in perfmon and hit Enter.
  3. Open the Data Collector Set and right click on the User Defined folder.
  4. On the context menu select New->Data Collector Set.
  5. In the dialogue box define an appropriate Name, select the Create manually (Advanced) option, and click Next.
  6. On the next screen enable Performance counter option only and click Next.
  7. Add the following Performance counters for your process(s):
    • Process->YourProcess
      • Private bytes
    • .NET CLR memory->YourProcess
      • # of Bytes all Heaps
      • Gen 0 heap size
      • Gen 1 heap size
      • Gen 2 heap size
      • Large Object Heap size
  8. Modify both the Sample interval and the Units as appropriate and hit Next.
  9. Select the Root directory where you would like to save collector set and hit Next.
  10. Update what security context the data collector set should Run as, select the Open properties for this data collector set and hit Finish.
  11. In the properties dialogue box select the Schedule tab to determine when data collection should stop and start. Alternatively right click on the data collector set and hit Start for immediate collection.

Here are the definitions of the counters you are likely to be most interested in:

Private bytes indicate the amount of memory that the process executable has asked for but not necessarily the amount it is actually using. There is no way to tell whether a change in private bytes was due to the executable itself, or due to a linked library.

# of Bytes all Heaps displays 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.

Gen 0 heap size displays the maximum bytes that can be allocated in generation 0; it does not indicate the current number of bytes allocated in generation 0.

Gen 1 heap size displays the current number of bytes in generation 1; this counter does not display the maximum size of generation 1. Objects are not directly allocated in this generation; they are promoted from previous generation 0 garbage collections. This counter is updated at the end of a garbage collection, not at each allocation.

Gen 2 heap size displays the current number of bytes in generation 2. Objects are not directly allocated in this generation; they are promoted from generation 1 during previous generation 1 garbage collections. This counter is updated at the end of a garbage collection, not at each allocation.

Large Object Heaps size displays the current size, in bytes, of the Large Object Heap. Objects that are greater than approximately 85,000 bytes are treated as large objects by the garbage collector and are directly allocated in a special heap; they are not promoted through the generations. This counter is updated at the end of a garbage collection, not at each allocation.