How to detect memory leak .NET WPF or GC long run?

I have the following very strange situation and problem:

  • .NET 4.0 chart editing application (WPF).

  • It works fine on my PC: 8 GB of RAM, 3.0 GHz, i7 quad-core.

  • When creating objects (mainly diagram and connector nodes, as well as all information about undo / redo), the TaskManager shows, as expected, some memory usage "jumps" (up and down).

  • These mem-usage "transitions" also remain executable after the user interaction is complete. Maybe this is cleaning / reorganizing the GC memory?

  • To find out what was going on, I used the Ants mem profiler, but to some extent it prevents such "jumps" after interacting with the user.

PROBLEM: it Freezes / Hangs after seconds or minutes of using my beta testers (with a frequency of 2 GHz and less than 2 GB of RAM) in some slow / weak laptos / netbooks. I was thinking about a memory leak, but ...

EDIT 1: In addition, there is a case where memory usage is growing and growing to crash (only on slow machines).

  • In Windows XP Mode (VM in Win 7) with only 512 MB of RAM, Assigned works fine without the use of "jumping" memory after interacting with the user (without clearing GC ?!).

EDIT 2: The problem is worse when other heavy programs are running on the system (for example, Visual Studio, Office and web pages are open). Even the first character of a chart cannot be created when memory usage takes off like a rocket into space (hundreds of MB consumed in seconds). Anyone with a similar experience? what were the strategies?

So, I have really big problems, because I can’t reproduce the error, I only see this strange behavior (memory transitions), and the tool that should show me what is happening hides the problem (for example, the “observer paradox”).

Any ideas on what's going on and how to solve it?

EDIT 3: This screenshot of the Ants memory profiler shows that huge ram consumption (in crescendo) if from unmanaged resources.

enter image description here

But, what can consume so much memory, so fast ?? !!!

+6
source share
3 answers

This suggests that you are probably creating a lot of “garbage” - basically, creating and allowing many objects to quickly get out of scope, but which take a lot of time to get into Gen1 or Gen2. This puts a lot of stress on the GC, which in turn can cause freezes and freezes on many systems.

To find out what was going on, I used the Ants mem profiler, but to some extent it prevents such "jumps" after interacting with the user.

The reason this profiler (ANTS), in particular, can mask this behavior is because it forces a full GC every time you take a memory snapshot. This would give the impression that there is no “memory leak” (since this is not), but does not show the total memory pressure in the system.

A tool like PerfView can be used to examine the behavior of the GC at runtime. This will help you keep track of the number of GCs that are occurring and the state of your application at that point.

+3
source

What you are describing is completely normal behavior for a .NET program, there is no indication that something is wrong with your code.

The biggest problem is that TaskMgr.exe is not a very good program to tell you what is going on in your process. It displays the "working set" for the process, a number that has very little to do with the amount of memory that the process uses.

A working set is the amount of RAM your process is using. Each process receives 2 gigabytes of virtual memory for use with code and data. Even on your virtual XP field with 512 MB of RAM. However, all of these processes require only a certain amount of RAM. On a small machine, which may be just a gigabyte.

Obviously, when you start several processes, each with a gigabyte of virtual memory with a gigabyte of real memory acquires some magic. What is provided by the operating system, Windows virtualizes RAM. In other words, it creates an illusion for every process that it launches independently on a machine with 2 gigabytes of RAM. This is done using the swap function, when the process must read or write memory, the operating system captures a piece of RAM to provide physical memory.

Inevitably, it must take some RAM from another process so that it can be accessed by you. Everything that was previously in this fragment of RAM must be preserved. What the swap file does, it saves the contents of RAM that has been unloaded.

Obviously, this does not work for free, the disks are rather slow, and the search engine is an expensive operation. This is why weak machines do not work well when you ask them to run several large programs. The real measure for this is also visible in TaskMgr.exe, but you must add it. Open + Select columns and check "Page fault defect". Observe this number during the process. When you see a splash, you can expect your program to slow down dramatically, and the displayed memory usage will change quickly.

Addressing your observations:

creating objects ... TaskManager shows, as expected, memory usage "jumps"

Yes, you are using RAM, so the working set is increasing.

These mem-usage transitions also continue to be executed AFTER user interaction is complete.

There is no slam dunk, but other processes get more time to execute, using RAM in turn and knocking out some of yours. Check the delta page error column.

I used the Ants mem profiler, but to some extent it prevents such "jumps" after interacting with the user.

Yes, memory profilers focus on using the real memory of your program, in the form of virtual memory. They largely ignore the working set, there is nothing you can do about it, and the number is pointless because it really depends on what other processes are working.

there is a case where memory usage is growing and growing to collapse

This may be a side effect of the garbage collector, but it is not typical. You probably just see Windows clipping your working set, popping out pages so you don't consume too much.

In Windows XP Mode (virtual machine in Win 7) with 512 MB of RAM Assigned works fine

Most likely, because you did not install any large programs on this WM that would compete for RAM. XP was also designed to work well on machines with very little memory, it is smooth on a machine with 256 MB. This definitely does not apply to Vista / Win7, they were designed to use modern hardware. Aero's specialty is sweet candy, but very expensive.

The problem is worse when the system has other heavy programs that run

Yes, you compete with other processes that require a large amount of RAM.

Even the first character of a chart cannot be created when memory usage takes off like a rocket

Yes, you see how pages are displayed in RAM, reloaded from the page file and ngen-ed.ni.dll files. Quick increase in working set. You will also see that the number of page error delta numbers reaches a maximum.

So, your WPF program just consumes a lot of memory and needs horse power to work well. This is not easy to fix; rather drastic redesign is required to reduce resource requirements. Therefore, just put the system requirements on the box, this is absolutely normal.

+5
source

It's hard to know exactly what happens without seeing your code, but here are a few tips:

Firstly, some information about the garbage collector. The most important thing to know is that the GC is not deterministic; you cannot know when it will work. Even a call to GC.Collect () is just a suggestion, not a command. The Gen0 heap is for locally localized objects and is collected frequently. If an object survives in the Gen0 collection, it will be moved to the Gen1 heap. After a while, the Gen1 heap will be assembled, and if the object survives, it moves to the Gen2 heap, which is less likely to be collected. For this reason, you can see a saw blade pattern in the memory graph if you select a lot of objects that fall into a bunch of Gen1 or Gen2.

Using a tool such as Process Explorer , examine the size of managed heaps (Gen0, Gen1, Gen2 and a bunch of large objects) and find out where the memory is stored. If you have a lot of short objects (a bunch of Gen1), think about a way to reuse memory instead of reallocating - something like an object pool works well for this.

Also, try comparing the total size of the heap managed with the shared private bytes of your application. Private bytes include both managed and unmanaged memory allocated by your application. If there is a big difference between the size of the managed heap and the private byte, it is likely that your application distributes unmanaged objects (through graphic objects, streams, etc.) that are not getting correctly. Look for objects that implement IDisposable but do not have a Dispose () call.

Another problem might be heap fragmentation. If you are an application that allocates large objects that it cannot fit into the current heap, it will request more memory from the OS. The solution to avoid this is to allocate smaller chunks or memory or allocate them in consecutive blocks rather than randomly (I think the array is against a linked list). A tool like the ANTS Memory profiler should be able to tell you that this is happening.

The @ReedCopsey PerfView (or its predecessor CLR Profiler) recommendation is good and will give you a better idea of ​​how your memory is allocated.

+2
source

Source: https://habr.com/ru/post/912552/


All Articles