Подтвердить что ты не робот

Выделение более 1000 МБ памяти в 32-битном .NET-процессе

Мне интересно, почему я не могу выделить более 1000 МБ памяти в своем 32-битном .NET-процессе. Следующее мини-приложение выдает исключение OutOfMemoryException после выделения 1000 МБ. Почему 1000 МБ, а не 1,8 ГБ? Могу ли я изменить настройки процесса?

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: Сбор мусора не помогает.

Изменить, чтобы уточнить, что я хочу: Я написал серверное приложение, которое обрабатывает очень большие объемы данных перед записью в базу данных/диск. Вместо того, чтобы создавать временные файлы для всего, я написал кеш в памяти, что делает все очень быстрым. Но память ограничена, поэтому я попытался выяснить, каковы пределы. И задавался вопросом, почему моя небольшая тестовая программа выбросила OutOfMemoryException после 1000 МБ.

4b9b3361

Ответ 1

Предел виртуального адресного пространства для процесса Win32 составляет 1,5 ГБ (не совсем верно). Кроме того, в .NET frameworks есть ограничитель для% памяти, которую может потреблять процесс .NET. У machine.config есть элемент processModel с атрибутом memoryLimit, который является% доступной памяти, которую может потреблять процесс. Значение по умолчанию - 60%.

Если машина, на которой вы работаете, имеет 2 ГБ памяти или вы не включили переключатель /3GB в вашем BOOT.INI, тогда вы получите ~ 1,3 ГБ памяти на каждый процесс.

Я не могу найти статью в KB, но если я правильно помню,.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.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

Ответ 2

Наличие огромных блоков памяти никогда не является хорошей идеей, даже на 64-битной. Вы получаете большие проблемы с непрерывной памятью и фрагментацией.

Проблема здесь заключается в нахождении смежного блока. Вы можете попробовать включить режим 3gb (что может помочь ему найти еще несколько байтов), но я рекомендую действительно. Ответы здесь:

  • использовать меньше памяти
  • использовать базу данных/файловую систему.
  • использовать x64

Вы также можете прочитать блог Эрика Липперта (у него, кажется, есть запись в блоге для каждого общего .NET-вопроса...)

Ответ 3

Недавно я делал обширное профилирование по ограничениям памяти в .NET на 32-битном процессе. Мы все обмануты идеей о том, что мы можем выделить до 2,4 ГБ (2 ^ 31) в .NET-приложении, но, к сожалению, это не так:( Прикладной процесс имеет столько места для использования, и операционная система отлично справляется работа, управляющая им для нас, однако сама .NET, похоже, имеет свои собственные накладные расходы, что составляет примерно 600-800 МБ для типичных приложений реального мира, которые вызывают ограничение памяти. Это означает, что как только вы выделите массив целых чисел, который принимает 1.4 ГБ, вы должны ожидать увидеть OutOfMemoryException().

Очевидно, что в 64-битном листе это происходит позже (пусть чат через 5 лет:)), но общий размер всего в памяти также растет (я нахожу его от 1,7 до ~ 2 раза) из-за увеличенного размера слова.

То, что я точно знаю, это то, что идея виртуальной памяти от операционной системы определенно НЕ дает вам практически бесконечное пространство для размещения в рамках одного процесса. Он доступен только для того, чтобы полные 2,4 ГБ были адресованы всем (многим) приложениям, запущенным за один раз.

Я надеюсь, что это понимание поможет несколько.

Я изначально ответил на что-то связанное здесь (я все еще новичок, поэтому не уверен, как я должен делать эти ссылки):

Есть ли предел памяти для одного .NET-процесса

Ответ 4

Вы можете выделить МНОГО БОЛЬШЕ памяти, чем ~ 2 ГБ, создав приложение в 64-битной архитектуре, для чего требуется создать новую конфигурацию сборки в Visual Studio, а сборка приложения будет работать только на 64-битной версии Windows. В .NET, используя опцию сборки "Любой процессор" по умолчанию для вашего приложения, я обнаружил, что я могу выделить около 1,5 ГБ памяти из кучи (даже на 64-битной машине Windows), потому что приложение действительно работает только в 32-битном режиме, когда он встроен в режим "Любой процессор". Но, компилируя в архитектуру x64, вы можете выделить намного больше памяти из кучи во время выполнения вашего приложения, и я объясню, как создать сборку x64 для вашего приложения ниже:

