C # large byte array and memory leak if not fast

I have a class that has an array of bytes containing from 1,048,576 bytes to 134,217,728 bytes. In dispose void, I have a null array, and after that the method calls the GC.Collect call.

If I leave immediately, I will regain my memory, but if I wait 10 hours and leave, the memory usage will not change.

+4
source share
3 answers

Memory usage is based on OS memory allocation. He may be released immediately, may not be. It depends on the use of the OS, application, etc. You free it at runtime, but that does not mean that the OS always returns it. I should think that this is a definition based on memory patterns (i.e. Time is here) that affects this calculation of when to return it or not. This has been reviewed here:

Explicit memory deallocation in C #

+5
source

Note: if the memory is not released, it does not automatically mean that it is being used. It is up to the CLR whether it frees memory or not, but this memory was not wasted.

However, if you want a technical explanation, you will want to read litterature about the big heap of objects: http://msdn.microsoft.com/en-us/magazine/cc534993.aspx p>

In principle, this is a memory zone where very large objects are allocated (more than 85 KB). It differs from other memory zones in that it never compacts and, therefore, can become fragmented. I think what happens in your case:

  • Case 1: you select an object and immediately call GC.Collect. The object is allocated at the end of the heap, then freed. The CLR sees a free segment at the end of the heap and frees it in the OS.

  • Case 2: you select an object and wait a while. At the same time, another object is highlighted in LOH. Now your object is not the last. Then, when you call GC.Collect, your object is erased, but another object remains at the end of the memory segment. Therefore, the CLR cannot free memory for the OS.

Just an assumption based on my knowledge of memory management in .NET. Maybe I'm wrong.

0
source

Your results are not unusual, but that does not mean that everything is wrong. To be compiled, something must prompt the GC to compile (often an attempt). As a result, you can create an application that consumes a bunch of memory, frees it up, and then stays idle. If there is no memory pressure on the machine, and if your application does not try to do something after that, the GC will not work (because it is not necessary). Once you are busy, GC will begin to do its job. This behavior is often mistaken for a leak.

BTW: Do you use this very large array more than once? If so, you might be better off keeping it around and reusing it. Reason: any object larger than 85,000 bytes is allocated in a bunch of large objects. This heap only gets GC'd in Generation 2 collections. Therefore, if you often allocate and redistribute arrays, you will invoke many Gen 2 collections (expensive).

(note: this does not mean that there is a hard and fast rule for reusing large arrays, but if you are doing a lot of allocation / deallocation / allocation of the array, you should measure how much this helps if you are reusing).

0
source

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


All Articles