Проверьте возможность выделения определенного объема памяти на платформе x64 - PullRequest
0 голосов
/ 29 сентября 2011

У меня есть приложение, которое использует много памяти, но это нормальная ситуация.Мне нужно сообщить пользователю, если недостаточно памяти для выполнения операции.Я знаю, что процесс x86 может выделить менее 2 ГБ пользовательской памяти.Но процесс 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, и мне это удалось.Мне удалось выделить 4 ГБ памяти на компьютере x64 с физической памятью 4 ГБ, и после этого у меня возникло исключение OutOfMemory.

Как проверить возможность выделения определенного объема памяти на платформе x64

Ответы [ 2 ]

2 голосов
/ 29 сентября 2011

Это совсем не так, как работает Windows.Это виртуальная память операционная система.Вы получаете OOM, когда больше не можете выделять больше виртуальной памяти.Физическая память (RAM) не имеет к этому никакого отношения.

Когда ваш код работает в 32-режиме, он имеет 2 гигабайта адресуемой виртуальной памяти.OOM происходит, когда вы пытаетесь выделить кусок памяти, и не остается дыры, достаточно большой, чтобы соответствовать запросу.Большие распределения проваливаются раньше.Никогда не думайте, что вы можете выделить все, когда программа выделяет больше гигабайта, вероятность того, что она не сможет начать быстро расти.

Проблема, решаемая в 64-битной операционной системе.Размер адресуемой виртуальной памяти находится где-то между 192 гигабайтами и 2 терабайтами, в зависимости от версии Windows.Теперь ограничением является то, сколько из этого огромного адресного пространства сопоставимо .Максимальный размер файла подкачки.Что является движущейся целью, файл подкачки используется другими процессами.Когда вы приближаетесь к пределу, у вас возникают гораздо большие проблемы, например, сбор мусора, который занимает вечность.Вы просто больше не беспокоитесь, рассказывая пользователю о том, как близко к нему приходит OOM, она уже знает по вашей программе, что она больше не реагирует.

Windows Internals - хорошая книга, чтобы узнать больше о том, как работает Windows.

0 голосов
/ 29 сентября 2011

См. MemoryFailPoint , чтобы узнать, как проверить распределение без непредсказуемости попытки перехвата исключения OutOfMemoryException. Обратите внимание, что это работает как для x86, так и для x64.

...