GC.GetTotalMemory(false) and Process.WorkingSet
After running my .net process for a long time, I see there's a big difference between the memory GC is aware of and the process working set.
The values I'm monitoring are GC.GetTotalMemory(false) and Process.WorkingSet.
If I check in the "task manager" (or using a SysInternals tool) the value of WorkingSet (Process) and what's shown in "task manager" don't match, but they're somehow close (let's say, 100mb in task manager, 130 in WorkingSet), but what's shocking for me is that GC.GetTotalMemory(false) is like 40Mb or so.
I've run several times through profilers (my favorite is ants memory profiler from redgate), and there it is easy to check that there's a value called "free memory" which is normally the difference between what GC "sees" and what the OS sees (ok, plus loaded DLLs and so on).
A couple of questions:
Is there a way to programmatically monitor this "GC free memory". Yes, I could use the profiler, but in a long running process is not that easy.
If your process runs for a long time, allocates a lot of memory and then frees it (and allocation means thousands or millions of objects, not as simple as a big allocation an开发者_StackOverflow中文版d free), the problem is that it will never "shrink" to a low value, despite of the fact that GC values are low and correct. Is there a way to fix this? It could be that something is broken on my process but it has been profiled several times over the years and it doesn't seem to be a leak.
Thanks
Just to resurrect an ancient thread, if you want to monitor "GC free memory"
, you can periodically make a call to GC.GetTotalMemory(false)
and store the value. Dump it to disk or a database or something. Alternatively you can use a library like prometheus-net
(https://github.com/prometheus-net/) which will export this and a whole bunch of metrics for you.
As for your second question, there is a way to force your application to shrink, but it's not dot net native, it's windows only, and it's NOT recommended:
[DllImport("psapi.dll")]
static extern int EmptyWorkingSet(IntPtr hwProc);
static void MinimizeFootprint()
{
EmptyWorkingSet(Process.GetCurrentProcess().Handle);
}
From what little I know I think the OS will take care of this if the server is under memory pressure, and it's more efficient for your app, and for the server in general, if the memory remains allocated to your process. This is because there's a good chance it will need it again in the future, so there's no point in cleaning it up when it will just have to allocate it again, especially when your server has enough memory.
精彩评论