System outofmemoryexception как исправить
Перейти к содержимому

System outofmemoryexception как исправить

  • автор:

Устранение неполадок нехватки памяти (System.OutOfMemoryException) в ASP.NET

Эта статья поможет устранить ошибки нехватки памяти в ASP.NET.

Исходная версия продукта: ASP.NET
Исходный номер базы знаний: 2020006

Симптомы

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

Прежде чем мы рассмотрим сведения об устранении неполадок OutOfMemoryException , важно понять, что вызывает эту проблему. Вопреки мнению многих разработчиков, установленный объем ОЗУ не влияет на возможность OutOfMemoryException использования . 32-разрядная операционная система может использовать 4 ГБ виртуального адресного пространства независимо от объема физической памяти, установленной в коробке. Из этого 2 ГБ зарезервировано для операционной системы (память в режиме ядра), а 2 ГБ выделяется для процессов в пользовательском режиме. 2 ГБ, выделенные для памяти в режиме ядра, совместно используются всеми процессами, но каждый процесс получает собственные 2 ГБ адресного пространства в режиме пользователя. Предполагается, что вы не работаете с включенным параметром /3gb .

Когда приложению необходимо использовать память, оно резервирует блок виртуального адресного пространства, а затем фиксирует память из этого блока. Именно это делает сборщик мусора (GC) платформа .NET Framework, когда ему требуется память для увеличения управляемых кучи. Когда сборке мусора требуется новый сегмент для кучи небольших объектов (где находятся объекты размером менее 85 КБ), выделяется 64 МБ. Когда требуется новый сегмент для кучи больших объектов, выделяется 16 МБ. Эти большие выделения должны быть удовлетворены из смежных блоков 2 ГБ адресного пространства, с которыми должен работать процесс. Если операционная система не может удовлетворить запрос GC на непрерывный блок памяти, System.OutOfMemoryException возникает (OOM).

32-разрядный процесс, выполняющийся в 64-разрядной операционной системе, может обрабатывать 4 ГБ памяти в пользовательском режиме, а 64-разрядный процесс, запущенный в 64-разрядной операционной системе, может обрабатывать 8 ТБАЙТ памяти в пользовательском режиме, поэтому OOM в 64-разрядной операционной системе вряд ли. Можно столкнуться с OOM в 32-разрядном процессе, работающем в 64-разрядной операционной системе, но обычно это не происходит, пока процесс не использует около 3 ГБ частных байтов.

Условие OOM может отображаться по двум причинам.

  1. Процесс использует большой объем памяти (обычно более 800 МБ в 32-разрядной среде).
  2. Виртуальное адресное пространство фрагментировано, что снижает вероятность того, что большое непрерывное выделение будет успешным.

Также можно увидеть условие OOM из-за сочетания 1 и 2. Дополнительные сведения см . в разделе Устранение неполадок System.OutOfMemoryExceptions в ASP.NET.

При возникновении OOM вы можете заметить один или несколько из следующих симптомов:

  • Происходит сбой приложения. Дополнительные сведения см. в разделе Кто этот парень OutOfMemory и почему он делает сбой процесса, когда у меня осталось много памяти?.
  • Приложение может испытывать большой объем памяти, как указано в диспетчере задач или Монитор производительности.
  • Обработка запросов может занять много времени. В службах IIS 7 можно использовать устранение неполадок с неудачными запросами с помощью трассировки в IIS 7 для устранения неполадок с длительными запросами.
  • Пользователи могут сообщать об ошибке в приложении из-за OOM.

Когда дело доходит до определения причины состояния OOM, вы фактически работаете над определением причины ситуации с большим объемом памяти или фрагментированного адресного пространства. Хотя мы не можем задокументировать все возможные причины таких ситуаций, существуют некоторые распространенные причины, которые мы видим регулярно.

В следующих сведениях описываются распространенные причины возникновения условий OOM и способы устранения каждой из этих причин.

Объединение строк

Строки в управляемом приложении (приложении, написанном с помощью платформа .NET Framework) неизменяемы. Если строке присваивается новое значение, создается копия существующей строки. И новое значение присваивается новой строке. Обычно это не вызывает никаких проблем. Но при объединении большого количества строк это приводит к гораздо большему выделению строк, чем может себе понять разработчик. И это может привести к росту памяти и условиям OOM.

Чтобы избежать OOM из-за объединения строк, убедитесь, что используется StringBuilder класс . Дополнительные сведения см . в статье Повышение производительности объединения строк в Visual C#.

Фрагментация в управляемой куче

Сборщик мусора (GC) в управляемом приложении сжимает кучи, чтобы уменьшить объем фрагментации. Однако можно закрепить объекты в управляемом приложении. Закрепленные объекты нельзя перемещать во время сжатия кучи. Это приведет к изменению адреса, по которому находится объект . Если приложение закрепляет большое количество объектов и (или) закрепляет объекты в течение длительного времени, это может привести к фрагментации в управляемой куче. Это может привести к тому, что сборка мусора увеличивает управляемую кучу чаще и вызывает состояние OOM.

Мы работали над минимизацией условий OOM из-за закрепления с платформа .NET Framework 1.0. В каждой версии были внесены добавочные улучшения. Тем не менее, существуют шаблоны проектирования, которые можно реализовать, что будет полезно, если вам нужно закрепить объекты.

Фрагментация в пространстве виртуального адреса (VA)

Каждому процессу выделяется определенный объем памяти, и эта память представляет пространство va для процесса. Если пространство va становится фрагментировано, это повышает вероятность того, что GC не сможет получить большой блок непрерывной памяти для увеличения управляемых кучи. И это может привести к состоянию OOM.

Фрагментация в пространстве va часто вызвана одним или несколькими из следующих сценариев:

  • Загрузка одних и тем же сборок в несколько доменов приложения. Если необходимо использовать сборку в нескольких приложениях, работающих в одном пуле приложений, назовите сборку строгим именем и установите ее в GAC. Это позволит убедиться, что сборка загружается в процесс только один раз.
  • Запуск приложения в рабочей среде с атрибутом отладки элемента, для которых задано значение true .
    • Атрибут отладки элемента должен быть false в рабочей среде.
    • Вы можете использовать конфигурацию , чтобы гарантировать, что отладка всегда отключена в продукте. Дополнительные сведения см. в разделе Элемент развертывания (схема ASP.NET параметров).

    Возврат больших наборов данных

    При использовании данных из базы данных или другого источника данных важно ограничить объем возвращаемых данных. Например, кэширование результата запроса, возвращающего всю таблицу базы данных, чтобы избежать затрат на извлечение частей данных из базы данных при необходимости, не является хорошим подходом. Это может легко вызвать большой объем памяти и привести к состоянию OOM. Разрешение пользователю запустить аналогичный запрос — еще один распространенный способ создания ситуации с большим объемом памяти. Например, верните всех сотрудников компании или всех клиентов в штате Техас с фамилией, начинаемой с буквы S.

    Всегда ограничивайте объем данных, которые могут быть возвращены из базы данных. Не разрешайте запросы, например, так как SELECT * FROM. . . вы не можете контролировать объем данных, отображаемых на странице.

    Не менее важно убедиться, что результат больших данных не отображается в элементах пользовательского интерфейса, таких как элемент управления GridView. Помимо памяти, необходимой для возвращаемых данных, вы также будете использовать большие объемы данных в строках и элементах пользовательского интерфейса, необходимых для отрисовки результатов. Реализуя разбиение по страницам и проверяя входные данные, чтобы большие наборы данных не возвращались, можно избежать этой проблемы.

    Запуск в рабочей среде с включенной трассировкой

    ASP.NET трассировка — это мощная функция для устранения неполадок приложений. Но его никогда не следует оставлять в рабочей среде. ASP.NET трассировка использует структуры данных, например DataTables для хранения сведений трассировки, и со временем они могут привести к большому объему памяти, что может привести к OOM.

    Трассировка должна быть отключена в рабочей среде. Это можно сделать, задав enabled атрибуту элемента значение false в файлеweb.config . Включение розничного развертывания с помощью также отключает трассировку в приложениях.

    Утечка собственных ресурсов

    Многие управляемые ресурсы также будут использовать собственные ресурсы. Так как сборка мусора не очищает собственные ресурсы, разработчик отвечает за реализацию и вызов метода Dispose для очистки собственных ресурсов. Если вы используете тип, реализующий IDisposable интерфейс, и не вызываете Dispose метод, вы рискуете утечкой собственных ресурсов и вызовом условия OOM.

    Эти объекты должны реализовывать iDisposable интерфейс и вызывать Dispose метод для этих объектов, если они больше не нужны.

    Обратная связь

    Были ли сведения на этой странице полезными?

    Как устранить OutOfMemoryException?

    Произошло падение от OutOfMemoryException. Как понять в чем проблема? Хочу разобраться какие вообще могут быть варианты, как их подтвердить и устранить. Прошу поправить если мои предположения не верны и дополнить полезной информацией. Читал о таких ситуациях: 1) Отсутствует требуемый непрерывный объем памяти. При этом свободной памяти еще может быть много, просто она фрагментирована. Способ определить: если не одна из последующих ситуаций не выявлена. Решение: ?(похоже что этим занимается CLR) 2) Физически не достаточно памяти для данной программы и программа написана не оптимально. Способ определить: Предположил что можно определить физический недостаток памяти посмотрев на монитор ресурсов(к примеру если нагрузка >90% — не достаточно памяти). Предположил что можно определить проблемы с производительностью с помощью дампа с кучей(хотя как это делать еще не знаю) или если знать узкие места системы. Решение: если узких мест не знаем — ждать второго падения и собирать дамп(какой инструмент порекомендуете для прод среды?), после менять код(оптимизировать, высвобождать неуправляемые ресурсы с помощью Dispose в проблемных местах) 3) Физически не достаточно памяти для данной программы и программа написана оптимально. Способ определить: из пункта 2. Решение: маcштабировать сервера. 4) Переполнение StringBuilder. Способ определить: проследить за местами их использования StringBuilder. Решение: использовать конструктор StringBuilder() или менять логику программы. 5) Ограничение 32-bit only 2GB per object. Способ определить: Посмотреть диспетчером задач к примеру что x32 и что обьем памяти близок к 2GB. (Тут имеет значение битность OS или только сборка?) Решение: делать сборку 64-bit, или если это возможно поставить в app.config настройку gcAllowVeryLargeObjects enabled=»true».

    Отслеживать
    AndreyMagnificent
    задан 9 янв 2019 в 11:33
    AndreyMagnificent AndreyMagnificent
    165 1 1 серебряный знак 10 10 бронзовых знаков
    Посмотри что в памяти лежит. В Rider есть вкладка для этого. В VS тоже должно быть что-то подобное.
    9 янв 2019 в 13:30

    Дмитрий Полянин, спасибо. Я думал что Rider и VS только вне прода способны на это (в режиме дебага или по уже созданному дамп файлу с кучей), но проверю.

    9 янв 2019 в 13:39

    Еще System.Drawing.Bitmap.Clone может бросать out of memory если просто не угадать с координатами (чуть-чуть выйти за пределы rect) — там криво выбран тип исключения. Еще может падать Out Of Memory если памяти не хватит для подгрузки сборки (видел ровно один раз, на проекте злоупотребляли аппдоменами с огромным количеством динамики)

    – user177221
    9 янв 2019 в 13:41

    Dispose и вообще работа с неуправляемыми ресурсами, кстати, к освобождению памяти не имеет никакого отношения. Неуправляемые ресурсы — это, в основном, handles, у них свои лимиты.

    – user177221
    9 янв 2019 в 13:42

    PashaPash, спасибо. Возможно я сейчас не прав, но похоже во время использования handles также возникает потребление памяти. И в случае их некорректной обработки также будет утечка памяти. Следовательно устранив некорректную обработку устраним и утечку памяти.

    Тема: Фронт: Ошибка памяти.

    Ed_888 вне форума

    При переходе на версию 4.3 столкнулся с тем, что Фронту (Варипосы 1 Ггб ОЗУ) катастрофически не хватает памяти при запуске, в следствии этого возникает ошибка:

    [2015-12-15 11:31:47,703] ERROR [20] [RemoteMethodCaller:WrapExceptions:0] — Unexpected exception
    System.AggregateException: One or more errors occurred. —> System.OutOfMemoryException: Exception of type ‘System.OutOfMemoryException’ was thrown.
    at System.Text.StringBuilder.ToString()
    at System.Xml.XmlTextReaderImpl.ParseText()
    at System.Xml.XmlTextReaderImpl.ParseElementContent()
    at System.Xml.XmlTextReaderImpl.Read()
    at System.Xml.XmlTextReader.Read()

    На каких-то кассах помогает установка фиксированной выделенной памяти в 2048 Мб, установка компонент Frameworka 4.0, его обновления unoff_NDP40-KB2974335-x86, где-то только переустановка ОС, но в любом случае, в диспетчере задач видно, как растет память до 1.6 Ггб, потом либо падает в ошибку, либо сразу падает до ~500 Мб и загрузка успешно продолжается.
    Какие варианты есть, докупать память? или Айко должны как-то исправить ситуацию?

    15.12.2015, 14:48 #2

    Speaker вне форума

    Сведущий Регистрация 05.08.2015 Адрес Ярославль Сообщений 76 Поблагодарил(а) 0 Благодарностей: 1 (сообщений: 1)

    Ошибка в ранних версиях .Net Framework 4.0.
    Наш дистрибутив содержит базовую версию 4.0.30319.1. Microsoft не предоставляет единого инсталлятора, содержащего полную версию .Net Framework 4.0 со всеми обновлениями (для .Net 3.5, кстати, выпускались Service Pack’и). Нам остаётся только рекомендовать пользователям устанавливать исправления .Net Framework штатными средствами Windows Update.

    Если на машине где работают с front установлена windows 7 или выше необходимо установить framework 4.6,
    Например отсюда http://www.microsoft.com/ru-RU/downl. aspx?id=44927

    Если ОС windows XP или подобные POS ready 2009, то необходимо установить пакет KB2974335 ( в аттаче) и поставить все обновления через WindowsUpdate

    Системные требования к оборудованию для использования ПО iiko
    Стационарный терминал официанта/ бармена/ кассира.
     Процессор: Atom D525, частота не менее 1.8GHz;
     Оперативная память: рекомендуется 2GB RAV;
     Свободное место на жестком диске: 40GB;
     Сеть: 100Mbit Ethernet;
     Разрешение дисплея 1024х768;
     Операционная система: Windows XP Professional SP3 , Windows 7 Pro SP1, Windows 2009
    POS Ready SP3

    26.12.2015, 23:12 #3

    Ed_888 вне форума

    Интересующийся Регистрация 27.10.2014 Адрес г. Тула Сообщений 47 Поблагодарил(а) 2 Благодарностей: 1 (сообщений: 1)

    Нет логики, где-то, даже не приходится устанавливать обновления Framework KB2974335-x86, где-то устанавливать их, переустанавливать самого клиента, где-то вообще ничего не делать, Фронты запускаются сразу и это при учете 1Ггб ОЗУ.
    Сегодня отказалась запускаться ГК, при применении патча на Офис 4.3.1, как объяснить, где логика?
    Используются Варипосы на D525, win XP.

    27.12.2015, 23:49 #4

    Ed_888 вне форума

    Интересующийся Регистрация 27.10.2014 Адрес г. Тула Сообщений 47 Поблагодарил(а) 2 Благодарностей: 1 (сообщений: 1)

    А, вот и логика нашлась.
    Нашли разработчики Айко, на основании моего сбоя, почему растет память: сервер выгружает на кассы справочник Заказы на производство, у меня он 1 Ггб, сделали патч и вуаля, касса потребляет не более 500 Мб ОЗУ, обещали патч учесть в следующих обновлениях.

    Необработанное исключение типа «System.OutOfMemoryException» в mscorlib.dll. Что делать?

    Спустя i = 33554433 вылетает исключение System.OutOfMemoryException
    Сущность его понятна, а что делать нет.

    • Вопрос задан более трёх лет назад
    • 1854 просмотра

    2 комментария

    Оценить 2 комментария

    Nipheris

    Станислав Макаров @Nipheris Куратор тега C#

    > i = 33554433
    Я не понял — вы уверены, что вам столько надо, или нет? В том смысле что список res тоже будет немалым, может действительно другой алгоритм нужен? Ну или не заю, yield return какой-нибудь.

    xkeirainx

    Да, уточните этот момент.
    Решения вопроса 0
    Ответы на вопрос 3

    dasha_programmist

    Даша Циклаури @dasha_programmist
    ex Software Engineer at Reddit TS/React/GraphQL/Go

    — увеличить объем оперативной памяти, поставить х64 систему
    — запускать приложение в облаке со снятым ограничением на оперативную память
    — придумать алгоритм, который будет требовать меньше памяти

    Ответ написан более трёх лет назад
    Комментировать
    Нравится 2 Комментировать
    .NET developer/ORM developer

    1)Вы уверены что у вас элементов будет меньше чем int.MaxValue?
    2)Выкиньте в топку этот List, можно оставить только если вам заранее известно количество элементов и вы можете инициализировать maxCapacity сразу. если нет то выкидывайте однозначно. Дело в том, что после 4-ой вставки (если мне не изменяет память) при каждой следующей вставке элемента Capacity увеличивается вдвое, соответственно массив элементов который там внутрях тоже увеличивается вдвое и элементы перегоняются в новый. представляете с какой скоростью растет массив? то есть на i = 33554433 + 1 list.Add() будет пытаться выделить кусок под 67108866 элементов, а это нужен непрерывный кусок памяти который к тому времени наверняка не находится и все падает с OutOfMemoryException. кстати же еще нужно хранит массив с которого будем копировать в тот который копируем. это огромная трата памяти. жесть просто.

    Не знаю что у вас за код, который использует результат метода Time, но если там всего лишь перебор то этот ваш алгоритм это просто жесть, и наверняка можно вообще не использовать внутренний список, а выдавать посчитанное значение по мере необходимости через yield return и вычислять на лету.

    Ответ написан более трёх лет назад
    Нравится 1 1 комментарий

    кстати, чтоб было легче понять размеры ж*пы, 67108866 * 64 бит = 4 294 967 424 бит = 536 870 928 байт непрерывного участка памяти.

    Alek_dr @Alek_dr Автор вопроса
    Пожалуй, переделаю лучше код)
    спасибо
    Ответ написан более трёх лет назад
    Комментировать
    Нравится Комментировать
    Ваш ответ на вопрос

    Войдите, чтобы написать ответ

    c#

    • C#
    • +1 ещё

    Ошибка Unity Editor — Unity 2023.3.0b7_ebadad6d577d что делать?

    • 1 подписчик
    • 23 часа назад
    • 29 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *