我想知道为什么我无法在32位.NET进程中分配超过1,000 MB的内存。以下迷你应用程序在分配1,000 MB后抛出OutOfMemoryException。为什么1,000 MB,而不是说1.8 GB?是否有可以更改的流程范围设置?
static void Main(string[] args)
{
ArrayList list = new ArrayList();
int i = 0;
while (true)
{
list.Add(new byte[1024 * 1024 * 10]); // 10 MB
i += 10;
Console.WriteLine(i);
}
}
PS:垃圾收集无济于事。
编辑,澄清我想要的内容:我编写了一个服务器应用程序,在写入数据库/磁盘之前处理大量数据。我没有为所有内容创建临时文件,而是编写了一个内存缓存,这使整个过程非常快。但记忆是有限的,所以我试图找出限制是什么。并且想知道为什么我的小测试程序在完全1000 MB之后抛出了OutOfMemoryException。
答案 0 :(得分:16)
拥有巨大的内存块永远不是一个好主意,即使在64位。连续的内存和碎片会带来很大的问题。
这里的问题是找到一个连续的块。您可以尝试启用3gb模式(这可能有助于它找到更多的字节),但我真的建议反对它。这里的答案是:
您可能还想阅读Eric Lippert's博客(他似乎有一个针对每个常见.NET问题的博客条目......)
答案 1 :(得分:7)
Win32进程的虚拟地址空间限制为1.5GB(不完全正确)。此外,在.NET框架中,.NET进程可以使用的内存百分比有限制。 machine.config有一个processModel元素,其属性memoryLimit是进程可以使用的可用内存的百分比。默认值为60%。
如果您运行的计算机有2GB内存,或者您没有在BOOT.INI中启用/ 3GB开关,那么每个进程将获得~1.3GB的内存。
我找不到知识库文章,但如果我没记错,无论你的设置如何,.NET 1.x都无法超越1.5GB(1.8GB?)的限制。
http://blogs.msdn.com/tmarq/archive/2007/06/25/some-history-on-the-asp-net-cache-memory-limits.aspx http://social.msdn.microsoft.com/Forums/en-US/clr/thread/c50ea343-b41b-467d-a457-c5a735e4dfff http://www.guidanceshare.com/wiki/ASP.NET_1.1_Performance_Guidelines_-_Caching#Configure_the_Memory_Limit
答案 2 :(得分:2)
我最近在32位进程中对.NET中的内存限制进行了大量的分析。我们都被一个.NET应用程序中可以分配高达2.4GB(2 ^ 31)的想法所震撼,但不幸的是,这不是真的:(。应用程序进程有很大的空间可供使用,操作系统也很棒但是,.NET本身似乎有自己的开销,对于推动内存限制的典型实际应用程序来说,它本身就占了大约600-800MB。这意味着只要你分配一个整数数组就可以了1.4GB,你应该会看到一个OutOfMemoryException()。
显然在64位,这个限制发生的方式稍晚(让我们在5年内聊聊:)),但是内存中所有内容的一般大小也会增长(我发现它的大小是~1.7到2倍),因为字大小增加了
我确切知道,操作系统中的虚拟内存理念肯定不会在一个进程中为您提供几乎无限的分配空间。只有这样才能使完整的2.4GB可以同时运行所有(许多)应用程序。
我希望这种见解有所帮助。
我最初在这里回答了一些相关内容(我还是一个新手,所以我不确定我应该怎么做这些链接):
答案 3 :(得分:0)
通过将应用程序构建到64位体系结构,您可以分配大于2 GB的内存,这需要您在Visual Studio中创建新的构建配置,并且该应用程序的构建仅在64位上运行Windows版本。在.NET中,使用默认的"任何CPU"为您的应用程序构建选项,我发现我只能从堆中分配大约1.5 GB的内存(即使在64位Windows机器上),这是因为应用程序实际上只在构建时以32位模式运行in"任何CPU"模式。但是通过编译到x64架构,您可以在应用程序执行期间从堆中分配更多,更多的内存,我将在下面解释如何为您的应用程序创建x64构建:
再次,使用普通(默认)"任何CPU"在.NET项目中构建选项,您的应用程序将始终在32位模式下运行,即使在64位Windows操作系统上也是如此。因此,在应用程序执行期间,您无法分配超过大约1.5到2 GB的RAM内存。要以真正的64位模式运行.NET应用程序,您需要进入构建配置管理器并为x64体系结构创建构建类型,然后使用该构建类型显式重新编译x64程序。可以使用以下步骤为.NET解决方案创建x64构建模式选项:
在64位Windows操作系统上使用64位版本的应用程序将允许您的程序分配超过〜2GB的内存,大概可达2 ^ 64个地址空间(如果您有RAM和磁盘空间)可用,这是撰写此回复时的真正限制因素)。
如果您的应用程序中仍然没有内存不足,您还可以增加Windows内存页面文件的大小。在Windows上,页面文件允许操作系统将内存从RAM转移到磁盘(如果RAM内存空间不足)。但是,将RAM内存部分移入和移出磁盘需要花费大量时间,因此它可能会严重影响应用程序的性能。无论性能如何,通过增加页面大小,您(理论上)可以使页面文件与Windows计算机的C:驱动器上的可用空间一样大。在这种情况下,您的应用程序将能够在程序执行期间分配最多4 TB的内存(或页面文件大小设置为的任何内存量)。要更改Windows计算机的页面文件设置,请执行以下操作:
无论如何,我希望这有助于人们理解为什么他们会在.NET应用程序中遇到这个1.5-2 GB的内存限制问题,即使在64位Windows机器上运行也是如此。对于人们来说,这可能是一个非常令人困惑的问题,我希望我的解释是有道理的。如果需要,请随时向我发送有关此答案的问题。
答案 4 :(得分:0)
将程序编译为Any CPU
,您将拥有无限量的内存使用,并且程序仍然可以使用 x86(32 位)DLL 导入!!!
答案 5 :(得分:-1)
我认为这里的问题是这个应用程序将在每个循环中添加10MB,循环是:“while(true)”这意味着它将添加这些10MB直到应用程序停止。因此,如果它运行100循环它将增加接近1GB的RAM,我假设它将在不到30秒内完成此操作。我的观点是你在每个循环中尝试10兆字节的内存,在一个永无止境的循环中
答案 6 :(得分:-2)
如果我不明白你的意思,我真的很抱歉:
static void Main(string[] args)
{
ArrayList list = new ArrayList();
int i = 0;
while (true)
{
using(byte newBt = new byte[1024 * 1024 * 10])
{
list.Add(newBt); // 10 MB
i += 10;
Console.WriteLine(i);
}
}
}
您是否尝试过使用方法?这可能是一个愚蠢的问题,但为什么你创造了一个永恒的循环?如果你尝试代码剥离符号>。>的xD。
来源:http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx