Выделение более 1000 МБ памяти в 32-разрядном процессе .NET - PullRequest
19 голосов
/ 10 июля 2009

Мне интересно, почему я не могу выделить более 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 МБ.

Ответы [ 6 ]

16 голосов
/ 10 июля 2009

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

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

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

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

7 голосов
/ 10 июля 2009

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

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

Я не могу найти статью в КБ, но, если я правильно помню, .NET 1.x не может обращаться за пределами 1,5 ГБ (1,8 ГБ?) Независимо от ваших настроек.

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 голосов
/ 16 декабря 2009

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

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

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

Надеюсь, это понимание поможет.

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

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

0 голосов
/ 12 декабря 2017

Вы можете выделить НАМНОГО БОЛЬШЕ памяти, чем ~ 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 явно, используя этот тип сборки. Параметр режима сборки x64 можно создать для вашего решения .NET, выполнив следующие действия:

  1. На панели «Обозреватель решений» Visual Studio щелкните правой кнопкой мыши значок «Решение» и выберите «Configuration Manager» во всплывающем меню. Откроется диалоговое окно «Диспетчер конфигурации» для файла .NET Solution.
  2. Справа, в верхней части диалогового окна «Диспетчер конфигурации», нажмите стрелку вниз и выберите параметр «& ltnew & gt». Откроется диалоговое окно «Новая платформа решений».
  3. В диалоговом окне «Новая платформа решений» для параметра «Платформа» выберите «x64» в раскрывающемся меню. Затем нажмите кнопку «ОК», и новый вариант сборки x64 теперь будет доступен в диалоговом окне Configuration Manager.
  4. Затем в диалоговом окне «Диспетчер конфигурации» выберите «x64» в раскрывающемся меню «Active Solution Platform». Нажмите кнопку «Закрыть».
  5. В панели «Обозреватель решений» Visual Studio щелкните правой кнопкой мыши значок CS Project и выберите параметр «Свойства» во всплывающем меню (последний параметр в нижней части этого меню). Откроется окно свойств проекта CS.
  6. В левой части окна свойств CS Project нажмите на вкладку «Build», чтобы отобразить свойства сборки для вашего проекта кода. В верхней части этого окна обратите внимание, что «Платформа» должна теперь сказать «x64» (в отличие от опции «Любой процессор» по умолчанию). Если в раскрывающемся списке «Платформа» не отображается «x64», выберите его сейчас.
  7. Затем просто соберите свой код и в папке «bin» теперь у вас должна быть папка x64 с новой 64-битной сборкой вашего приложения.

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

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

  1. Откройте диалоговое окно «Свойства системы», щелкнув правой кнопкой мыши «Этот компьютер» и выбрав пункт «Свойства» во всплывающем меню. Это также может быть выполнено в более поздних версиях Windows (Windows 10, Win 2012 Server и т. Д.), Перейдя в «Пуск» & gt «Панель управления» & gt «Система и безопасность» & gt «Система».
  2. В левой части диалогового окна «Система» выберите параметр «Дополнительные свойства системы». Появится вкладка «Дополнительно» устаревшего диалога «Свойства системы» для Windows.
  3. На вкладке «Дополнительно» диалогового окна «Свойства системы» нажмите кнопку «Настройки» в поле «Производительность». Откроется диалоговое окно «Параметры производительности».
  4. В диалоговом окне «Параметры производительности» перейдите на вкладку «Дополнительно», чтобы увидеть текущие настройки размера файла страницы памяти Windows.
  5. Чтобы увеличить размер файла подкачки, нажмите кнопку «Изменить», и откроется диалоговое окно «Виртуальная память».
  6. В диалоговом окне «Виртуальная память» выберите диск «C:», затем в разделе «Нестандартный размер» установите размеры «Начальный» и «Максимальный». Вы можете использовать любой размер вплоть до максимального свободного места на диске C :, но внесение этого изменения зарезервирует это пространство для файла подкачки на жестком диске.
  7. Затем нажмите «ОК» во всех диалоговых окнах, чтобы зафиксировать новые настройки. Затем перезагрузите компьютер, чтобы убедиться, что все изменения были выполнены правильно и что новые параметры файла подкачки работают.

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

0 голосов
/ 17 декабря 2014

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

0 голосов
/ 20 апреля 2012

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...