Опять же, используя стандартную (по умолчанию) версию "Любой процессор" в вашем проекте .NET, ваше приложение ВСЕГДА будет работать под 32-разрядным режимом даже в 64-разрядной ОС Windows. Поэтому при выполнении приложения вы не сможете выделить более 1,5-2 ГБ оперативной памяти. Чтобы запустить приложение .NET в истинном 64-битном режиме, вам нужно будет войти в диспетчер конфигурации сборки и создать тип сборки для архитектуры x64, а затем перекомпилировать свою программу для x64, явно используя этот тип сборки. Для режима .NET можно создать параметр режима сборки x64, выполнив следующие шаги:

  • В области Visual Studio "Solution Explorer" щелкните правой кнопкой мыши значок "Решение" и выберите "Диспетчер конфигурации" во всплывающем меню. Это откроет диалоговое окно сборки "Configuration Manager" для файла .NET Solution.
  • Справа вверху диалогового окна сборки "Configuration Manager" щелкните стрелку вниз и выберите опцию "&ltnew > ". Откроется диалоговое окно "Новая платформа решений".
  • В диалоговом окне "Новая платформа решений" для опции "Платформа" выберите "x64" в раскрывающемся меню. Затем нажмите кнопку "ОК", и новая опция сборки x64 теперь будет доступна в диалоговом окне "Диспетчер конфигурации".
  • Затем в диалоговом окне "Configuration Manager" выберите "x64" в раскрывающемся меню "Active Solution Platform". Нажмите кнопку "Закрыть".
  • В области "Проводник" Visual Studio щелкните правой кнопкой мыши значок CS Project и выберите "Свойства" в всплывающем меню (последний параметр внизу этого меню). Это откроет окно свойств проекта CS.
  • В левой части окна свойств проекта CS щелкните вкладку "Создать", чтобы отобразить свойства сборки для вашего проекта кода. В верхней части этого окна обратите внимание, что теперь "Платформа" должна сказать "x64" (в отличие от опции "Любой процессор" по умолчанию). Если раскрывающийся список "Платформа" не показывает "x64", вы должны выбрать его сейчас.
  • Затем просто создайте свой код и в папке "bin", теперь у вас должна быть папка x64 с новой 64-разрядной версией вашего приложения.

Использование 64-разрядной сборки вашего приложения в 64-разрядной ОС Windows позволит вашей программе выделять гораздо больше ~ 2 ГБ памяти, предположительно до 2 ^ 64 адресных пространств (если у вас есть ОЗУ и дисковое пространство доступные, которые являются реальными ограничивающими факторами на момент написания ответа).

Если у вас STILL нехватка памяти в вашем приложении, вы также можете увеличить размер файла страницы памяти Windows. В Windows файл страницы позволяет операционной системе переводить память из ОЗУ на диск, если в нем не хватает памяти оперативной памяти. Но при переключении разделов оперативной памяти на диск и с диска большие затраты времени, поэтому это может сильно повлиять на производительность вашего приложения. Независимо от производительности, увеличивая размер страницы, вы могли (теоретически) сделать файл с файлом настолько большим, насколько это доступно на диске C: на вашем компьютере Windows. В этом случае ваше приложение сможет выделять, например, до 4 ТБ памяти (или любой объем памяти, на который установлен размер файла вашей страницы) во время выполнения вашей программы. Чтобы изменить параметры файла страницы для вашего компьютера Windows, выполните следующие действия:

  • Откройте диалоговое окно "Свойства системы" , щелкнув правой кнопкой мыши на "Этот ПК" и выбрав "Свойства" во всплывающем меню. Это также можно выполнить в более поздних версиях Windows (Windows 10, Win 2012 Server и т.д.), Перейдя в "Начать" > "Панель управления" > "Система и безопасность" > "Система".
  • В левой части диалогового окна "Система" нажмите "Дополнительные параметры системы". Это покажет вкладку "Дополнительно" в устаревшем диалоговом окне "Свойства системы" для Windows.
  • На вкладке "Дополнительно" диалогового окна "Свойства системы" нажмите кнопку "Настройки" в поле "Производительность". Откроется диалоговое окно "Параметры производительности".
  • В диалоговом окне "Параметры производительности" перейдите на вкладку "Дополнительно" , чтобы просмотреть текущую настройку размера файла страницы памяти Windows.
  • Чтобы увеличить размер файла страницы, нажмите кнопку "Изменить", и откроется диалоговое окно "Виртуальная память".
  • В диалоговом окне "Виртуальная память" выберите диск "C:", затем в разделе "Пользовательский размер" установите значения "Начальный" и "Максимальный". Вы можете использовать любой размер с максимальным объемом свободного места на диске C:, но внесение этого изменения зарезервирует это пространство для файла страницы на жестком диске.
  • Затем нажмите "ОК" во всех диалоговых окнах, чтобы зафиксировать новые настройки. Затем перезагрузите компьютер, чтобы убедиться, что все изменения выполнены правильно и что новые параметры файла страницы находятся в работе.

В любом случае, я надеюсь, что это поможет людям понять, почему они могут столкнуться с этой проблемой ограничения памяти на 1,5-2 ГБ в приложении .NET даже при работе на 64-битной машине Windows. Это может быть очень запутанной проблемой для людей, и я надеюсь, что мое объяснение имеет смысл. Пожалуйста, не стесняйтесь сообщать мне с вопросами об этом ответе, если это необходимо.

Ответ 5

Я думаю, проблема в том, что это приложение будет добавлять 10 МБ с каждым циклом, который он делает, и цикл: "while (true)", что означает, что он добавит эти 10 МБ до тех пор, пока приложение не будет остановлено. Так что, если бы он работал в течение 100 циклов, он добавил бы около 1 ГБ в ОЗУ, и я предполагаю, что это сделало бы это менее чем за 30 секунд. Я хочу сказать, что вы пытаетесь сделать 10 мегабайт памяти за цикл, в бесконечном цикле

Ответ 6

Мне очень жаль, если я не понял вашу точку зрения, но:

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);
        }
    }
}

Вы пробовали использовать метод? И это может быть глупый вопрос, но почему вы создали вечный цикл? O, если вы попробуете код кодировать символы > . > XD.

Источник: http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx