Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当计算机有更多的ram时,为什么.net程序使用更多的虚拟内存64_C#_.net_Memory - Fatal编程技术网

C# 当计算机有更多的ram时,为什么.net程序使用更多的虚拟内存64

C# 当计算机有更多的ram时,为什么.net程序使用更多的虚拟内存64,c#,.net,memory,C#,.net,Memory,我创建了一个简单的测试应用程序,它使用二进制数组分配100mb的内存 using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; namespace VirtualMemoryUsage { class Program { static void Main(string[] args) { StringBuilder sb = new S

我创建了一个简单的测试应用程序,它使用二进制数组分配100mb的内存

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace VirtualMemoryUsage
{
class Program
{
    static void Main(string[] args)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine($"IsServerGC = {System.Runtime.GCSettings.IsServerGC.ToString()}");

        const int tenMegabyte = 1024 * 1024 * 10;
        long allocatedMemory = 0;
        List<byte[]> memory = new List<byte[]>();
        for (int i = 0; i < 10; i++)
        {
            //alloc 10 mb memory
            memory.Add(new byte[tenMegabyte]);
            allocatedMemory += tenMegabyte;
        }

        sb.AppendLine($"Allocated memory:    {PrettifyByte(allocatedMemory)}");
        sb.AppendLine($"VirtualMemorySize64: {PrettifyByte(Process.GetCurrentProcess().VirtualMemorySize64)}");
        sb.AppendLine($"PrivateMemorySize64: {PrettifyByte(Process.GetCurrentProcess().PrivateMemorySize64)}");
        sb.AppendLine();
        Console.WriteLine(sb.ToString());
        Console.ReadLine();
    }

    private static object PrettifyByte(long allocatedMemory)
    {
        string[] sizes = { "B", "KB", "MB", "GB", "TB" };
        int order = 0;
        while (allocatedMemory >= 1024 && order < sizes.Length - 1)
        {
            order++;
            allocatedMemory = allocatedMemory / 1024;
        }
        return $"{allocatedMemory:0.##} {sizes[order]}";
    }
 }
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用系统文本;
名称空间虚拟化
{
班级计划
{
静态void Main(字符串[]参数)
{
StringBuilder sb=新的StringBuilder();
sb.AppendLine($“IsServerGC={System.Runtime.GCSettings.IsServerGC.ToString()}”);
常量int十兆字节=1024*1024*10;
长分配内存=0;
列表内存=新列表();
对于(int i=0;i<10;i++)
{
//alloc 10 mb内存
Add(新字节[tenMegabyte]);
allocatedMemory+=10兆字节;
}
sb.AppendLine($“已分配内存:{PrettifyByte(allocatedMemory)}”);
sb.AppendLine($“VirtualMemorySize64:{PrettifyByte(Process.GetCurrentProcess().VirtualMemorySize64)}”);
sb.AppendLine($“privatemorysize64:{PrettifyByte(Process.GetCurrentProcess().privatemorysize64)}”);
(某人);
Console.WriteLine(sb.ToString());
Console.ReadLine();
}
私有静态对象PrettifyByte(长分配内存)
{
字符串[]大小={“B”、“KB”、“MB”、“GB”、“TB”};
整数阶=0;
while(allocatedMemory>=1024&&order
注意:对于此测试,在app.config中将gcserver设置为true非常重要

<runtime>
  <gcServer enabled="true"/>  
</runtime>

然后,这将显示进程分配的PrivateMorySize64和VirtualMemorySize64的数量

虽然PrivateMorysize64在不同的计算机上保持相似,但VirtualMemorySize64的差异很大。


当分配相同的内存量时,VirtualMemorySize64中出现这种差异的原因是什么?有关于这方面的文档吗?

您使用的指标不是分配的内存,而是内存。一个-,另一个-与机器上的其他进程一起。实际内存量取决于可用内存量和正在运行的其他进程

编辑:Thomas Weller的回答提供了比我的Microsoft链接更多的关于该主题的详细信息

它不一定表示应用程序执行的分配量。若您想获得分配内存的估计值(不包括.NET framework库和内存分页开销等),可以使用

long memory = GC.GetTotalMemory(true);

其中
true
参数告诉GC首先执行垃圾收集(它不必这样做)。未使用但未收集的内存将计入您询问的值中。若系统有足够的内存,在需要之前可能无法收集。在这里你可以找到GC是如何工作的。

哇,你真幸运。在我的机器上,最后一行显示17 GB

Allocated memory:    100M
VirtualMemorySize64: 17679M
PrivateMemorySize64: 302M
虽然PrivateMorysize64在不同的计算机上保持相似[…]

专用字节是仅属于程序的字节。它很难受到其他东西的影响。它包含堆中其他人无法访问的内容

为什么是302MB而不仅仅是100MB?SysInternals VMMap是分解该值的好工具:

专用字节的颜色和大小表示:

  • 紫色(7.5 MB):图像文件,即不可共享的DLL
  • 橙色(11.2MB):堆(非.NET)
  • 绿色(103MB):托管堆
  • 橙色(464KB):堆栈
  • 黄色(161MB):私有数据,如TEB和PEB
  • 棕色(36MB):页表
如您所见,.NET在托管堆中的开销只有3 MB。其余的是任何流程都需要完成的其他工作

调试器或探查器有助于分解托管堆:

0:013> .loadby sos clr
0:013> !dumpheap -stat
[...]
000007fedac16878      258        11370 System.String
000007fed9bafb38      243        11664 System.Diagnostics.ThreadInfo
000007fedac16ef0       34        38928 System.Object[]
000007fed9bac9c0      510       138720 System.Diagnostics.NtProcessInfoHelper+SystemProcessInformation
000007fedabcfa28        1       191712 System.Int64[]
0000000000a46290      305       736732      Free
000007fedac1bb20       13    104858425 System.Byte[]
Total 1679 objects
因此,您可以看到.NET“默认情况下”需要一些字符串和其他对象

当分配相同的内存量时,VirtualMemorySize64中出现这种差异的原因是什么

仅提交了335 MB。这就是可以实际使用的内存。16.954 GB刚刚被保留。它们目前不能使用。它们既不在RAM中,也不在页面文件的磁盘上。分配保留内存非常快。我经常看到17 GB的值,特别是在ASP.NET崩溃转储中

再次查看VMMap中的详细信息


我们可以看到,17 GB仅分配在一个块中。关于您的问题的一条评论说:“当系统内存不足时,垃圾收集器会触发并释放繁忙的垃圾收集器。”但是,要逐个VirtualFree()释放VirtualAlloc()'d块,该块在逻辑上不能为空,即内部不应该有一个.NET对象,这是不可能的。所以它将永远留在那里

可能的好处是什么?它是一个连续的内存块。如果您现在需要一个
新字节[4G]()
,它就可以工作了

最后,可能的原因是:这样做是因为它不会伤害内存和磁盘。如果需要,可以在以后的时间点提交

有关于这方面的文件吗

那不太可能。GC实现的细节可能会随着.NET的下一个版本而改变。我认为微软没有记录这一点,否则人们会抱怨,如果行为改变

有人写过这样的博客文章,告诉我们一些值可能取决于处理器的数量,例如

0:013> !eeheap -gc
Number of GC Heaps: 4
[...]

我们在这里看到的是.NET创建的堆与处理器的堆一样多。这对于垃圾收集很有好处,因为每个处理器都可以独立收集一个堆。

当系统内存不足时,垃圾收集器会触发并释放繁忙的堆。只要有足够的内存,垃圾收集器就会休眠。潜在原因:因为它是可用的。官方的
0:013> !eeheap -gc
Number of GC Heaps: 4
[...]