Прочитать на английском

Поделиться через


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

В этой статье показано, как устранить ошибки нехватки памяти в ASP.NET.

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

Симптомы

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

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

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

Примечание

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

Существует две причины, по которым может появиться условие OOM.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Загрузка одинаковых сборок в несколько доменов приложений.

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

  • Запуск приложения в рабочей среде с атрибутом отладки <compilation> набора trueэлементов.

    • Атрибут отладки <compilation> элемента должен находиться false в рабочей среде.
    • Конфигурацию <deploy retail="true" /> можно использовать, чтобы убедиться, что отладка всегда отключена в продукте. Дополнительные сведения см. в разделе "Элемент развертывания" (схема параметров ASP.NET).
  • Использование скриптов в преобразованиях или создании XmlSerializersязыка таблицы стилей eXtensible (XSL).

    В этом случае динамические сборки, вызванные расширяемыми преобразованиями языка таблицы стилей (XSLT) или XmlSerializers.

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

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

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

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

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

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

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

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

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

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