Tim Anderson's ITWriting

How much memory does my .NET application use?

 

Want to reproduce this article?

If you would like to reproduce this article on your own publication or web site, please contact Tim Anderson .

How much memory does my .NET application use?

Many developers are surprised by the high memory usage that Task Manager reports for their .NET application. But is Task Manager giving misleading information? By Tim Anderson.

picture of Delphi sqlite application

Here's what happens when you minimize a Windows application: Working Set drops dramatically, but Private Bytes stays flat.

 

If you search back through .NET discussion groups you’ll see many conversations like this. Newcomer to .NET says: “I’ve just been looking at Task Manager. Why does my simple VB.NET Windows application use 12MB RAM?” The answer comes back, “Don’t worry. The app doesn’t really use that much RAM; Windows will give it back if other apps need it. Minimize your application and you’ll see how little it really needs.” Newcomer minimizes the app, and sees the Mem Usage reported go down to say 750K. You don’t even need to minimize it: if you execute the API call SetProcessWorkingSetSize with -1,-1 arguments, then Windows will trim the working set immediately.

However, the point that needs emphasizing is that the minimized figure is just as misleading as Task Manager’s figure. Here’s my high-level understanding of how it works. What Task Manager reports is called the Working Set. This is the amount of physical RAM allocated to the process. To complicate matters, some of the memory in the Working Set may be shared with other processes, including parts of the .NET runtime. Therefore, there is double counting in Task Manager’s mem usage column. Windows may also allocate additional memory to the process in case it may be needed later. For these reasons, the Working Set may overstate the real memory requirements of the application.

It can work the other way too. When you trim the Working Set, Windows not only trims unneeded memory from the allocation, but also pages memory to disk where possible. The Working Set does not include memory paged to disk. In this case, the Task Manager figure understates the real memory requirements.

If you’ve not done so before, try this experiment. Fire up Performance Monitor (Start – Run – Perfmon). Then start up your .NET application. Note the Mem Usage figure in Task Manager. Then go to Perfmon, right-click the list of counters at the bottom of the right-hand pane and choose Add counters. In the Add counters dialog, choose Process under Performance object. In the Instances list, select your .NET application. In the Counters list, select Private Bytes and choose Add. Then select Working Set and choose Add. Close the dialog.

In Perfmon, you can get the current value of a counter by selecting it in the list. You’re likely to find that the Working Set value is higher than the Private Bytes value, and matches the value in Task Manager. Bear in mind that Task Manager reports Kilobytes, while Perfmon shows a decimal value. Now minimize the .NET application. The figure for Working Set drops like a stone, but Private Bytes remains the same, typically much higher. Now Task Manager has changed from pessimist to optimist. See the illustration above.

So what are these Private Bytes? This is memory allocated to the process that cannot be shared by other processes. It is probably the most useful single figure when you want to know “How much memory does my app use?” It still needs qualification. As we’ve seen, the Private Bytes may not all be in physical memory. If they are swapped to disk, and the user isn’t actively using the application, then they aren’t having much impact on other applications.

Here are a few further observations.

First, Windows generally does a good job of memory management. High figures in Task Manager needn’t concern the user if the system is running well.

Second, .NET applications really do have a high memory footprint relative to most native code applications (Java has the same problem). This isn’t too important on systems with plenty of RAM, but becomes a major issue in constrained environments like Terminal Server or Citrix clients.

Third, don’t use the mem usage column in Task Manager for diagnostics or profiling. Use the Perfmon counters, especially Private Bytes and the specific .NET counters that will reveal problems like memory leaks.

Fourth, what really counts is performance and user satisfaction. Memory usage is one of many factors that make up performance, and it’s important to keep it in perspective. Keep an eye on the available physical memory on Task Manager's Performance tab; if this reports hundreds of MB free, your .NET app is not really stressing the system.

Finally, there isn't much developers can do about the memory footprint of the .NET runtime. That's down to Microsoft, and it will be interesting to see how .NET 2.0 compares when it comes out of beta. However, there is a lot that developers can do to make applications that use memory efficiently and avoid leaks. This mostly involves looking at the .NET counters rather than the system counters. Use of a profiler is near-essential; I like the SciTech one listed below.

Links

.NET Allocation profiler

MSDN article on evaluating memory usage

SciTech memory profiler

Blog article on CLR performance troubleshooting - by the lead developer in Microsoft's CLR performance team,

Copyright Tim Anderson 10th March 2005. All rights reserved.

Copyright ©2004 Tim Anderson


 
 
17 comments
Comment posted on 2010-03-19 09:22:04 by: Mrinal.
Hello,

I am not sure if things are exactly the way you have mentioned, since I have seen in my application Private Bytes value far more than Working Set (through Perfmon).

