I do not understand the difference between Process.PrivateMemorySize64 and Process.VirtualMemorySize64
I have created a simple console application which allocates 10 times 10 megabyte into an byte array.
const int tenMegabyte = 1024*1024*10;
long allocatedMemory = 0;
List<byte[]> memory = new List<byte[]>();
for (int i = 0; i < 10; i++)
{
allocatedMemory += tenMegabyte;
Console.WriteLine("Allocated memory: " + PrettifyByte(allocatedMemory));
Console.WriteLine("VirtualMemorySize64: " + PrettifyByte(Process.GetCurrentProcess().VirtualMemorySize64));
Console.WriteLine("PrivateMemorySize64: " + PrettifyByte(Process.GetCurrentProcess().PrivateMemorySize64));
Console.WriteLine();
memory.Add(new byte[tenMegabyte]);
}
The PrivateMemorySize64 works as i did expect: It starts with a certain size, and grows with the allocated memory.
But the VirtualMemorySize64 seems to allocate a lot of memory at the very start even for a console application (180mb for 32bit and 560mb for 64bit)
Questions:
VirtualMemorySize measures all of the virtual memory that your process uses. Which includes the pages shared by all other processes on your machine. Which in a .NET program includes the operating system, CLR, jitter and the ngen-ed Framework assemblies.
PrivateMemorySize measures the virtual memory that's dedicated to your process and cannot be shared by other processes. Which in a .NET program includes all the data and any jitted code that isn't ngen-ed.
Both are virtual memory measurements, internally represented as just numbers to the processor. One each for every 4096 bytes of memory. Actual RAM usage is a very different number, represented by Process.WorkingSet. Not generally useful, it can change very rapidly when other processes require RAM and some of what you use needs to be mapped out. Both your operating system and .NET were optimized to use lots of VM, there is a lot of it available on modern machines and it beats the alternative, the disk.
Is the PrivateMemorySize part of the VirtualMemorySize? If this is true, what is the rest of the VirtualMemorySize? Is it just reserved memory, or is this actually in ram/page file?
Yes. The rest is shared memory as noted in the first paragraph
Why does even a simple console application allocate more than 500mb VirtualMemory?
Neither the operating system nor the .NET runtime is partial to your console app being small, both are still needed to execute it. Since they are shared by all processes, you don't care that much about it. Nor is there anything you can do about it. A "big" console app doesn't usually add that much more VM unless it allocates a lot of memory.
If my application use 1GB of PrivateMemorySize and 20GB of VirtualMemorySize, should i care or can this be ignored?
1GB of private memory isn't much to worry about. 20GB of VM is getting excessive. The size of the GC heap is the one to watch, collections can get slow when it has to plow through multiple gigabytes of heap.
Why does the 64bit version of the program allocate so much more VirtualMemory?
Well, 64 is 2 * 32. That doesn't quite scale like that, a 64-bit process still tends to use plenty of ints. A modern 64-bit OS was written to assume plenty of hardware resources to be available, Win8 does require 8 GB of RAM to work smoothly.
Is the PrivateMemorySize part of the VirtualMemorySize?
Yes. Everything is part of VirtualMemorySize, unless you write kernel drivers in which case you might talk about physical RAM.
If this is true, what is the rest of the VirtualMemorySize?
Is it just reserved memory, or is this actually in ram/page file?
Virtual memory can be reserved (unusable) or committed (ready for use). The reserved parts are neither in RAM nor in page file.
Why does even a simple console application allocate more than 500mb VirtualMemory?
You can look it up with a debugger, e.g. WinDbg. Here's my .NET 4.5 32 bit program (your code) on a 64 bit OS.
0:005> .loadby sos clr
0:005> !address -summary
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 59 edb72000 ( 3.714 GB) 92.86%
<unknown> 119 ceca000 ( 206.789 MB) 70.70% 5.05%
Image 222 3220000 ( 50.125 MB) 17.14% 1.22%
MappedFile 15 1b7c000 ( 27.484 MB) 9.40% 0.67%
Stack 18 600000 ( 6.000 MB) 2.05% 0.15%
Heap 12 1e0000 ( 1.875 MB) 0.64% 0.05%
Other 8 31000 ( 196.000 kB) 0.07% 0.00%
TEB 6 6000 ( 24.000 kB) 0.01% 0.00%
PEB 1 1000 ( 4.000 kB) 0.00% 0.00%
The <unknown>
part includes .NET memory. In this case it's likely only .NET, since I have no C++ or VirtualAlloc() calls.
It's also possible to see that .NET currently uses only 105 MB of those 206:
0:005> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x02741018
generation 1 starts at 0x0274100c
generation 2 starts at 0x02741000
ephemeral segment allocation context: none
segment begin allocated size
02740000 02741000 027afff4 0x6eff4(454644)
Large object heap starts at 0x03741000
segment begin allocated size
03740000 03741000 04193fe8 0xa52fe8(10825704)
04860000 04861000 05261020 0xa00020(10485792)
05990000 05991000 06391020 0xa00020(10485792)
06be0000 06be1000 075e1020 0xa00020(10485792)
07be0000 07be1000 085e1020 0xa00020(10485792)
08be0000 08be1000 095e1020 0xa00020(10485792)
09be0000 09be1000 0a5e1020 0xa00020(10485792)
0b070000 0b071000 0ba71020 0xa00020(10485792)
0c070000 0c071000 0ca71020 0xa00020(10485792)
0d070000 0d071000 0da71020 0xa00020(10485792)
Total Size: Size: 0x64c20fc (105652476) bytes.
------------------------------
GC Heap Size: Size: 0x64c20fc (105652476) bytes.
And we can see that in total, 131 MB are reserved:
0:005> !address -summary
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE 59 edb72000 ( 3.714 GB) 92.86%
MEM_COMMIT 302 a114000 ( 161.078 MB) 55.07% 3.93%
MEM_RESERVE 99 836a000 ( 131.414 MB) 44.93% 3.21%
If my application use 1GB of PrivateMemorySize and 20GB of VirtualMemorySize, should i care or can this be ignored?
You can't tell that without knowing what your process is expected to do. It's possible that you use a 3rd part DLL that makes excessive use of memory, e.g. for data analytics. Then it's ok.
In general, you should get a kind of "feeling" for your product. If the behavior changes massively, then I would start investigation.
Why does the 64bit version of the program allocate so much more VirtualMemory?
Likely because .NET does not have to worry about other things.
On 32 bit, with only 4 GB of memory, .NET needs to ensure that other DLLs can be loaded, threads can be created etc. On 64 bit, with 8 TB of memory, there will always be 1 MB left to create a new thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With