在32位.NET进程中分配超过1,000 MB的内存

我想知道为什么我无法在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:垃圾收集没有帮助。

编辑,澄清我想要的:我编写了一个服务器应用程序,在写入数据库/磁盘之前处理大量数据。 我没有为所有内容创建临时文件,而是编写了一个内存缓存,这使得整个过程非常快。 但记忆是有限的,所以我试图找出限制是什么。 并且想知道为什么我的小测试程序在1,000 MB之后抛出了OutOfMemoryException。

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 /论坛/ zh-CN / clr / thread / c50ea343-b41b-467d-a457-c5a735e4dfff http://www.guidanceshare.com/wiki/ASP.NET_1.1_Performance_Guidelines_-_Caching#Configure_the_Memory_Limit

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

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

  • 使用更少的内存
  • 使用数据库/文件系统
  • 使用x64

您可能还想阅读Eric Lippert的博客(他似乎为每个常见的.NET问题都有一个博客条目……)

我最近在32位进程中对.NET中的内存限制进行了大量的分析。 我们都被我们在.NET应用程序中分配高达2.4GB(2 ^ 31)的想法所震撼,但不幸的是,这不是真的:(。应用程序进程有很大的空间可供使用,操作系统做得很好然而,.NET本身似乎有自己的开销,对于推动内存限制的典型实际应用程序来说,它本身就占了大约600-800MB。这意味着只要你分配一个整数数组就可以了1.4GB,你应该会看到一个OutOfMemoryException()。

显然在64位,这个限制发生的方式稍晚(让我们在5年内聊聊:)),但由于字数增加,内存中所有内容的一般大小也会增长(我发现它大约是1.7到2倍)。

我确切知道的是,来自操作系统的虚拟内存理念肯定不会在一个进程中为您提供几乎无限的分配空间。 只有这样才能使完整的2.4GB可以同时运行所有(许多)应用程序。

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

我最初回答了一些相关的问题(我还是一个新手,所以我不确定我应该怎么做这些链接):

单个.NET进程是否有内存限制

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

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

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

在64位Windows操作系统上使用64位版本的应用程序将允许您的程序分配超过2GB的内存,大概可达2 ^ 64个地址空间(如果您有可用的RAM和磁盘空间,是撰写此回复时的真正限制因素)。

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

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

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

我认为这里的问题是这个应用程序将在每个循环中添加10MB,循环是:“while(true)”这意味着它将添加这些10MB直到应用程序停止。 因此,如果它运行100循环,它将增加接近1GB的RAM,我假设它将在不到30秒内完成此操作。 我的观点是你在每个循环中尝试10兆字节的内存,这是一个永无止境的循环

如果我没有明白你的意思,我真的很抱歉,但是:

 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