.Net Почему я не могу получить более 11 ГБ выделенной памяти в процессе x64?

Я думал, что максимальное пространство пользователя для 64-битного процесса составляет 8 ТБ, но я сделал небольшой тест, и максимум, который я смог получить, составляет 10-11 ГБ.

Примечание. Мне не нужно столько памяти в процессе, я просто хочу понять, почему из любопытства.

Вот моя тестовая программа:

static void Main(string[] args)
{
    List<byte[]> list = new List<byte[]>();

    while (true)
    {
        Console.WriteLine("Press any key to allocate 1 more GB");
        Console.ReadKey(true);
        list.Add(new byte[1024 * 1024 * 1024]);

        Console.WriteLine("Memory size:");
        double memoryUsage = Process.GetCurrentProcess().PeakVirtualMemorySize64 / (double)(1024 * 1024 * 1024);
        Console.WriteLine(memoryUsage.ToString("0.00") + " GB");
        Console.WriteLine();
    }
}

EDIT:

Обновленная тестовая программа будет более детерминированной.

Чтобы принять ответ, я хотел бы знать, как рассчитывается реальная максимальная выделенная память, если 8TB является только теоретическим.

Ответы

Ответ 1

Он до 8 ТБ, а не 8 ТБ. Вы можете иметь до 8 ТБ, но вам нужен соответствующий файл RAM/swap.

Ответ 2

Это ваша машина.

У меня есть x64 с 8 ГБ оперативной памяти и 12-страничный файл подкачки, и я запустил вашу программу, и она превысила 16,23 ГБ.

EPILOG. Затем моя установка Win7 постепенно скользила в кому, поскольку критические процессы, по-видимому, были голодными.

EDIT. Если вы хотите понять, как Windows выделяет (то есть резервирует и фиксирует) память, читайте это: http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx и это: http://blogs.technet.com/markrussinovich/archive/2008/11/17/3155406.aspx

Так как .Net полагается на Windows для управления памятью, которую он использует для создания кучи GC, механика того, как Windows это отражается в том, как распределена память в .Net на низком уровне.

Ответ 3

Попробуйте выделить один кусок (в отличие от списка блоков 1 МБ):

Dim p As IntPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(New System.IntPtr(24 * (1024 ^ 3)))

Изменить. Учитывая ваш комментарий, у вас есть только 4 ГБ физической памяти, у вас действительно нет бизнеса, выделяющего > ~ 8 ГБ, и даже это подталкивает его.

Изменить -

Чтобы принять ответ, я хотел бы знать, как рассчитывается реальная максимальная выделенная память, если 8TB является только теоретическим.

Максимальный объем оперативной памяти, который вы можете выделить, вероятно, эквивалентен (размер файла страницы - размер всего в ОЗУ, кроме того, который не может или не будет выгружен) + (размер физической RAM - размер всего, что не может или не будет быть выгруженным, то есть тем, что необходимо для поддержания вашей системы... ядро, драйверы,.net и т.д.)

Конечно, файл страницы может расти...

Рано или поздно пейджинг на/с диска становится много, и ваша система замедляется до обхода и становится непригодной.

Прочитайте блог Марка Руссиновича:

Ответ 4

Я предполагаю, что это потому, что вы используете список, который, как мне кажется, имеет внутренний предел.

Посмотрите, что вы можете получить, если попробуете что-то вроде создания своего собственного старого школьного списка:

public class ListItem<T>
{
    public ListItem Parent;
    public T Value;

    public ListItem(ListItem<T> parent, T item)
    {
        this.Parent = parent;
        this.Value = item;
    }
}

Я написал почти этот точный код раньше (только мой элемент был int) и запускал его на машине с 32 процессорами и 128 ГБ оперативной памяти, он всегда искал один размер независимо от того, что и всегда было чем-то связанные с Int32.MaxValue, надеюсь, что это поможет.