As far as I can understand from your article Private Bytes should be the subset of the Working Set, but that doesn;t seems to be the case.

Any clue why ?

thnaks,

Mrinal

Comment posted on 2009-08-29 07:30:02 by: Rustle.
100 MG is my application is it too heavy in desktop ?
Comment posted on 2009-02-13 23:32:02 by: kasbaba.
Hi,

The tutorial provided was very helpful and helped me understand why my application always showed 12-14MB usage in the Task Manager.
However, some users claim that their systems have started running slowly after my Software was installed.
I was hoping that there might some tweaking that I can do to make it fast; but I think there is nothing much we can do as far as the memory management is concerned since most of it is managed by the Garbage Collector of .NET.
Thanks once again.

kasbaba

Comment posted on 2009-02-06 20:05:44 by: Andres.
Great article
Comment posted on 2009-02-03 13:07:20 by: Mag Studios.
Wow What a Great Article i found very informative! knowledge from this article in Software development when using .Net

Thanks
MAG Studios
mag-corp.com


Comment posted on 2008-07-07 15:40:22 by: Abhisek.
Thanks for this good article.
Comment posted on 2008-04-11 18:03:57 by: Onur.
Good article, good insight. However there's another issue unrelated to memory usage. Many and heavy .NET-based apps are too small-sized even less than 100kb, although they have hundreds(nearly thousands) of codelines. C apps and non-NET apps which do the same job cost much more disk space.

My humble understanding is that .NET apps are looking into assemblies through CLR at launch, then all of the framework is responsible of keeping classes / assemblies, thus .NET app's classes are not built-in therefore they cost very few space.

I'd like to know a brief explanation of small disk space cost issue of .NET applications if possible.

Regards,

Onur

Comment posted on 2008-01-24 22:37:00 by: Ash.
Quote:
Comment posted on 2005-11-20 10:03:18 by: Anon.
I have been running a desktop application that is taking over 150M of RAM using a lot of graphics. However according to .NET memory coutners all heaps take about 20M, the working size as you said simply does not matter and private bytes are 150M. So where is the memory? Does it make sense for .NET CLR to take 130M of RAM, and the APP Data to take 20M of ram? Where is the memory? the .NET CLR counters are much lower then the private bytes. I can't make sense of it? how do I reduce private bytes?


---

Check it is not creating lots of instances on the heap, i.e. reference types, especially without using the IClonable interface. Each ref type on the heap which is still 'valid' will not be touched by the GC therefore pile up mem usage.

Ash

Comment posted on 2007-12-21 23:02:56 by: LISEK.
elo

Comment posted on 2006-01-26 15:17:10 by: Balaji.
Ad Brian said,
"""VM Szie in Task Manager's display (choose View | Select Columns... and choose Virtual Memory Size)""" doesnt exits.

Balaji

Comment posted on 2006-01-06 12:38:29 by: Unknown.
Hi Brian, doesn't VM size denote the Page Memory size. As far as I know, Virtual memory is the page memory. How can it be equal to Private Bytes. Because Private Bytes denote a completely different counter. They might have been equal by co-incidence, but that's not the case always.
Comment posted on 2006-01-05 15:53:15 by: gurvin.
Brian, thats a good one. But the real use of Perfmom is to monitor .net related process like garbage collection, threading, JIT but I really don't know how to make sense of this data, still searching for related articles......
Comment posted on 2005-11-20 10:03:18 by: Anon.
I have been running a desktop application that is taking over 150M of RAM using a lot of graphics. However according to .NET memory coutners all heaps take about 20M, the working size as you said simply does not matter and private bytes are 150M. So where is the memory? Does it make sense for .NET CLR to take 130M of RAM, and the APP Data to take 20M of ram? Where is the memory? the .NET CLR counters are much lower then the private bytes. I can't make sense of it? how do I reduce private bytes?

Comment posted on 2005-07-14 19:57:13 by: Aws.
Great and Simple blug...
Used it to record the mem of my .net app over 1 day using counter log

Comment posted on 2005-03-22 10:48:08 by: Morpheus.
Thanks for this good article :)


Comment posted on 2005-03-16 16:06:04 by: Tim Anderson.
Thanks Brian, though I reckon it's still worth getting to know PerfMon - pretty graphs, and many more counters available.

Tim

Comment posted on 2005-03-16 15:40:07 by: Brian Long.
Whilst it is true that Mem Usage in Task Manager is the same as Working Set in PerfMon, it is also true that VM Size in Task Man is the same as Private Bytes in PerfMon.

In other words, you can cut out the PerfMon step, with all the messing around adding counters, by simply adding VM Szie in Task Manager's display (choose View | Select Columns... and choose Virtual Memory Size)

- Brian

Comments are closed.