.NET WinForm Memory Consumption
I've been profiling a WinForm's application using ".NET Memory P开发者_C百科rofiler".
I can't quite seem to understand how my application is growing to 1GB, then 2GB, then 3GB of usage - according to windows task manager.
The private bytes using that tool, and "Total Bytes in All Heaps" shows only as 70MB or so. At the top of my list of instances hanging around, they are mostly String, or WeakReferences to lots of little objects.
All the application is doing is showing a form that loads data from a database. I repeat the show/dispose cycle of the form about 100 times and the growth is continuous.
I've tried about 3 memory profiling tools now and none of them are showing me where this enormous amount of memory consumption is coming from.
Can anyone help or take a guess as to what it might be?
Thanks.
Is this a known issue for VB.NET apps?
Yes. It is a side-effect of Edit + Continue support compiled into the executable. It is affected by any event that is declared with the WithEvents keyword. A WeakReference keeps track of those event instances. Problem is, those WeakReferences are leaked if you run the app without a debugger. The rate at which the process consumes memory is highly dependent on how many instances of the class get created. The leak is 16 bytes per event per object.
The workaround is simple, do not use the Debug build of your app without a debugger. Only use the Release build. And of course, only ship the Release build to your customer.
I can't quite seem to understand how my application is growing to 1GB, then 2GB, then 3GB of usage - according to windows task manager.
That's because the counter from task manager is the "working set" as Tess Ferrandez points out in this article
There is another counter called working set which simplified consists of how much memory is in the memory pages that are currently or was recently touched by threads in the process or approximately, how much of the memory that is used by the process is currently in RAM. The working set counter might be interesting if you have issues with too much paging and many processes on the same box competing about the RAM, but in order to determine how much memory you are using (reserved or committed) it offers little or no help.
From the MSDN article on working set (Emphasis mine)
Working Set
The set of memory pages (areas of memory allocated to a process) recently used by the threads in a process. If available memory on the server is above a specified threshold, pages remain in the Working Set of a process even if they are not in use. When available memory falls below a specified threshold, pages are removed from the Working Set. If these pages are needed, they will be returned back to the Working Set before they leave main memory and are made available for other processes to use.
I have found that under high CPU load that the garbage collection often gets a very low priority so the .NET libraries responsible for cleaning up unused memory will only fire off when they absolutely have to, in spite of the reference counts to a managed object going to zero. If it's possible try putting some intentional Thread.Sleep calls in your code or simply accept the fact that it's a memory hog and hope that the logic will allow your system to run and it will have "odd" memory usage as you never stated that anything breaks, it just has an unreal memory footprint.
精彩评论