Environment.WorkingSet incorrectly reports memory usage
Environment.WorkingSet incorrectly reports the memory usage for a web site that runs on Windows 2003 Server.(OS Vers: Microsoft Windows NT 5.2.3790 Service Pack 2, .NET Vers: 2.0.50727.3607)
It reports memory as Working Set(Physical Mem.): 1952 MB (2047468061).
Same web site runs locally on Windows Vista with a Working Set(Physical Mem.): 49 MB (51924992).
I have limited access to the server and support is so limited :(. so i have computed the total memory by traversing with VirtualQuery. Tota开发者_StackOverflow社区l of pages with state: MEM_FREE is 1300 MB. (I guess server have 4 GBs of RAM and PAE is not enabled, max user mode virtual address is 0x7fff0000.)
So, i know working set is not only about virtual memory. But, is it normal to have such a high working set while its very low on another machine?
I think the problem is related to what is described in this article:
MAY 04, 2005
Fun with the WorkingSet and int32
I finally found an honest to goodness bug in the .NET framework.... the WorkingSet returns the amount of memory being used by the process as an integer (32 bit signed integer). OK, so the maximum value of an integer is 2,147,483,647 -- which is remarkably close to the total amount of memory that a process can have in its working set.
... There is actually a switch in Windows that will allow a process to use 3 gig of memory instead of 2 gig. This switch is often turned on when dealing with Analysis Services -- this thing can be a memory hog. So now what happens is that when I poll the WorkingSet I get a negative number, a really big negative number. Usually, in the realm of -2,147,482,342.
... The problem was the overflow bit.
Working set is returned to the .NET framework as a binary value. The first bit of an integer is the sign bit. 0 is positive, 1 is negative. So, when the value turned from (binary) 1111111111111111111111111111111 to (binary) 10000000000000000000000000000000 the value goes from 2147483647 to -2147483647.
OK, so I still have to fix this. Here is what I came up with (in C#):
long lWorkingSet = 0; if (process.WorkingSet >= 0) lWorkingSet = processWorkingSet; else lWorkingSet = ((long)int.MaxValue*2)+process.WorkingSet;
Hopefully that fixes the problem for now.
The real question will come in down the road. Microsoft knows about this problem. I still have find out how they are going to fix this for Win64...where this trick will no longer work.
http://msdn2.microsoft.com/library/0aayt1d0(en-us,vs.80).aspx:
There's gonna be a Process.WorkingSet64 variable, and they're deprecating WorkingSet.On a tangent, though, I thought it was impossible for a managed process to come near the 3gb limit, because the runtime splits the memory into multiple heaps. Is this not true?
At a guess, Environment.WorkingSet
is probably returning the value from GetProcessWorkingSetSize
, which is basically what has been set with SetProcessWorkingSetSize
. It's basically whatever the system has picked as the largest working set size it would like to see for this process, not necessarily anything to do with how much memory it's actually using. The basic effect is that when/if the process uses more memory than that, the system's working set trimmer goes to work seeing if it can get some of its memory paged out to disk.
精彩评论