Какие стратегии и инструменты полезны для обнаружения утечек памяти в .NET? - PullRequest
147 голосов
/ 25 сентября 2008

Я написал C ++ в течение 10 лет. У меня возникли проблемы с памятью, но они могли быть устранены с разумным усилием.

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

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

Какие стратегии и инструменты полезны для устранения утечек памяти в .NET?

Ответы [ 14 ]

51 голосов
/ 25 сентября 2008

Я использую Scitech MemProfiler при подозрении на утечку памяти.

Пока что я обнаружил, что он очень надежный и мощный. Это спасло мой бекон хотя бы один раз.

GC очень хорошо работает в .NET IMO, но, как и на любом другом языке или платформе, если вы пишете плохой код, случаются плохие вещи.

41 голосов
/ 25 сентября 2008

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

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif
17 голосов
/ 25 сентября 2008

Мы использовали Ants Profiler Pro с помощью программного обеспечения Red Gate в нашем проекте. Он работает очень хорошо для всех приложений на основе языка .NET.

Мы обнаружили, что .NET Garbage Collector очень «безопасен» для очистки объектов в памяти (как и должно быть). Это будет держать объекты вокруг только потому, что мы могли бы использовать его когда-нибудь в будущем. Это означало, что мы должны быть более осторожны с количеством объектов, которые мы надували в памяти. В конце мы преобразовали все наши объекты данных в «раздувание по требованию» (непосредственно перед тем, как запрашивается поле), чтобы уменьшить нагрузку на память и повысить производительность.

РЕДАКТИРОВАТЬ: Вот еще одно объяснение того, что я имею в виду под «надувать по требованию». В нашей объектной модели нашей базы данных мы используем Свойства родительского объекта для представления дочерних объектов. Например, если бы у нас была какая-то запись, которая ссылалась на какую-то другую запись «detail» или «lookup» один на один, мы бы структурировали ее так:

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class

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

class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class

Это оказалось намного более эффективным, потому что объекты оставались в памяти до тех пор, пока они не были необходимы (был вызван метод Get). Это обеспечило очень большое повышение производительности в ограничении обращений к базе данных и огромный выигрыш в объеме памяти.

7 голосов
/ 25 сентября 2008

Вам все еще нужно беспокоиться о памяти, когда вы пишете управляемый код, если ваше приложение не является тривиальным. Я предложу две вещи: во-первых, прочитайте CLR через C # , потому что это поможет вам понять управление памятью в .NET. Во-вторых, научитесь использовать такой инструмент, как CLRProfiler (Microsoft). Это может дать вам представление о том, что вызывает утечку памяти (например, вы можете взглянуть на фрагментацию кучи больших объектов)

6 голосов
/ 25 сентября 2008

Вы используете неуправляемый код? По словам Microsoft, если вы не используете неуправляемый код, утечки памяти в традиционном смысле невозможны.

Тем не менее, память, используемая приложением, может не высвобождаться, поэтому выделение памяти приложению может увеличиваться в течение срока службы приложения.

С Как определить утечки памяти в общеязыковой среде выполнения на Microsoft.com

В .NET может произойти утечка памяти. Рамочное приложение при использовании неуправляемый код как часть приложение. Этот неуправляемый код может утечка памяти и .NET Framework среда выполнения не может решить эту проблему.

Кроме того, проект может только похоже, есть утечка памяти. это состояние может возникнуть, если много больших объекты (такие как объекты DataTable) объявлены и затем добавлены к коллекция (например, DataSet). ресурсы, которыми владеют эти объекты, могут никогда не выйдет, а ресурсы остались живы на весь пробег программа. Это похоже на утечка, но на самом деле это просто симптом того, что память выделяется в программе.

Для решения проблемы такого типа вы можете реализовать IDisposable . Если вы хотите ознакомиться с некоторыми стратегиями работы с управлением памятью, я бы предложил поискать IDisposable, XNA, управление памятью , поскольку разработчики игр должны иметь более предсказуемую сборку мусора и поэтому должны заставлять GC его вещь.

Одна распространенная ошибка - не удалять обработчики событий, которые подписываются на объект. Подписка на обработчик событий предотвратит повторное использование объекта. Кроме того, взгляните на оператор using , который позволяет создавать ограниченную область действия для ресурса ресурса.

5 голосов
/ 22 октября 2015

У меня просто была утечка памяти в службе Windows, которую я исправил.

Сначала я попробовал MemProfiler . Я нашел, что это действительно трудно использовать и совсем не удобно для пользователя.

Затем я использовал JustTrace , который проще в использовании и дает вам больше информации об объектах, которые расположены неправильно.

Это позволило мне действительно легко устранить утечку памяти.

5 голосов
/ 01 октября 2008

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

3 голосов
/ 25 сентября 2008

Большие пушки - Инструменты отладки для Windows

Это удивительная коллекция инструментов. С его помощью вы можете анализировать как управляемые, так и неуправляемые кучи и делать это в автономном режиме. Это было очень удобно для отладки одного из наших приложений ASP.NET, которые продолжали перерабатываться из-за чрезмерного использования памяти. Мне только нужно было создать полный дамп памяти живого процесса, работающего на рабочем сервере, весь анализ проводился в автономном режиме в WinDbg. (Оказалось, что какой-то разработчик злоупотреблял хранилищем данных в памяти.)

«Если сломано, это ...» В блоге есть очень полезные статьи на эту тему.

3 голосов
/ 25 сентября 2008

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

Тем не менее, ИМХО, было бы лучше рассмотреть сделанное на заказ решение - только вы действительно знаете, как долго вам нужно держать объекты вокруг, поэтому разработка подходящего служебного кода для вашей ситуации обычно является лучшим подходом.

2 голосов
/ 02 марта 2018

Я предпочитаю dotmemory от Jetbrains

...