2009-07-10 54 views
18

我想知道为什么我无法在我的32位.NET进程中分配多于1,000 MB的内存。以下迷你应用程序在分配1,000 MB后引发OutOfMemoryException。为什么要1,000 MB,而不是说1.8 GB?有没有可以改变的全过程设置?在32位.NET进程中分配超过1,000 MB的内存

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。

回答

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

16

拥有巨大的内存块永远不是一个好主意,即使在64位。连续的内存和碎片会导致严重的问题。

这里的问题是找到一个连续的块。你可以尝试启用3gb模式(这可能会帮助它找到更多的字节),但我真的建议反对它。这里的答案是:

  • 使用较少的内存
  • 使用一个数据库/文件系统
  • 使用64

您可能还需要阅读Eric Lippert's博客(他似乎有一个博客条目对于每个常见的.NET问题......)

+2

Johannes,为什么会有更多的地址空间不容易找到更多的连续地址空间?我对你的评论完全困惑。你可以解释吗? – 2009-07-10 18:06:06

+0

@Eric - 我很高兴它不只是我... – 2009-07-10 18:55:44

+0

请看我的说明。我已经在使用db/fs。 – 2009-07-12 13:36:19

2

我最近一直在32位进程在做.NET左右的内存限制了广泛分析。我们都受到这样的想法的轰炸:我们可以在.NET应用程序中分配高达2.4GB(2^31)的内存,但不幸的是这不是真的:(应用程序具有足够的空间来使用,操作系统很棒但是,.NET本身似乎有自己的开销,对于推动内存限制的典型真实世界应用程序来说,它占据了大约600-800MB的空间。这意味着只要您分配一组需要处理大小的整数1.4GB,你应该看到一个OutOfMemoryException()。

显然在64位,这个限制发生在稍后的方式(让我们在5年:)聊天),但一切在内存中的一般大小也增长(我发现这是〜1.7倍~2倍),因为增加了字的大小。

我所知道的是,操作系统中的虚拟内存理念绝对不会在一个进程中给你几乎无尽的分配空间。只有这样才能让全部2.4GB的存储空间适用于同时运行的所有(许多)应用程序。

我希望这种见解有所帮助。

我本来在这里回答有关的东西(我仍然是一个牛逼所以我不知道我是多么应该做这些链接):

Is there a memory limit for a single .NET process

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

您是否尝试过使用方法?这可能是一个愚蠢的问题,但为什么你创造了一个永恒的循环? O如果您尝试使用代码去除符号>。> xD。

来源:http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

-1

我觉得这里的问题是,这个应用程序将增加10MB每圈它使和循环是:“虽然(真)”,这意味着它将加入这些10MBs烧至应用程序停止。因此,如果要运行100个循环,它将向RAM添加接近1GB的内存,并且我假设它将在不到30秒的时间内完成此操作。我的意思是,你试图在每个循环中存储10兆字节的内存,在一个永无止境的循环中

0

通过将应用程序构建到64位体系结构中,您可以分配更多的内存,而不是约2 GB,这需要您创建Visual Studio中的新构建配置,并且该应用程序的构建只能在64位版本的Windows上运行。在.NET中,使用应用程序默认的“Any CPU”构建选项,我发现我只能从堆中分配大约1.5 GB的内存(即使在64位Windows计算机上),这是因为应用程序实际上当它以“任何CPU”模式构建时,只能在32位模式下运行。但是通过编译为x64架构,您可以在执行应用程序时从堆中分配更多,更多的内存,并且我将解释如何为您的应用程序创建x64版本:

