Welcome to AddressOf.com Sign in | Help

.NET Application Memory Flush via Interop - Revisited

As I've stated before, I do make mistakes ;-)

I have an application that I've written for my employer that appears, under certain *unidentified* circumstances to have a very slow memory leak.  While trying to narrow down where it could be, I pulled one of my components out to test it with a console interface as a harness (to reduce the amount of outside memory being used) and leveraging the CLR Profiler (free) and the .NET Memory Profiler (14 day eval) to see what is happening.  One of the things making this difficult, since I'm trying to look at native memory as well, is the effect that the framework has on the application and Windows reporting memory consumption.  So I decided to add the memory flush method that I posted back in November 2003 to the mix.  Even though I had several warnings around that code posting, there was one that wasn't stated.  Although it does do what is says, on the surface, there is a slight bloating effect inherent to it as well.  In addition, it's seriously overkill since it's forcing a garbage collection.  Here is an updated code listing:

Public Class MemoryManagement
 
  Private Declare Function SetProcessWorkingSetSize Lib "kernel32.dll" ( _
    ByVal process As IntPtr, _
    ByVal minimumWorkingSetSize As Integer, _
    ByVal maximumWorkingSetSize As Integer) As
Integer

 
Public Shared Sub FlushMemory()
    'GC.Collect()
    'GC.WaitForPendingFinalizers()
    If (Environment.OSVersion.Platform = PlatformID.Win32NT)
Then
      Dim p As
Process = Process.GetCurrentProcess

     
SetProcessWorkingSetSize(p.Handle, -1, -1)
      p.Dispose
    End
If
 
End
Sub

End
Class

The problem with the previous version is that the GetCurrentProcess was creating a reference to a Process that was staying in memory until it's finalizers would run during a GC0 (Garbage Collection level 0).  By adding in the Dispose, you are removing the bloat by specifically telling the framework to release (what appears to be) the un-managed reference to a Process.  Again, this wasn't that big of a deal since we are talking about a relatively small amount of memory, but still... it was wrong... now it's right ;-)

As for forcing the GC, I don't really think that it is necessary in order to get Windows to see the “true” memory consumption as described in the previous article.  Also, it's just not good .NET practice to do so... so it's been removed. 

Also, due to these modifications, the warnings in the previous article are no longer relevant... since we aren't forcing a GC.  The only warning now is the fact that you are using P/Invoke and have to adhere to whatever restrictions doing so incur.

Published Thursday, February 24, 2005 2:13 PM by CorySmith
Filed under: , ,

Comments

# Interesting finds this week

Saturday, February 26, 2005 10:04 AM by Jason Haley
Interesting finds this week

# re: .NET Application Memory Flush via Interop - Revisited

Thursday, January 19, 2006 11:10 AM by manus
How does .net application de-allocated(releases) memory create by a callled unmanaged dll. That is when .nat calling a un managed dll by passing string byref and then the dll allocating memory to this.

# re: .NET Application Memory Flush via Interop - Revisited

Wednesday, March 01, 2006 10:41 PM by Mark Howard
Thank you so much for this bit of code. I've been pulling my hair out and this solved my problem instantly.

# re: .NET Application Memory Flush via Interop - Revisited

Tuesday, May 23, 2006 7:19 AM by Sam
Amazing how the amount of memory drops down from 22,000K to 3,000K!

thank you so much; you've really solved my problem.

# re: .NET Application Memory Flush via Interop - Revisited

Sunday, August 05, 2007 7:42 AM by Craig
You are THE Man! This solution completely solves my memory leak issue. I've spent ages searching and thinking of a solution and this really hits the spot! Cheers Craig
Anonymous comments are disabled