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?
- DLLs loaded into the process
- mapped files
- .NET IL code that gets compiled
- the default process heap
- stack
- TEB (thread environment block) and PEB (process environment block)
- C++ heaps if you do P/Invoke or similar stuff
- direct calls to VirtualAlloc()
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.