Memory Not Release for Array asignment in Mono (C#) - c#

In my C# program i have function that in it, i create array of Byte with length of 1000000 and when the function executed , memory show 1MB increase in memory usage.
The problem is here, after returning from function , 1MB memory that allocated in function does not release , WHY????

Garbage collector doesn't free up memory right away but
Garbage collection occurs when one of the following conditions is true:
The system has low physical memory. This is detected by either the low memory notification from the OS or low memory indicated by the host.
The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This threshold is continuously adjusted as the process runs.
The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs continuously. This method is primarily used for unique situations and testing.
You can find more here.

Related

garbage collection after a local method in C#

I'm a beginner in C#, just a question on garbage collection in C#. Let's say we have the following code:
...
public void Test()
{
...
MyClass a = new Myclass()
}
so when will a be garbage collected by CLR? I mean immediately garbage collected after Test() method gets executed? or when the program finishes?
Running this code will not let you control or know when the garbage collection will run, there are a number of conditions that will trigger the garbage collection:
Conditions for a garbage collection
The system has low physical memory. This is detected by either the low
memory notification from the OS or low memory indicated by the host.
The memory that is used by allocated objects on the managed heap
surpasses an acceptable threshold. This threshold is continuously
adjusted as the process runs.
The GC.Collect method is called. In almost all cases, you do not have
to call this method, because the garbage collector runs continuously.
This method is primarily used for unique situations and testing.
More information: Conditions for a garbage collection / learn.microsoft.com
Answer from : https://www.codeproject.com/Articles/1095402/Garbage-Collection-and-Csharp
When GC Gets Triggered?
There are no specific timings for GC to get triggered, GC automatically starts operation on the following conditions:
When virtual memory is running out of space.
When allocated memory is suppressed acceptable threshold (when GC found if the survival rate (living objects) is high, then it increases the threshold allocation).
When we call GC.Collect() method explicitly, as GC runs continuously, we actually do not need to call this method.
Unlike in other languages, c# manages itself to clean up most resources for you. As you can read in other answers, resources are freed, when the GC detect's that they are not needed anymore and he has the time to do it. But if you really need to trigger this manually, you can use the GC.Collect() Method.
If you are interested in freeing unmanaged resources (files, connections, unmanaged code, basically everything that is not controlled by the CLR) you should have a look into the dispose-pattern. Usually you would Implement the IDisposable interface. But there are really many handsome approaches to this, to also free unmanaged resources, even if Dispose() doesn't get called by the code. Have a look at this.

Visual Studio 2017 - Diagostic tool - Heap profiling affects program memory consumption

I am trying to debug strange memory leak in C# application (uses c++/cli and c++) using Diagnostic tool and Memory usage snapshots. But i have discovered one strange problem.
When I run debug in VS2017 with Heap Profiling turned on memory consumption is constant and program runs as expected. When Heap Profiling is turned off program leaks memory which has linear increase. Work completed is same, i have progress of work printed in console and I am sure both programs have made the same work, but one uses constant memory and other has linearly increasing memory (when same work done 2x memory used). Visually it looks like when GC is fired with Heap Profiling some memory gets released, and no memory is released when Heap Profiling is not used.
Does anyone have idea how could Heap Profiling affect this? Native memory is leaked.
[EDIT1] Data from Performance Profiler -> Memory usage
Object Type Reference Count Module
shared_ptr_cli<GeoAtomAttributes> TestBackEnd64.dll
shared_ptr_cli<GeoAtomAttributes> [Finalization Handle] 856,275 TestBackEnd64.dll
shared_ptr_cli<GeoAtomAttributes> [Local Variable] 1 TestBackEnd64.dll
GeoAtomAttributesCli [Local Variable] 1 TestBackEnd64.dll
Memory that can be relased with gc should not be considered as leaked memory, it should be considered as memory that is eligible for garbage collection. Because the next time gc is performed this memory will be collected and available for new object allocations.
Other thoughts;
Gc runs on managed heap, native libraries allocates memory on the native heap. So It cannot effect the memory management of native libraries. But you should be aware of the following cases.(this might not be your case though)
If you pass pinned data structures to native code and free these handles on your Object.Finalize method (of wrapper class); in this case the pinned memory can only be collected when wrapper class is queued for finalization.Calling cleanup functions(*) of native code in the finalize method of managed class can also cause similar cases. I think these are bad practices and should not be used, instead these cleanups should be done as soon as possible.
(*) This case might cause your total process memory consumption to bloat even when there is no need for gc in the managed heap.

Should garbage collection have run by now?

I have had a C# application running for the past few weeks. When I first started it, it had ~10000K memory usage. Since then, I've checked and it's at a ~20000K memory footprint.
I don't know .Net garbage collection very well, but is this a sign that I definitely have a memory leak? Shouldn't the GC have run by now?
I've read into garbage collection here:
https://msdn.microsoft.com/en-us/library/ee787088(v=vs.110).aspx
And they have the following conditions for when GC should run:
The system has low physical memory. (I have well over 70000K of memory left to use, so this shouldn't be triggered)
The memory that is used by allocated objects on the managed heap
surpasses an acceptable threshold. This threshold is continuously
adjusted as the process runs. (how do you define "acceptable" threshold?)
Shouldn't I expect GC to have run in a few weeks timespan?
Shouldn't I expect GC to have run in a few weeks timespan?
Nope, you shouldn't expect GC.Collect to occur in timely manner.
Garbage collection occurs when one of the following conditions is
true:
The system has low physical memory.
The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This threshold is continuously
adjusted as the process runs.
The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs
continuously. This method is primarily used for unique situations
and testing.
Read this for more fundamental details.

Why this memory management trick works?

Refers to this Unity documentation and go to section
Large heap with slow but infrequent garbage collection
var tmp = new System.Object[1024];
// make allocations in smaller blocks to avoid them to be treated in a special way, which is designed for large blocks
for (int i = 0; i < 1024; i++)
tmp[i] = new byte[1024];
// release reference
tmp = null;
The trick is to pre-allocate some memory chunks at the program start.
Why does this trick work?
Are the chunks being somekind of "registered" (or "bound") to the application when they are being pre-allocated, so that even though the tmp is being freed when Start() is finished, the OS still treat these chunks as "registered" to the application?
Since the chunks are "registered" to the application, so the heap size of the application is expanded to certain size, and the next time it acquires memory chunk, the OS would just pick it from the heap of this application.
Is my explanation correct? No matter Yes or No could someone please explain in more details, thanks.
It's not really a trick. It's the way that parts of Unity3D handle memory.
In Unity3D you have objects that are handled by Mono and will be garbage collected, and objects that are handled by Unity, that will not be garbage collected. Strings, ints etc are cleaned up by Mono automatically and we do not have to worry about this. Texture(2D)s etc are not, and we have to dispose of these objects manually.
When a request for memory is made the first thing that happens is that the memory manager scans the application's currently allocated memory from the OS for a chunk large enough to store the data you are requesting. If a match is found, that memory is used. If a match is not found, then the application will request additional memory from the OS in order to store your data. When this data is no longer used up it is garbage collected, but the application still retains that memory. In essence, it sets a flag on the memory to say it is 'usable' or re-allocatable. This reduces the requests for memory made to the OS by never returning it.
What this means is two things;
1) Your application's memory will only continue to grow, and will not return memory to the OS. On mobile devices this is dangerous, as if you use too much memory your application will be terminated.
2) Your application may actually be allocated way more memory than it actually needs. This is due to fragmented memory. You may have 10MB of available memory in your application's memory pool, but non of those chunks are large enough to house the data you need to store. Therefore, it is possible that the application will request more memory from the OS because there is not a single piece of contiguous memory available that can be used.
Because you're creating a large object, an therefore requesting memory, when you set that object to null and signal to the garbage collector that memory is no longer needed by the application, it is quicker to reallocate that kept memory to other objects rather than requesting additional memory from the OS. It is this reason why in theory this particular method is fast and will result in less performance spikes as the garbage collector is invoked less often. Especially as this is a large, contiguous memory allocation.
Why does this trick work?
This trick works because the application won't return memory to the OS, unless the OS memory manager is low and explicitly requests them to do so, in which then they will free up as much as possible. There is an assumption that once the memory is allocated, it will be needed again. If it is already allocated, there is no reason to return it back to the OS, unless it really needs to use it.

