See inline
Willy.
MuZZy said:
Well, calling GC.Collect just asks GC to "please collect as soon as
possible" which can be minutes...
NO, this is not true, calling GC.Collect is honoured as soon as the GC is
able to kick in, that is when managed code is at a GC safe point, I hope
your code doesn't spend minutes to reach a safe point
.
Unfortunately all this dancing around GC doesn't help in many cases. We
had a weird problem with dramatically increasing memory thought we were
releasing all datasets and arrays and profiler was saying it's ok, so we
finally came up with a solution:
Calling this function will "shake" your avail memory which does really
help - you going to see an immidiate used memory drop.
This is not a solution, because there is no problem, "dramatic increase" of
memory means what in terms of free memory? Does your application or other
applications running in the system suffer from a lack of memory?
If the answer to this question is NO, well, don't call GC.Collect or don't
trim the Working Set of your application.
If the answer is yes, run a memory profiler and look at your memory
allocation patterns, take a close look at your containers like Datasets,
Arraylists etc..., they are so easy to use but he! they come at a price and
they are largely overused, the result is that .NET applications are known to
be memory hungry. Right, .NET makes it possible to build windows
applications real fast, but to build well designed and well performing (in
terms of performance and resource consumption) is just as hard as any other
development platfom, with one exception, the time you win during development
can now be spent for designing and testing etc....
bool bTipAction = true;
public static void SetWorkingSet()
{
//Needs Admin rights on the machine
try
{
System.Diagnostics.Process loProcess =
System.Diagnostics.Process.GetCurrentProcess();
if(m_bTipAction == true)
{
loProcess.MaxWorkingSet = (IntPtr)((int)loProcess.MaxWorkingSet - 1);
loProcess.MinWorkingSet = (IntPtr)((int)loProcess.MinWorkingSet - 1);
}
else
{
loProcess.MaxWorkingSet = (IntPtr)((int)loProcess.MaxWorkingSet + 1);
loProcess.MinWorkingSet = (IntPtr)((int)loProcess.MinWorkingSet + 1);
}
m_bTipAction = !m_bTipAction;
}
catch(System.Exception)
{
}
}
What you are doing is realy bad, just like calling GC.Collect without having
any serious reason, reducing the working set is just as bad (well actually
worse). Don't fool yourself in thinking that your application uses less
memory because you reduced the WS, all you did is throw away (valuable?)
pages from memory (to the paging file). The result is that you disturb the
OS memory manager and pager, also you are inducing a lot of hard page faults
whenever a paged file has to be brought back into the working set. Worse you
disturb the GC even more when doing this, think what happens if pages from
the managed heap are paged-out, when the GC runs it has to reaload all the
pages from the paging file to perform a scan.
Funny that people are so paranoid about memory consumption these days, while
they don't seem to understand (or measure) the impact on other resources
when trying to play fast and loose with things that are much better left to
the OS and the GC itself to be done.