再次,使用正常默认).NET项目中的“任何CPU”构建选项,即使在64位Windows操作系统上,您的应用程序也将始终运行在32位模式下。因此,在应用程序执行期间,您将无法分配超过1.5到2 GB的RAM内存。要以真正的64位模式运行.NET应用程序,您需要进入构建配置管理器并为x64体系结构创建构建类型,然后使用该构建类型明确重新编译x64程序。在64位编译模式选项可以为您的.NET解决方案使用以下步骤来创建:

  1. 在Visual Studio的“解决方案资源管理器”窗格中,右键点击Solution图标,并选择从“配置管理器”选项弹出菜单。这将打开.NET解决方案文件的构建“配置管理器”对话窗口。
  2. 在右侧的构建“Configuration Manager”对话框的顶部,单击向下箭头并选择“&ltnew”选项。这将打开“新解决方案平台”对话框。
  3. 在“新解决方案平台”对话框中,对于“平台”选项,从下拉菜单中选择“x64”。然后单击“确定”按钮,现在可以在配置管理器对话框中使用新的x64构建选项。
  4. 然后,在“Configuration Manager”对话框的“Active Solution Platform”下拉菜单中选择“x64”。点击“关闭”按钮。
  5. 在Visual Studio的“解决方案资源管理器”窗格中,右键单击CS项目图标,然后从弹出菜单(此菜单底部的最后一个选项)中选择“属性”选项。这将打开CS项目属性窗口。
  6. 在CS Project属性窗口的左侧,单击“Build”选项卡以显示代码项目的构建属性。在此窗口的顶部,请注意“平台”现在应该说“x64”(而不是默认的“任何CPU”选项)。如果“平台”下拉列表中没有显示“x64”,则应该立即选择它。
  7. 然后,只需构建代码并在“bin”文件夹中,您现在应该有一个x64文件夹,其中包含应用程序的新64位版本。

使用您的64位应用程序的64位编译Windows操作系统将让你的程序分配更多的内存大于〜2GB,大概达到2^64的地址空间(如果你有RAM和磁盘空间可用,这是写入此响应时的真正限制因素)。

如果您仍然在应用程序内存不足,您还可以增加Windows内存页面文件的大小。在Windows上,页面文件允许操作系统将内存从RAM移动到磁盘(如果RAM内存空间不足)。但是,将RAM存储器的各部分移入和移出磁盘存在很大的时间成本,因此它可能会对应用程序的性能造成实质性影响。无论性能如何,通过增加页面大小,(理论上)可以使页面文件的大小与Windows计算机的C:驱动器上的可用空间一样大。在这种情况下,您的应用程序将能够在执行程序期间分配最多4 TB的内存(或者您的页面文件大小设置为的任意数量的内存)。改变页面文件设置为你的Windows机器,请执行以下操作:

  1. 打开“这台电脑”,选择弹出菜单中的“属性”选项,在“系统属性”对话框中右击。通过转到“开始”&gt“控制面板”&gt“系统和安全性>>系统”,也可以在更高版本的Windows(Windows 10,Win 2012 Server等)中完成此操作。
  2. 在“系统”对话框的左侧,单击“高级系统属性”选项。这将显示Windows的传统“系统属性”对话框的“高级”选项卡。
  3. 在“系统属性”对话框的“高级”选项卡上,单击“性能”框中的“设置”按钮。这将打开“性能选项”对话框。
  4. 在“性能选项”对话框中,单击“高级”选项卡以查看Windows内存页面文件的当前大小设置。
  5. 要增加页面文件大小,请单击“更改”按钮并打开“虚拟内存”对话框。
  6. 在“虚拟内存”对话框中,选择“C:”驱动器,然后在“自定义尺寸”下设置“初始”和“最大”尺寸。您可以使用任何大小,直到C:驱动器上的最大可用空间量,但进行此更改将为硬盘驱动器上的页面文件保留该空间。
  7. 然后在所有对话框上单击“确定”以提交新设置。然后重新启动计算机以确保所有更改都已正确完成,并且新页面文件设置处于运行状态。

无论如何,我希望这可以帮助人们理解为什么他们可以在.NET应用程序中遇到这种1.5 - 2 GB的内存限制问题,即使是在64位Windows机器上运行。这可能是一个令人困惑的问题,我希望我的解释有道理。如有需要,请随时通知我有关此答案的问题。

相关问题