C# 在 32 位 .NET 进程中分配超过 1,000 MB 的内存
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1109558/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Allocating more than 1,000 MB of memory in 32-bit .NET process
提问by Stefan Schultze
I am wondering why I'm not able to allocate more that 1,000 MB of memory in my 32-bit .NET process. The following mini application throws an OutOfMemoryException after having allocated 1,000 MB. Why 1,000 MB, and not say 1.8 GB? Is there a process-wide setting I could change?
我想知道为什么我不能在我的 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: Garbage collecting does not help.
PS:垃圾收集没有帮助。
Edit, to clarify what I want:I have written a server application which deals with very large amounts of data before writing to database/disk. Instead of creating temporary files for everything, I have written an in-memory cache, which makes the whole thing super-fast. But memory is limited, and so I tried to find out what the limits are. And wondered why my small test program threw the OutOfMemoryException after exactly 1,000 MB.
编辑,澄清我想要什么:我编写了一个服务器应用程序,它在写入数据库/磁盘之前处理大量数据。我没有为所有内容创建临时文件,而是编写了一个内存缓存,这使整个过程变得非常快。但是内存是有限的,所以我试图找出限制是什么。并想知道为什么我的小测试程序在恰好 1,000 MB 之后抛出 OutOfMemoryException。
采纳答案by MyItchyChin
The virtual address space limit of a Win32 process is 1.5GB (not entirely true). Additionally in the .NET frameworks there is a limiter to the % of memory a .NET process can consume. The machine.config has a processModel element with an attribute memoryLimit which is the % of available memory a process can consume. The default value is 60%.
Win32 进程的虚拟地址空间限制为 1.5GB(不完全正确)。此外,在 .NET 框架中,.NET 进程可以消耗的内存百分比存在限制。machine.config 有一个 processModel 元素,其属性 memoryLimit 是进程可以消耗的可用内存的百分比。默认值为 60%。
If the machine you're running on has 2GB of memory or you haven't enabled the /3GB switch in your BOOT.INI then you're going to get ~1.3GB of memory per process.
如果您运行的机器有 2GB 的内存,或者您没有在 BOOT.INI 中启用 /3GB 开关,那么每个进程将获得大约 1.3GB 的内存。
I can't find the KB article but if I remember correctly .NET 1.x cannot address beyond the 1.5GB (1.8GB?) limit regardless of your settings.
我找不到知识库文章,但如果我没记错的话,无论您的设置如何,.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.aspxhttp://social.msdn.microsoft.com/Forums/en-US/clr/thread/c50ea343-b41b-467d-a457-c5a735e4dfffhttp://www.guidanceshare.com/wiki/ASP.NET_1.1_Performance_Guidelines_-_Caching#Configure_the_Memory_Limit
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
回答by Marc Gravell
Having enormous blocks of memory is never a good idea, even in 64bit. You get big problems with contiguous memory and fragmentation.
拥有巨大的内存块从来都不是一个好主意,即使在 64 位中也是如此。您会遇到连续内存和碎片的大问题。
The problem here is finding a contiguous block. You could try enabling 3gb mode (which might help it find a few more bytes) but I reallyadvise against it. The answers here are:
这里的问题是找到一个连续的块。您可以尝试启用 3gb 模式(这可能有助于它找到更多字节),但我真的不建议这样做。这里的答案是:
- use less memory
- use a database/file system
- use x64
- 使用更少的内存
- 使用数据库/文件系统
- 使用 x64
You might also want to read Eric Lippert'sblog (he seems to have a blog entry for every common .NET question...)
您可能还想阅读Eric Lippert 的博客(他似乎对每个常见的 .NET 问题都有一个博客条目......)
回答by Luke Machowski
I have recently been doing extensive profiling around memory limits in .NET on a 32bit process. We all get bombarded by the idea that we can allocate up to 2.4GB (2^31) in a .NET application but unfortunately this is not true :(. The application process has that much space to use and the operating system does a great job managing it for us, however, .NET itself seems to have its own overhead which accounts for approximately 600-800MB for typical real world applications that push the memory limit. This means that as soon as you allocate an array of integers that takes about 1.4GB, you should expect to see an OutOfMemoryException().
我最近在 32 位进程上围绕 .NET 中的内存限制进行了广泛的分析。我们都被 .NET 应用程序中最多可以分配 2.4GB (2^31) 的想法轰炸,但不幸的是这不是真的 :(。应用程序进程有那么多空间可以使用,操作系统做得很好为我们管理它的工作,然而,.NET 本身似乎有它自己的开销,对于推动内存限制的典型现实世界应用程序,它大约占 600-800MB。这意味着一旦你分配一个整数数组,大约需要1.4GB,您应该会看到 OutOfMemoryException()。
Obviously in 64bit, this limit occurs way later (let's chat in 5 years :)), but the general size of everything in memory also grows (I am finding it's ~1.7 to ~2 times) because of the increased word size.
显然,在 64 位中,此限制发生得更晚(让我们在 5 年后讨论 :)),但是由于字大小的增加,内存中所有内容的总体大小也会增加(我发现它是 ~1.7 到 ~2 倍)。
What I know for sure is that the Virtual Memory idea from the operating system definitely does NOT give you virtually endless allocation space within one process. It is only there so that the full 2.4GB is addressable to all the (many) applications running at one time.
我可以肯定的是,操作系统的虚拟内存理念绝对不会在一个进程中为您提供几乎无限的分配空间。只有在那里,整个 2.4GB 才能被一次运行的所有(许多)应用程序寻址。
I hope this insight helps somewhat.
我希望这种见解有所帮助。
I originally answered something related here (I am still a newby so am not sure how I am supposed to do these links):
我最初在这里回答了一些相关的问题(我仍然是新手,所以不确定我应该如何做这些链接):
回答by Nico
I am truly sorry if I didn't get your point but:
如果我没有明白你的意思,我真的很抱歉,但是:
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);
}
}
}
Have you tried the using method? And this might be a stupid question but why did you create an eternal loop? O if you try the code strip the symbols >.> xD.
你试过使用方法吗?这可能是一个愚蠢的问题,但你为什么要创建一个永恒的循环?O 如果您尝试使用代码去除符号 >.> xD。
Source: http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
来源:http: //msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
回答by ntwana
I think the issue here is that this application will be adding 10MB with every loop it makes, and the loop is: "while(true)" which means it will adding these 10MBs till the application is stopped. So if it were to run for 100 loop it would have added close to 1GBs to RAM, and I'm assuming that it would have done this in less than 30 seconds. My point is you are trying to 10 megabyte's of memory per loop, in a never ending loop
我认为这里的问题是这个应用程序将在每次循环时添加 10MB,并且循环是:“while(true)”,这意味着它将添加这 10MB 直到应用程序停止。因此,如果它运行 100 次循环,它会为 RAM 添加接近 1GB,我假设它会在不到 30 秒的时间内完成此操作。我的观点是你试图在一个永无止境的循环中每个循环使用 10 兆字节的内存
回答by GeoffreyG
You can allocate MUCH MORE memory than ~2 GB by building your application to a 64-bit architecture, which requires that you create a new build configuration in Visual Studio, and that build of the application will only run on 64-bit versions of Windows. In .NET, using the default "Any CPU" build option for your application, I find that I am only able to allocate about 1.5 GB of memory from the heap (even on 64-bit Windows machine), which is because the application actually only runs in 32-bit mode when it is built in "Any CPU" mode. But by compiling to x64 architecture, you can allocate much, much more memory from the heap during the execution of your application, and I will explain how to create a x64 build for your application below:
通过将应用程序构建为 64 位体系结构,您可以分配比 ~2 GB 多得多的内存,这要求您在 Visual Studio 中创建新的构建配置,并且该应用程序的构建将仅在 64 位版本的 Windows 上运行. 在 .NET 中,为您的应用程序使用默认的“Any CPU”构建选项,我发现我只能从堆中分配大约 1.5 GB 的内存(即使在 64 位 Windows 机器上),这是因为应用程序实际上只有在“Any CPU”模式下构建时,才能在 32 位模式下运行。但是通过编译为 x64 架构,您可以在应用程序执行期间从堆中分配更多、更多的内存,我将在下面解释如何为您的应用程序创建 x64 构建:
Again, using the normal (default) "Any CPU" build option in your .NET project, your application will ALWAYS run under 32-bit mode, even on a 64-bit Windows OS. Therefore you won't be able to allocate more than about 1.5 to 2 GB of RAM memory during application execution. To run your .NET application in true 64-bit mode, you will need to go into the build configuration manager and create a build type for the x64 architecture, and then recompile your program for x64 explicitly using that build type. The x64 build mode option can be created for your .NET solution using the following steps:
同样,在您的 .NET 项目中使用普通(默认)“任何 CPU”构建选项,您的应用程序将始终在 32 位模式下运行,即使在 64 位 Windows 操作系统上也是如此。因此,在应用程序执行期间,您将无法分配超过 1.5 到 2 GB 的 RAM 内存。要在真正的 64 位模式下运行您的 .NET 应用程序,您需要进入构建配置管理器并为 x64 架构创建一个构建类型,然后使用该构建类型明确地为 x64 重新编译您的程序。可以使用以下步骤为 .NET 解决方案创建 x64 构建模式选项:
- In the Visual Studio "Solution Explorer" pane, right click on the Solution icon and choose the "Configuration Manager" option from the pop-up menu. This will open the build "Configuration Manager" dialog window for the .NET Solution file.
- On the right, top side of the build "Configuration Manager" dialog, click on the down arrow and select the "<new>" option. This will open the "New Solution Platform" dialog.
- In the "New Solution Platform" dialog, for the "Platform" option, choose "x64" from the drop-down menu. Then click the "OK" button and the new, x64 build option will now be available in the Configuration Manager dialog.
- Then, on the "Configuration Manager" dialog, select "x64" in the "Active Solution Platform" drop-down menu. The click the "Close" button.
- In the Visual Studio "Solution Explorer" pane, right click on the CS Project icon and choose the "Properties" option from the pop-up menu (the last option at the bottom of this menu). This will open the CS Project properties window.
- On left side of the CS Project properties window, click on the "Build" tab to show the build properties for your code project. At the top of this window, notice that the "Platform" should now say "x64" (as opposed to the default "Any CPU" option). If the "Platform" drop-down doesn't show "x64", you should select it now.
- Then just build your code and in the "bin" folder, you should now have a x64 folder with the new 64-bit build of your application within it.
- 在 Visual Studio 的“解决方案资源管理器”窗格中,右键单击“解决方案”图标并从弹出菜单中选择“配置管理器”选项。这将打开 .NET 解决方案文件的构建“配置管理器”对话框窗口。
- 在构建“配置管理器”对话框的右侧,顶部,单击向下箭头并选择“<new>”选项。这将打开“新解决方案平台”对话框。
- 在“New Solution Platform”对话框中,对于“Platform”选项,从下拉菜单中选择“x64”。然后单击“确定”按钮,新的 x64 构建选项现在将在“配置管理器”对话框中可用。
- 然后,在“配置管理器”对话框中,在“活动解决方案平台”下拉菜单中选择“x64”。单击“关闭”按钮。
- 在 Visual Studio 的“解决方案资源管理器”窗格中,右键单击 CS 项目图标并从弹出菜单中选择“属性”选项(此菜单底部的最后一个选项)。这将打开 CS 项目属性窗口。
- 在 CS 项目属性窗口的左侧,单击“构建”选项卡以显示代码项目的构建属性。在此窗口的顶部,请注意“平台”现在应显示“x64”(与默认的“任何 CPU”选项相反)。如果“平台”下拉列表未显示“x64”,则应立即选择它。
- 然后只需构建您的代码,在“bin”文件夹中,您现在应该有一个 x64 文件夹,其中包含您的应用程序的新 64 位构建版本。
Using a 64-bit build of your application on a 64-bit Windows OS will allow your program to allocate much more than ~2GB of memory, presumably up to 2^64 address spaces (if you have the RAM and disk space available, which are the real limiting factors as of the time of writing this response).
在 64 位 Windows 操作系统上使用您的应用程序的 64 位版本将允许您的程序分配超过 ~2GB 的内存,大概最多 2^64 个地址空间(如果您有可用的 RAM 和磁盘空间,是截至撰写此回复时的真正限制因素)。
If you're STILL running out of memory in your application, you can also increase the size of the Windows memory page file. On Windows, the page file allows the operating system to shift memory from RAM to the disk, if it runs out of RAM memory space. But there is a big time cost in shifting sections of RAM memory to and from the disk, so it may be a real hit on the performance of your application. Regardless of performance, by increasing the page size, you could (in theory) make the page file as large as there is free space available on the C: drive of your windows machine. In that case, your application would be able to allocate, for example, up to 4 TB of memory (or whatever amount of memory that your page file size is set to) during the execution of your program. To change the page file settings for your Windows machine, do the following:
如果您的应用程序内存仍然不足,您还可以增加 Windows 内存页面文件的大小。在 Windows 上,如果 RAM 内存空间不足,页面文件允许操作系统将内存从 RAM 转移到磁盘。但是将 RAM 内存部分移入和移出磁盘需要花费大量时间,因此这可能会真正影响应用程序的性能。不管性能如何,通过增加页面大小,您(理论上)可以使页面文件与 Windows 计算机的 C: 驱动器上的可用空间一样大。在这种情况下,您的应用程序将能够在您的程序执行期间分配,例如,最多 4 TB 的内存(或您的页面文件大小设置的任何内存量)。要更改 Windows 计算机的页面文件设置,
- Open the "System Properties" dialog by right clicking on "This PC" and choosing the "Properties" option on the pop-up menu. This can also be accomplished in later versions of Windows (Windows 10, Win 2012 Server, etc...) by going to "Start" > "Control Panel" > "System and Security" > "System".
- On the left side of the "System" dialog, click on the "Advanced System Properties" option. This will show the "Advanced" tab of the legacy "System Properties" dialog for Windows.
- On the "Advanced" tab of the "System Properties" dialog, click the "Settings" button in the "Performance" box. This will open the "Performance Options" dialog.
- On the "Performance Options" dialog, click on the "Advanced" tab to see the current size setting for the Windows memory page file.
- To increase the page file size, click on the "Change" button and the "Virtual Memory" dialog will be opened.
- On the "Virtual Memory" dialog, select the "C:" drive, then under "Custom Size", set the "Initial" and "Maximum" sizes. You can use any size up to the maximum amount of free space on the C: drive, but making this change will reserve that space for the page file on the hard drive.
- Then click "Ok" on all dialogs to commit the new settings. Then reboot your computer to ensure all changes have been completed properly and that the new page file settings are in operation.
- 通过右键单击“此电脑”并在弹出菜单中选择“属性”选项,打开“系统属性”对话框。这也可以在更高版本的 Windows(Windows 10、Win 2012 Server 等)中通过转到“开始”>“控制面板”>“系统和安全”>“系统”来完成。
- 在“系统”对话框的左侧,单击“高级系统属性”选项。这将显示 Windows 旧版“系统属性”对话框的“高级”选项卡。
- 在“系统属性”对话框的“高级”选项卡上,单击“性能”框中的“设置”按钮。这将打开“性能选项”对话框。
- 在“性能选项”对话框中,单击“高级”选项卡以查看 Windows 内存页面文件的当前大小设置。
- 要增加页面文件大小,请单击“更改”按钮,将打开“虚拟内存”对话框。
- 在“虚拟内存”对话框中,选择“C:”驱动器,然后在“自定义大小”下,设置“初始”和“最大”大小。您可以在 C: 驱动器上使用任意大小的最大可用空间,但进行此更改将为硬盘驱动器上的页面文件保留该空间。
- 然后在所有对话框上单击“确定”以提交新设置。然后重新启动计算机以确保所有更改都已正确完成并且新的页面文件设置正在运行。
Anyway, I hope this helps people understand why they can run into this 1.5 - 2 GB memory limitation issue in a .NET application, even when running on a 64-bit Windows machine. This can be a very confusing issue for people and I hope my explanation makes sense. Please feel free to message me with questions about this answer if needed.
无论如何,我希望这有助于人们理解为什么他们会在 .NET 应用程序中遇到这个 1.5 - 2 GB 内存限制问题,即使在 64 位 Windows 机器上运行也是如此。这对人们来说可能是一个非常令人困惑的问题,我希望我的解释有意义。如果需要,请随时向我发送有关此答案的问题。