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

本文关键字:内存 可能性 x64 平台 分配 检查 | 更新日期: 2023-09-27 18:09:58

我有一个应用程序使用了大量内存,但这是正常情况。如果没有足够的内存来执行操作,我需要通知用户。我知道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平台上分配一定量内存的可能性?

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

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

当你的代码在32模式下运行时,它有2gb的可寻址虚拟内存。当您尝试分配一块内存并且没有足够大的空间来容纳请求时,就会发生OOM。较大的分配较早失败。永远不要以为你可以分配所有的内存,一旦一个程序分配了超过1gb的内存,它失败的几率就会迅速增加。

在64位操作系统上解决的问题。可寻址虚拟内存大小介于192gb和2tb之间,具体取决于Windows版本。现在的限制是这个巨大的地址空间中有多少是可映射的。分页文件的最大大小。这是一个移动的目标,分页文件由其他进程共享。当你接近极限时,你就会遇到更大的问题,比如垃圾收集需要花很长时间。你不必再费心告诉用户她离OOM有多近了,她已经从你的程序不再响应中知道了。

请参阅MemoryFailPoint,了解一种验证分配的方法,而不需要尝试拦截OutOfMemoryException的不可预测性。注意,这既适用于x86,也适用于x64。