Who is responsible for C# memory allocation?

What part of the .NET framework takes responsibility to allocate memory. Is it GC?
It is the CLR but in close cooperation with the GC. And the GC is a part of the CLR so it's not such a clear division.
Allocation takes place at the start of the free section of the Heap, it is a very simple and fast operation. Allocation on the Large Object Heap (LOH) is slightly more complicated.
Do Visit http://www.codeproject.com/Articles/38069/Memory-Management-in-NET
Allocation of Memory
"Generally .NET is hosted using Host process, during debugging .NET
creates a process using VSHost.exe which gives the programmer the
basic debugging facilities of the IDE and also direct managed memory
management of the CLR. After deploying your application, the CLR
creates the process in the name of its executable and allocates memory
directly through Managed Heaps.
When CLR is loaded, generally two managed heaps are allocated; one is
for small objects and other for Large Objects. We generally call it as
SOH (Small Object Heap) and LOH (Large Object Heap). Now when any
process requests for memory, it transfers the request to CLR, it then
assigns memory from these Managed Heaps based on their size.
Generally, SOH is assigned for the memory request when size of the
memory is less than 83 KBs( 85,000 bytes). If it is greater than this,
it allocates memory from LOH. On more and more requests of memory .NET
commits memory in smaller chunks."
Upon reading further this paragraphs, Its the CLR with the help of Windows (32bit or 64Bit) it "allocates" the memory.
The "De-allocation" is managed by GC.
"The relationships between the Object and the process associated with
that object are maintained through a Graph. When garbage collection is
triggered it deems every object in the graph as garbage and traverses
recursively to all the associated paths of the graph associated with
the object looking for reachable objects. Every time the Garbage
collector reaches an object, it marks the object as reachable. Now
after finishing this task, garbage collector knows which objects are
reachable and which aren’t. The unreachable objects are treated as
Garbage to the garbage collector."
Despite the name, many kinds of modern "garbage collectors" don't actually collect garbage as their primary operation. Instead, they often identify everything in an area of memory that isn't garbage and move it somewhere that is known not to contain anything of value. Unless the area contained an object that was "pinned" and couldn't be moved (in which case things are more complicated) the system will then know that the area of memory from which things were moved contains nothing of value.
In many such collectors, once the last reference to an object has disappeared, no bytes of memory that had been associated with that object will ever again be examined prior to the time that they get blindly overwritten with new data. If the GC expects that the next use of the old region of memory will be used to hold new objects, it will likely zero out all the bytes in one go, rather than doing so piecemeal to satisfy allocations, but if the GC expects that it will be used as a destination for objects copied from elsewhere it may not bother. While objects are guaranteed to remain in memory as long as any reference exists, once the last reference to an object has ceased to exist there may be no way of knowing whether every byte of memory that had been allocated to that object has actually been overwritten.
While .NET does sometimes have to take affirmative action when certain objects (e.g. those whose type overrides Finalize) are found to have been abandoned, in general I think it's best to think of the "GC" as being not a subsystem that "collects" garbage, but rather as a garbage-collected memory pool's manager, that needs to at all times be kept informed of everything that isn't garbage. While the manager's duties include the performance of GC cycles, they go far beyond that, and I don't think it's useful to separate GC cycles from the other duties.

Categories