检查在x64平台上分配一定量内存的可能性

时间:2011-09-29 13:43:03

标签: c# .net 64-bit out-of-memory

我有一个使用大量内存的应用程序,但这是正常情况。如果没有足够的内存来执行操作,我需要通知用户。 我知道x86进程可以分配少于2 GB的用户内存。但是x64进程可以根据物理内存分配更多的用户内存。 之前该应用程序仅支持x86平台,我使用了以下代码:

private bool CheckMemoryInternal(long bytesCountToCheck) {

 // Get physical memory of the current workstation
 long memSize = long.MaxValue;
 NativeMethods.MEMORYSTATUSEX memory = new NativeMethods.MEMORYSTATUSEX();
 memory.dwLength = (uint)System.Runtime.InteropServices.Marshal.SizeOf(memory);
 if (UnsafeNativeMethods.GlobalMemoryStatusEx(ref memory))
   memSize = (long)memory.ullTotalPhys;

 // Don't know the reason, but this value is measured in kilobytes, and MSDN wrote that it is measured in bytes
 long maxWorkingSet = (long)Process.GetCurrentProcess().MaxWorkingSet * 1024;

 // Obtain the maximal amount of memory for our app
 // If the current amount of physical memory is less than maxWorkingSet, we can use it, but it should not be less than 512 MB for our application.
 long maxMemorySize = Math.Min(Math.Max(512 * OneMegaByte, memSize), maxWorkingSet);

 return bytesCountToCheck + Process.GetCurrentProcess().PrivateMemorySize64 < maxMemorySize;
}

我知道另一种方法:

private bool CheckMemoryInternal(long megaBytes) {

  try {
    byte[][] chunks = new byte[megaBytes][];
    for (int i = 0; i < chunks.Length; i++)
      chunks[i] = new byte[1024 * 1024];
    return true;
  }
  catch (OutOfMemoryException) {
    return false;
  }
}

但我不喜欢这样。

现在我将应用程序迁移到x64平台。起初,代码示例无法正常工作。用于分配的允许内存的最大大小与x86应用程序中的最大大小相同(MaxWorkingSet(32位)== MaxWorkingSet(64位))。 我试图在x64机器上分配大量内存,但我成功了。我能够在具有4Gb物理内存的x64机器上分配4Gb内存,之后我得到了OutOfMemory异常。

如何检查在x64平台上分配一定数量内存的可能性?

2 个答案:

答案 0 :(得分:2)

这根本不是Windows的工作方式。它是虚拟内存操作系统。当您无法再分配虚拟内存时,您将获得OOM。物理内存(RAM)与它无关。

当您的代码在32模式下运行时,它有2千兆字节的可寻址虚拟内存。当你试图分配一块内存并且没有留下足够大的空洞来满足请求时,会发生OOM。大型分配早先失败。永远不要假设你可以分配所有东西,一旦一个程序分配超过一千兆字节,它将失败的可能性开始迅速增加。

在64位操作系统上解决的问题。可寻址的虚拟内存大小介于192千兆字节和2千兆字节之间,具体取决于Windows版本。现在的约束是,这个巨大的地址空间有多少 mappable 。页面文件的最大大小。哪个是移动目标,页面文件由其他进程共享。当你接近极限时,你会遇到更大的问题,比如永远需要的垃圾收集。你只是不再费心告诉用户她有多接近OOM,她已经知道你的程序不再响应了。

Windows Internals是一本很好的书,可以了解有关Windows工作方式的更多信息。

答案 1 :(得分:0)

有关验证分配的方法,请参阅MemoryFailPoint,而不会出现尝试拦截OutOfMemoryException的不可预测性。请注意,这适用于x86以及x64。