How to detect where a Memory Leak is?

2019-01-21 20:34发布

问题:

I have a large website that seems to be sucking up all the memory that is being allocated. There is nothing else on the server beside this site. Within a week it eats away the 2 gigs and requires a restart. Currently this is server 2008 32 bit using IIS 7. We are reinstalling to use 64bit and add more memory. It would be nice to be able to track down where the leaks are occurring.

So what is the best practice to tracking memory leaks?

回答1:

Run a profiler on your code.

Here are two good options:

RedGate's memory profiler

Jetbrains dotTrace

I believe both products have a free trial.



回答2:

Memory leaks in .NET are not that common, but when they happen it is most commonly due to unattached event handlers. Make sure you detach handlers, before the listeners go out of scope.

Another option is if you forget to call Dispose() on IDisposable resources. This may prevent cleanup of unmanaged resources (which are not handled by GC).

And yet another possible reason is a deadlocked finalizer. That will prevent all remaining objects in the finalizer queue from being collected.

I use WinDbg + Sos to track down leaks. The steps are as follows

  • Dump the heap and look for suspects
  • Use !gcroot to find out what is keeping the suspects alive
  • Repeat as necessary

Be aware that large memory usage may also be due to heap fragmentation. The regular heaps are compacted, but pinned objects can cause fragmentation. Also, the LOH is not compacted so fragmentation is not uncommon for LOH.

Excellent tutorials on WinDbg + sos here: http://blogs.msdn.com/tess/



回答3:

Run, don't walk, over to Tess Ferrandez's blog, If broken it is, fix it you should, which has well scripted labs dedicated to learning how to diagnose and debug crash, hang and memory issues with .NET code. She has some of the best material I've found to date to help get you started.

Commercial memory profilers such as ANTS and SciTech are excellent resources that will show what objects are in the heap, and how they are rooted. Most commercial memory profilers have the ability to load a memory 'snap' of a process (say from your production environment).

You can capture a memory 'snap' (see Snap v. Dump) using adplus.vbs or DebugDiag. Adplus is available as part of the Debugging Tools for Windows. DebugDiag will also have some rudimentary analysis (but seems to be more reliable on unmanaged code) automagically.

Monitor the Application
For an idea on what to monitor, see Improving .NET Performance and Scalability, specifically Chapter 15.

As to how to monitor, there are commercial tools available for that as well, however, every Windows machine also comes with Perfmon.exe, which can be used to record relevant performance counters.

Test the Application
For an idea on how to perform load, or stress, tests, check out the Patterns and Practices Performance Testing Guidance for Web Applications.

Debug the Application
Once you've identified you've got a problem (monitoring) and your able to reproduce the problem (testing) you can get down to debugging the problem. See the links for Tess - that information will carry you a long way.

Then rinse and repeat! :)

Good luck!
Z



回答4:

In performance monitor, add counters for Process/Private Bytes and .NET CLR Memory/# Bytes in All Heaps. Private bytes is all memory and CLR memory is just managed. So if the CLR memory remains fairly even but the private bytes continues to grow over time, this means that the leak is in unmanaged resource. That usually means that you are not disposing of native resources properly. A good thing to look at is stuff like COM or IO (streams and files). Make sure all of that stuff gets disposed when you are done with it.



回答5:

You can try using profilers such as dotTrace -- set it into a memory trace and run your application.

This should give you clues in which assemblies and areas of the application that eat up too much memory on the get go.



回答6:

This is probably prevention rather then detection, but at the c# code level, you should check that any classes that use large resources such as images and other files are correctly implementing the dispose pattern. If needed you may also need to override the finalizer.

MSDN has good guidance on this subject.

If you have any classes in your application that you know make use of large resources, these are the first places to look for memory issues.



回答7:

I've found that the EQATEC Profiler is pretty good, plus it's free!



回答8:

Check out the Memory and Memory Leak labs on this blog post:

.NET Debugging Demos

They may be of some help. Basically, you can use WinDBG to analyze a memory dump and help determine what is eating up all of your memory.

We used a similar approach to determine that Regex was chewing up all of our memory, but only when the product was run on 64-bit machines. The learning curve is kind of steep, but WinDBG is a very powerful tool.



回答9:

This new article of mine maybe useful: How to detect and avoid memory and resources leaks in .NET applications



回答10:

Do you do any Office interop? If so, make sure you clean up your application objects. That's one possible culprit.

Another is global objects, such as anything that's static.



回答11:

Do you have lots of dynamic pages on your site?

You can also try IBM's Purify

I suggest you try with a small set of dynamic pages disabling all others for the meantime. I hate to say this but it's very much possible that IIS 7 may also have leaks.



回答12:

Look at this article on detecting .NET application memory leaks and related articles mentioned at the bottom of the page and hopefully you will find a solution or at least an idea to resolve it.

Thanks