我需要分配大量内存来模拟.NET应用程序的内存消耗。我预计new byte[1000*1024*1024]
会一次分配所有内存,但它没有发生。
例如,请考虑以下代码:
var bytes = 1000*1024*1024;
var memory = new byte[bytes];
memory[bytes - 1] = 16;
//Step 1
Console.ReadLine();
for (int i = 0; i < memory.Length / 2; i++)
{
memory[i] = 16;
}
//Step 2
Console.ReadLine();
for (int i = memory.Length / 2; i < memory.Length; i++)
{
memory[i] = 16;
}
根据Process Explorer,在步骤1之前没有分配内存,在步骤2之前只分配了一半的预期内存。仅在步骤2之后,才分配所有1000 * 1024 * 1024字节。在Debug和Release VS配置中编译。
所以问题是:
更新:
我已经通过资源监控工具检查了内存消耗,并且&#34;提交&#34;部分显示正确的1000 Mb,然而&#34;工作集&#34;表现如上所述。由于我的任务是模拟实际负载,我想我需要加载实际的物理内存,而不是虚拟内存。
答案 0 :(得分:2)
我在LinqPad中尝试了这个程序,同时打开了ProcessExplorer。它确实在步骤1增加了内存,但只增加了专用字节(即虚拟内存)。工作集大小或多或少相同。原因是这里的私有字节代表虚拟内存。这是按需分配的,但在需要之前不会被物理内存支持。工作集表示使用的实际物理内存。一旦开始使用该阵列,将分配未在物理内存中分配的部分,并且工作集大小将增加。请注意,它可能无法达到数组的完整大小,因为这样效率很低。相反,在一段时间内被触摸的部分将被换掉,这样工作集就不会变得很大。
编辑:在回答您的更新时,您几乎没有选择:
答案 1 :(得分:2)
这是Windows等需求页面虚拟内存操作系统的标准行为。使用 new 运算符分配内存仅分配地址空间。只是处理器的数字,每4096字节一个。一页。
提交大小增加,您有一个可靠的承诺,即一旦开始寻址数组元素,就可以获得所需的物理存储。 Windows在页面文件中保留了空间用于分配。
但是在你真正开始使用数组元素之前,RAM分配并没有发生。这会导致分页错误,每4096个元素就会得到一个。现在,操作系统被迫使物理存储可用。 RAM。
这往往会增加工作集,程序使用的RAM量。这是不保证会发生,当操作系统处于压力之下并且需要在需要大量内存的进程中分配可用RAM时,它可能需要强行丢弃页面以使其可用于您的程序。通常只是在页面包含代码时将内容丢弃或者映射到文件(如代码)。或者它将内容备份到页面文件。稍后再次检索,当进程需要再次在RAM中提供页面时。
您通常为新分配获得的页面错误类型是 soft 页面错误。它们被快速处理,操作系统从池中提取一页RAM。如果需要丢弃另一个页面并将其写入页面文件或者页面被换出并需要重新交换,则会出现硬页面错误。这会显着降低程序速度,这个问题称为&#34; thrashing&# 34 ;.没有足够RAM并且过载的机器由于颠簸而往往很慢。
这种操作系统设计的结果是文件和内存之间不再存在真正的区别。当您使用内存时,您还使用文件。通常是分页文件。反过来说,当你使用文件时,你实际上使用了内存。文件系统缓存。 RAM只是避免访问磁盘的便捷方式。机器拥有的RAM越多,您击中磁盘的频率就越低。程序员往往过于担心这一点,当他们也有选择(或没有api选择)使用文件时,他们太难以将数据保存在内存中。并且像OutOfMemoryException一样陷入麻烦或导致颠簸。