banner



How To Find Memory Leaks In Net Application

Anyone who worked on a large enterprise project knows memory leaks are like rats in a big hotel. You might not notice when there are few of them, just y'all always have to be on guard in case they overpopulate, break into the kitchen, and poop on everything.

Finding, Fixing and learning to Avert Memory Leaks is an important skill. I'll list 8 best practice techniques used past me and senior .Internet developers that advised me for this commodity. These techniques will teach you lot to find when at that place's a memory leak trouble in the application, to observe the specific memory leak and to fix it. Finally, I'll include strategies to monitor and report on memory leaks for a deployed program.

Defining Memory Leaks in .Net

In a garbage collected surround, the term memory leaks is a scrap counter intuitive . How can my retentiveness leak when there's garbage collector (GC) that takes care to collect everything?

There are 2 related core causes for this. The kickoff core crusade is when you take objects that are still referenced but are effectually unused. Since they are referenced, the garbage collector won't collect them and they volition remain forever, taking up memory. This tin can happen, for example, when you register to events but never unregister.

The 2nd crusade is when you somehow allocate unmanaged memory (without garbage collection) and don't free it. This is not so hard to do. .NET itself has a lot of classes that allocate unmanaged retentiveness. Almost anything that involves streams, graphics, the file organisation or network calls does that nether the hood. Commonly, these classes implement aDispose method, which frees the memory (nosotros'll talk about that later). Yous can hands allocate unmanaged retention yourself with special .NET classes (similar Marshal) or PInvoke (at that place's an example of this further on).

Let's motility on to my best practice techniques list:

If you lot go to Debug | Windows | Prove Diagnostic Tools, you'll come across this window. If you lot're like me, y'all probably saw this tool window after installing Visual Studio, closed it immediately, and never idea of it again. The Diagnostic Tools Window tin can be quite useful though. It can easily assist y'all detect 2 problems: Retention Leaks and GC Force per unit area.

When you have Retentiveness Leaks, the Process Retentiveness graph looks like this:

Yous can run across with the yellow lines coming from the tiptop that the GC is trying to complimentary retentiveness, but it nonetheless keeps rising.

When you accept GC Pressure, the Procedure Retention graph looks similar this:

GC Pressure is when you are creating new objects and disposing of them too quickly for the garbage collector to keep up. As you see in the picture show, the retention is close to its limit and the GC bursts are very frequent.

You won't be able to find specific memory leaks this way, only you tin detect that you have a retentivity leak problem, which is useful by itself. In Enterprise Visual Studio, the Diagnostics Window also includes a congenital-in memory profiler, which does allow to notice the specific leak. We'll talk near memory profiling in best practice #iii.

2. Detect Retentiveness Leak problems with the Chore Manager, Process Explorer or PerfMon

The second easiest style to detect major memory leak problems is with the Task Director or Process Explorer (from SysInternals). These tools can bear witness the amount of memory your procedure uses. If it consistently increases over time, you lot probably accept a memory leak.

Task manager memory measuring

PerfMon is a chip harder to use but can show a nice graph of your memory usage over time. Here'southward a graph of my awarding that endlessly allocates memory without freeing it. I'm using the Process | Private Bytes counter.

Perfmon private bytes graph

Notation that this method is notoriously unreliable. You might have an increase in memory usage just because the GC didn't collect information technology yet. At that place'south likewise the matter of shared memory and private retentivity, then you can both miss memory leaks and/or diagnose retentivity leaks that aren't your own (explanation). Finally, you might error retentivity leaks for GC Pressure. In this example, you don't have a memory leak just you lot create and dispose of objects so fast that the GC doesn't keep up.

Despite the disadvantages, I mention this technique because information technology's both easy to utilise and sometimes your only tool. Information technology's also a decent indicator something is wrong when observing for a very long flow of fourth dimension.

3. Use a memory profiler to find retentiveness leaks

A memory profiler is like the Chef's Knife of treatment memory leaks. It'south the main tool to discover and fix them. While other techniques can be easier to use or cheaper (profiler licenses are costly), information technology'southward best to be skillful past with at least one memory profiler to finer solve retentivity leak problems.

The big names in .NET memory profilers are: dotMemory, SciTech Retentiveness Profiler and ANTS Memory Profiler. At that place's also a "gratuitous" profiler if you have Visual Studio Enterprise.

All memory profilers work in a similar mode. You can either attach to a running process or open a Dump file. The profiler volition create a Snapshot of your process' current retentiveness heap. You tin can analyze the snapshot in all kinds of ways For example, here's a list of all the allocated objects in the current snapshot:

dotMemory Object Set

You can see how many instances of each type are allocated, how much memory they take, and the reference path to a GC Root.

A GC Root is an object which the GC can't costless, so anything that the GC root references also tin't exist freed. Static objects and the local objects in the current agile Threads are GC Roots. Read more in Understanding Garbage Collection in .Net.

The quickest and most useful profiling technique is to compare ii snapshots where the retention should return to the aforementioned state. The get-go snapshot is taken earlier an operation, and another snapshot is taken after the operation. The exact steps are:

  1. Beginning with some kind of Idle state in your application. This could be the Main Menu or something similar.
  2. Take a snapshot with the Memory profiler by attaching-to-process or saving a Dump.
  3. Run an operation where you lot suspect a memory leak is created. Return to the Idle state at the terminate of it.
  4. Take a second snapshot.
  5. Compare both snapshots with your memory profiler.
  6. Investigate the New-Created-Instances, they are probably memory leaks. Examine the "path to GC Root" and attempt to understand why those objects weren't freed.

Here's a keen video where 2 snapshots are compared in SciTech retentiveness profiler and the memory leak is found:

4. Utilise "Make Object ID" to find memory leaks

In my last article 5 Techniques to avoid Retentivity Leaks by Events in C# .Cyberspace you lot should know I showed a technique to find a memory leak by placing a breakpoint in the grade Finalizer. I'll testify yous a similar method here that's even easier to use and doesn't require code changes. This one utilizes the Debugger's Make Object ID feature and the Immediate Window.

Suppose y'all suspect a certain course has a memory leak. In other words, you suspect that after running a certain scenario, this class stays referenced and never collected past the GC. To observe out if the GC actually collected it, follow these steps:

  1. Place a breakpoint where the instance of the class is created.
  2. Hover over the variable to open the debugger's data-tip, then right-click and use Make Object ID. You can type in the Immediate Window $1 to see that the Object ID was created correctly.
  3. Terminate the scenario that was supposed to free your example from references.
  4. Force GC drove with the known magic lines

v. Blazon $1 again in the immediate window. If it returns null, and then the GC collected your object. If not, you have a memory leak.

Here's me debugging a scenario that has a memory leak:

And here's me debugging a similar scenario that doesn't accept a memory leak:

You can force garbage collection in the end by typing the magic lines in the immediate window, making this technique a fully debugging experience, with no need to change code.

Of import: This exercise doesn't work well in .Cyberspace Core 2.Ten debugger (issue). Forcing garbage collection in the same telescopic as the object allotment doesn't free that object. You can do information technology with a little more than effort by forcing garbage collection in another method out of scope.

5. Beware of mutual retention leak sources

There's always a risk of causing a memory leak, merely there are certain patterns that are much more than likely to practise so. I suggest to be extra careful when using these, and proactively cheque for retention leaks with techniques like the terminal best practice.

Here are some of the more than mutual offenders:

  • Events in .Internet are notorious for causing memory leaks. You can innocently subscribe to an event, causing a damaging memory leak without even suspecting. This subject is and then of import that I dedicated an entire commodity to it: 5 Techniques to avert Memory Leaks by Events in C# .Internet yous should know
  • Static variables, collections, and static events in-item should ever await suspicious. Call up that all static variables are GC Roots, so they are never collected by the GC.
  • Caching functionality – Any type of caching mechanism can easily cause memory leaks. By storing cache information in-memory, eventually, it will make full and cause an OutOfMemory exception. The solution tin can exist to periodically delete older caching or limit your caching amount.
  • WPF Bindings tin be dangerous. The rule of thumb is to always bind to a DependencyObject or to a INotifyPropertyChanged object. When you fail to do so, WPF will create a potent reference to your binding source (meaning the ViewModel) from a static variable, causing a retentiveness leak. More information on WPF Binding leaks in this helpful StackOverflow thread
  • Captured members – It might be articulate that an Event Handler Method means an object is referenced, only when a variable is Captured in an anonymous method, then it'south as well referenced. Hither's an case of a memory leak:
  • Threads that never terminate – The Alive Stack of each of your threads is considered a GC Root. This means that until a thread terminates, any references from its variables on the Stack volition not be collected by the GC. This includes Timers equally well. If your Timer'southward Tick Handler is a method, then the method'southward object is considered referenced and will not be nerveless. Here'southward an case of a retention leak:

For more on this bailiwick, check out my commodity 8 Ways You can Crusade Retentiveness Leaks in .NET.

6. Use the Dispose design to preclude unmanaged memory leaks

Your .NET application constantly uses unmanaged resources. The .Cyberspace framework itself relies heavily on unmanaged code for internal operations, optimization, and Win32 API. Anytime you lot use Streams, Graphics, or Files for case, you lot are probably executing unmanaged code.

.Cyberspace framework classes that utilize unmanaged code normally implement IDisposable. That's because unmanaged resources need to exist explicitely freed, and that happens in the Dispose method. Your only chore is to remember and call the Dispose method. If possible, use the using statement for that.

The using statement transforms the code into a attempt / finally argument behind the scenes, where the Dispose method is chosen in the finally clause.

Just, fifty-fifty if you lot don't call the Dispose method, those resource will be freed because .NET classes use the Dispose Pattern. This basically ways that if Dispose wasn't called before, it's called from the Finalizer when the object is garbage collected. That is, if yous don't have a retentivity leak and the Finalizer really is called.

When you're allocating unmanaged resources yourself, then you definitely should use the Dispose pattern. Here's an example:

The point of this pattern is to permit explicit disposal of resources. But besides to add a safeguard that your resources volition be disposed during garbage collection (in the Finalizer) if the Dispose() wasn't chosen.

The GC.SuppressFinalize(this) is besides of import. It makes sure the Finalizer isn't chosen on garbage collection if the object was already disposed. Objects with Finalizers are freed differently and much more costly. The Finalizer is added to something called the F-Reachable-Queue, which makes the object survive an additional GC generation. There are also other complications.

7. Add together Memory Telemetry from Code

Sometimes, you might want to periodically log your retentiveness usage. Perchance you suspect your production Server has a memory leak. Peradventure yous desire to take some action when your memory reaches a certain limit. Or perchance you're only in the adept habit of monitoring your memory.

There's a lot of data we can get from the app itself. Getting electric current memory in-use is equally simple equally:

For more information, you can use the PerformanceCounter grade that's used for PerfMon:

Information from any perfMon counter is bachelor, which is plenty.

You can get even deeper though. CLR MD (Microsoft.Diagnostics.Runtime) allows y'all to inspect your electric current memory heap and become any possible information. For example, yous can impress all the allocated types in memory, including instance counts, paths to roots and then on. You pretty much got a memory profiler from code.

To become a whiff of what y'all can achieve with CLR Physician, cheque out Dudi Keleti'southward DumpMiner.

All this information tin can be logged to a file, or even amend, to a telemetry tool like Awarding Insights.

viii. Test for memory leaks

It's a neat practice to proactively test for memory leaks. And information technology's not that hard. Hither's a short pattern you can use:

For more in-depth testing, memory profilers similar SciTech's .NET Memory Profiler and dotMemory provide a testing API:

Summary

Don't know about you, just my new year's day's resolution is: Better memory management.

I hope this mail service gave you some value and I'd love information technology if y'all subscribe to my web log or go out a comment below. Any feedback is welcome.

Enjoy the weblog? I would love you lot to subscribe! Performance Optimizations in C#: 10 Best Practices (exclusive article)

Desire to become an good problem solver? Check out a chapter from my book Practical Debugging for .NET Developers

Source: https://michaelscodingspot.com/find-fix-and-avoid-memory-leaks-in-c-net-8-best-practices/

Posted by: benitohoure1990.blogspot.com

0 Response to "How To Find Memory Leaks In Net Application"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel