Проблемы с памятью в C # - PullRequest
0 голосов
/ 14 мая 2019

У меня есть приложение, которое:

  • Targets C # 6
  • Targets .net 4.5.2
  • Является ли приложение Windows Forms
  • Сборки в режиме AnyCPU, потому что это ...
  • Использует старые 32-битные библиотеки, которые не могут быть обновлены до 64-битной, неуправляемой памяти
  • Использует DevExpress, сторонний поставщик управления
  • Ежедневно обрабатывает много гигабайт данных для создания отчетов

После нескольких часов использования в заданиях с большим количеством графиков приложение в конечном итоге исчерпывает память.Я потратил довольно много времени на устранение многих утечек, обнаруженных в коде, и довел проект до состояния, когда в худшем случае он может использовать более 400 000 КБ памяти в любой момент времени, согласно счетчикам производительности.Обработка этих данных не привела к возникновению каких-либо проблем на данный момент, поскольку данные обрабатываются в Jagged массивах, что предотвращает любые проблемы с кучей больших объектов.

В последний раз, когда это происходило, пользователь использовал ~ 305 000 КБ памяти.Приложение настолько «не хватает памяти», что диалоговое окно с ошибкой не может даже нарисовать значок ошибки в появившемся окне сообщений, пространство, где обычно находится значок, полностью черное.

Пока я сделалЧтобы очистить это, выполните следующие действия:

  • В формах Windows используется событие Disposed для обеспечения очистки ресурсов, при необходимости вызывается dispose
  • Бизнес-объекты используют IDisposable для удаления ссылок
  • Проверенная очистка с использованием профилировщика памяти ANTS и профилировщика памяти SciTech.Низкое использование памяти говорит о том, что это не тот случай, но я хотел посмотреть, видел ли я что-нибудь полезное, я не мог
  • Использовать свойство GCSettings.LargeObjectHeapCompactionMode, чтобы удалить любую фрагментацию из обрабатываемых данных, которые могут быть фрагментированы.в куче больших объектов (LoH)

Почти в каждой статье, которую я использовал для достижения этой точки, предполагается, что нехватка памяти фактически означает выход из смежного адресного пространства и с учетом используемого количества,Я согласен с этим.Я не уверен, что делать в этот момент, поскольку из того, что я понимаю (и, вероятно, очень ошибаюсь), сборщик мусора очищает это, чтобы освободить место по мере продвижения процесса, за исключением LoH, которыйтеперь очищен вручную с помощью нового свойства LargeObejctHeapCompactionMode, представленного в .net 4.5.1.

Чего мне здесь не хватает?Я не могу собрать 64-битную версию из-за старых 32-битных библиотек, которые содержат проприетарные алгоритмы, к которым у нас нет доступа даже к мечте о создании 64-битной версии.Существуют ли какие-либо режимы в этих профилях, которые я должен использовать, чтобы точно определить, что здесь выходит из-под контроля?

Если это адресное пространство не может быть очищено, означает ли это, что все приложения на c # в конечном итоге будут работать "из памяти""из-за этого?

1 Ответ

3 голосов
/ 15 мая 2019

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

Это разумная гипотеза, но даже разумные гипотезы могут быть ошибочными. Ваш, вероятно, не так .Что делать?

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

Итак:

  • в тот момент, когда у вашего приложения заканчивается память, на самом деле на нем нет смежных свободных страниц необходимого размера?Это звучит так, будто ваши наблюдения не указывают на то, что это правда, поэтому гипотеза, вероятно, ложна.

Каковы другие доказательства того, что гипотеза может быть ложной?

  • "После нескольких часов использования в заданиях, которые имеют много графиков , приложению в итоге не хватает памяти."
  • "Использует DevExpress, сторонний поставщик управления«
  • » диалоговое окно ошибки не может даже нарисовать значок ошибки в MessageBox »

Все это не похоже на проблему нехватки памяти.Это звучит как сторонняя библиотека управления, утечка дескрипторов ОС для графических объектов.К сожалению, такие утечки обычно появляются как ошибки «нехватки памяти», а не «нехватки ручек».

Итак, это новая гипотеза. Ищите доказательства и против этой гипотезы. Вы делаете хорошую работу, используя профилировщик памяти. Далее используйте дескриптор-профилировщик .

Если это адресное пространство не может быть очищено, означает ли это, что все приложения на c # в конечном итоге будут работать "из памяти" из-за этого?

Нет.GC хорошо очищает управляемую память;у многих приложений нет проблем с запуском без утечек.

...