Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between VirtualMemorySize64 and PrivateMemorySize64

Tags:

c#

.net

clr

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)

32bit sample of memory allocation32bit sample of memory allocation

Questions:

  • 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?
  • Why does even a simple console application allocate more than 500mb VirtualMemory?
  • If my application use 1GB of PrivateMemorySize and 20GB of VirtualMemorySize, should i care or can this be ignored?
  • Why does the 64bit version of the program allocate so much more VirtualMemory?
like image 435
Manuel Avatar asked Mar 20 '15 14:03

Manuel


2 Answers

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.

like image 64
Hans Passant Avatar answered Oct 31 '22 19:10

Hans Passant


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.

like image 36
Thomas Weller Avatar answered Oct 31 '22 19:10

Thomas Weller