簡體   English   中英

VirtualMemorySize64和PrivateMemorySize64之間的區別是什么

[英]What is the difference between VirtualMemorySize64 and PrivateMemorySize64

我不明白Process.PrivateMemorySize64Process.VirtualMemorySize64之間的區別

我創建了一個簡單的控制台應用程序,它將10倍10兆字節分配給一個字節數組。

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]);
}

PrivateMemorySize64按照我的預期工作:它以一定的大小開始,並隨着分配的內存而增長。

但VirtualMemorySize64似乎在一開始就分配了大量內存,即使對於一個控制台應用程序(180位為32位,560位為64位)

32位內存分配樣本32位內存分配樣本

問題:

  • VirtualMemorySize的PrivateMemorySize是一部分嗎? 如果是這樣,那么VirtualMemorySize的其余部分是什么? 它只是保留內存,還是實際上是ram / page文件?
  • 為什么即使是一個簡單的控制台應用程序也會分配超過500mb的VirtualMemory?
  • 如果我的應用程序使用1GB的PrivateMemorySize和20GB的VirtualMemorySize,我應該關心還是可以忽略它?
  • 為什么64位版本的程序分配了更多的VirtualMemory?

VirtualMemorySize測量進程使用的所有虛擬內存。 其中包括計算機上所有其他進程共享的頁面。 在.NET程序中包含操作系統,CLR,抖動和ngen-ed框架程序集。

PrivateMemorySize測量專用於您的進程的虛擬內存,並且不能由其他進程共享。 在.NET程序中包含所有數據和任何非編譯的jitted代碼。

兩者都是虛擬內存測量,內部表示為處理器的數字。 每4096字節的內存一個。 實際的RAM使用量是一個非常不同的數字,由Process.WorkingSet表示。 通常不太有用,當其他進程需要RAM時,它可以非常快速地改變,並且您需要將一些使用的內容映射出來。 你的操作系統和.NET都經過優化,可以使用大量的虛擬機,在現代機器上可以使用很多虛擬機,它可以替代磁盤。

VirtualMemorySize的PrivateMemorySize是一部分嗎? 如果是這樣,那么VirtualMemorySize的其余部分是什么? 它只是保留內存,還是實際上是ram / page文件?

是。 其余的是共享內存,如第一段所述

為什么即使是一個簡單的控制台應用程序也會分配超過500mb的VirtualMemory?

操作系統和.NET運行時都不會偏向於您的控制台應用程序很小,仍然需要它們來執行它。 由於它們由所有進程共享,因此您並不關心它。 你也沒有什么可以做的。 “大”控制台應用程序通常不會添加更多VM,除非它分配了大量內存。

如果我的應用程序使用1GB的PrivateMemorySize和20GB的VirtualMemorySize,我應該關心還是可以忽略它?

1GB的私人內存不用擔心。 20GB的VM過多。 GC堆的大小是值得關注的,當必須通過數千兆字節的堆時,集合可能會變慢。

為什么64位版本的程序分配了更多的VirtualMemory?

好吧,64是2 * 32.這並不像那樣,64位進程仍然傾向於使用大量的整數 編寫一個現代的64位操作系統來假設有大量的硬件資源可供使用,Win8需要8 GB的RAM才能順利運行。

VirtualMemorySize的PrivateMemorySize是一部分嗎?

是。 一切都是VirtualMemorySize的一部分,除非您編寫內核驅動程序,在這種情況下您可能會談論物理RAM。

如果是這樣,那么VirtualMemorySize的其余部分是什么?

  • DLL加載到進程中
  • 映射文件
  • .NET IL代碼被編譯
  • 默認進程堆
  • TEB(線程環境塊)和PEB(進程環境塊)
  • 如果你做P / Invoke或類似的東西,C ++會堆積
  • 直接調用VirtualAlloc()

它只是保留內存,還是實際上是ram / page文件?

虛擬內存可以保留(不可用)或已提交(可供使用)。 保留的部分既不在RAM中也不在頁面文件中。

為什么即使是一個簡單的控制台應用程序也會分配超過500mb的VirtualMemory?

您可以使用調試器查找它,例如WinDbg。 這是64位操作系統上的.NET 4.5 32位程序(您的代碼)。

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%

<unknown>部分包括.NET內存。 在這種情況下,它可能只有 .NET,因為我沒有C ++或VirtualAlloc()調用。

也可以看到.NET目前只使用那些206 MB中的105 MB:

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.

我們可以看到總共保留了131 MB:

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%

如果我的應用程序使用1GB的PrivateMemorySize和20GB的VirtualMemorySize,我應該關心還是可以忽略它?

如果不知道您的流程預期會做什么,您無法分辨。 您可能使用過度使用內存的第三方DLL,例如用於數據分析。 那沒關系。

一般來說,你應該對你的產品有一種“感覺”。 如果行為大規模改變,那么我會開始調查。

為什么64位版本的程序分配了更多的VirtualMemory?

可能因為.NET不必擔心其他事情。

在32位,只有4 GB的內存,.NET需要確保可以加載其他DLL,可以創建線程等。在64位,8 TB的內存,將始終有1 MB來創建一個新的線。

您提供的鏈接解釋了這個問題:

PrivateMemorySize:

此屬性返回的值表示進程使用的當前內存大小,該內存無法與其他進程共享。

VirtualMemorySize:

此屬性返回的值表示進程使用的當前虛擬內存大小。 操作系統將每個進程的虛擬地址空間映射到物理內存中加載的頁面,或映射到磁盤上虛擬內存頁面文件中存儲的頁面。

因此,第一個通過自己的內存分配來說明應用程序消耗了多少內存,后者告訴它有多少內存映射到它(意味着使用的整個內存空間,包括PrivateMemorySize),包括操作系統和.NET框架庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM