none
Memory release is not happenin on GC.SupressFinalize and GC.Collect() RRS feed

  • Question

  • Hi all,

    i have used CLR profiler, .net memory profiler and ANTS profiler. In al these profiler if i take/collect snapshots all un used memory will be removed and my application memory usage in task manaer will reduce imediately.

    but when i run my application and write

    GC.Collect()

    it has no effect on mem usage in task manager even for a long hours.

    i have a simple class and loading datatable with 2 lakh rows with 15 datacolumns of type string. once datarows is added to datatabe am using

    datatable.Dispose();

    datatable = null; and GC.Collect();

    i would like to know how we can able to release un used memory imediately like how CLR/dot net memory profilers are doing and what will be the impact.

    please suggest me on this.



    vinaya kumar

    Thursday, June 7, 2012 3:10 PM

Answers

  • Hi,

    I am not sure if I understood you correctly. I understood that your problem is, that the memory usage is not going down in Taskmanager when managed memory is released.

    You have to understand how .Net applications are running.

    The Common Language Runtime is starting and allocating memory. This is the amount of memory that you see in TaskManager. Once the Runtime is up and running, it will also start the main application as a thread (Which is just one thread of many e.g. the GC is also running on a thread). Whenever the .Net application requires some memory of the managed heap, the memory management of the runtime will check if it still has enough "free" memory. If not, it allocates memory from windows. When the GarbageCollector is releasing memory, it is just the runtime that manages some memory it got from windows. But that will not release memory from the view of the TaskManager.

    But of course - if a lot of memory is deallocated internally, the runtime will free memory, too. (So we have a .Net application that takes mltiple GB during some operations and afterwards the memory is cleaned up - which is also visible inside the taskmanager. But the TaskManager only has the view, what the windows process allocated. It is not aware, what is done with the memory. (So what the runtime is doing internally e.g. managing some managed heaps is unknown for the windows taskmanager).

    Did this help a little to understand the behaviour that you saw?

    With kind regards,

    Konrad

    Thursday, June 7, 2012 3:55 PM

All replies

  • Hi,

    I am not sure if I understood you correctly. I understood that your problem is, that the memory usage is not going down in Taskmanager when managed memory is released.

    You have to understand how .Net applications are running.

    The Common Language Runtime is starting and allocating memory. This is the amount of memory that you see in TaskManager. Once the Runtime is up and running, it will also start the main application as a thread (Which is just one thread of many e.g. the GC is also running on a thread). Whenever the .Net application requires some memory of the managed heap, the memory management of the runtime will check if it still has enough "free" memory. If not, it allocates memory from windows. When the GarbageCollector is releasing memory, it is just the runtime that manages some memory it got from windows. But that will not release memory from the view of the TaskManager.

    But of course - if a lot of memory is deallocated internally, the runtime will free memory, too. (So we have a .Net application that takes mltiple GB during some operations and afterwards the memory is cleaned up - which is also visible inside the taskmanager. But the TaskManager only has the view, what the windows process allocated. It is not aware, what is done with the memory. (So what the runtime is doing internally e.g. managing some managed heaps is unknown for the windows taskmanager).

    Did this help a little to understand the behaviour that you saw?

    With kind regards,

    Konrad

    Thursday, June 7, 2012 3:55 PM
  • Hi, 

    Few of my words, 

    ICorProfilerCallBack is an profiling interface used by CLR to raise the event on certain actions which were read by code profiler. I guess while before taking snapshot profiler makes sure calling GC.Collect to take current live objects state.  When GC.Collect() occur releases unused memory by CLR and immediately releases from the process which is what you see in TaskManager.

    Strange, that you are seeing no change at memory even after hours.. I suspect you may have still referring LO (may be copy) and walkthrough with profiler and without is different.

    In common scenario this happens immediately, for eg: I created DataTable with 10000000 rows, which occupies approx 121xxxxxxx bytes of memory

    table = new DataTable();
    var column = new DataColumn("Name");
    table.Columns.Add(column);
    
    for (int i = 0; i < 10000000; i++)
    {
    	var newRow = table.NewRow();
    	newRow.SetField<string>(column, "Hello " + i);
    }

    Since, it takes more than 85000 bytes allocated at LOH (generation 2).

    now you perform

    GC.Collect();

    Debug.WriteLine(GC.GetTotalMemory(false)); //1214077868 bytes table.Dispose(); table = null; GC.Collect();

    Debug.WriteLine(GC.GetTotalMemory(false)); //236264 bytes

    After this run, I can see the change , immediately,  reducing memory in task manager.

    Also check through Performance Monitor ( select .Net CLRMemory) for your application and observe live memory change with GC calls

    Nice articles

    http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

    http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

    I hope this helps you...


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".


    • Edited by Kris444 Saturday, June 9, 2012 8:52 AM
    Saturday, June 9, 2012 8:50 AM