Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# large byte array and memory leak if not nulled quickly

Tags:

c#

I have a class that has a byte array holding from 1,048,576 bytes up to 134,217,728 bytes. In the dispose void I have the array set to null and the method calling the dispose calls GC.Collect after that.

If I dispose right away I will get my memory back, but if I wait like 10 hours and dispose, memory usage doesn't change.

like image 308
jasonbay13 Avatar asked Nov 28 '11 16:11

jasonbay13


2 Answers

Memory usage is based on OS memory allocation. It may be freed immediately, it may not be. This depends on OS utilization, application, etc. You free it in the runtime, but this doesn't mean the OS alway gets it back. I have to think heres a determination based on memory patterns (ie time here) that affects this calculation of when to return it or not. This was addressed here:

Explicitly freeing memory in c#

like image 173
Adam Tuliper Avatar answered Oct 13 '22 21:10

Adam Tuliper


Note: if the memory isn't released, it doesn't automatically means it used. It's up to the CLR whether it's releases chuncks of memory or not, but this memory isn't wasted.

That said, if you want a technical explanation, you'll want to read litterature about the Large Object Heap: http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

Basically, it's a zone of memory where very large objects (more than 85kB) are allocated. It differs from the other zones of memory in that it's never compacted, and thus can become fragmented. I think what happens in your case is:

  • Case 1: you allocate the 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 releases it to the OS.

  • Case 2: you allocate the object and wait for a while. In the mean time, an other object is allocated in the LOH. Now, your object isn't the last one anymore. Then, when you call GC.Collect, your object is erased, but there's still the other object(s) at the end of the memory segment. So the CLR cannot release the memory to the OS.

Just a guess based on my knowledge of memory management in .NET. I may be completely wrong.

like image 23
Kevin Gosse Avatar answered Oct 13 '22 19:10

Kevin Gosse