Проблема памяти в .NET 4 WCF - PullRequest
       41

Проблема памяти в .NET 4 WCF

4 голосов
/ 20 сентября 2011

Я столкнулся с проблемой, что мое ASP.NET 4 MVC 2 + WCF приложение использует много памяти в Windows 2008 64-битное приложение во время нагрузочного тестирования, где оно почти полностью израсходует вся доступная память (8 ГБ) через несколько минут работы (у нас работало несколько рабочих процессов).

После профилирования с использованием ANTS Memory Profiler было несколько интересных результатов:

  1. . Увеличение управляемой памяти .NET с 15 МБ до 40 МБ, однако это связано с механизмом кэширования, который мы использовали в программе. Однако .NET сам выделяет почти 180 МБ свободного пространства, что является неожиданным.
  2. Объем неуправляемой памяти значительно увеличивается до 120 МБ после того, как нагрузочный тест выполняется всего около 3 минут (хотя наше приложение явно не использовало P / Invoke или COM-объект. Однако мы использовали несколько объектов COM +, которые после использования в блоке finally).
  3. Память становится фрагментированной.
  4. Оба пункта № 1 и 2, приведенные выше, приводят к тому, что для всего приложения используется около 350 МБ сразу после выполнения нагрузочного теста через несколько минут, но если мы не остановим тест, он будет продолжать расти.

На основании пункта 1 выше, я протестировал некоторые приложения, чтобы проверить, связана ли проблема с нашим приложением или WCF. Тестовое приложение просто загружает данные XML (около 300 КБ) в набор данных в многопоточном приложении . Когда логика хранится в программе EXE, приложение использует только 200 КБ (дополнительно 120 КБ от начала до 40 КБ для неиспользуемой памяти) управляемой памяти из 24 МБ личных байтов после завершения (что приемлемо); но когда логика размещается в WCF, приложение использует 66 МБ управляемой памяти (дополнительно 61 МБ от начала до 64 МБ свободной / неиспользуемой управляемой памяти). Похоже, что именно WCF / ASP.NET вызывает значительное увеличение памяти).

  1. Почему .NET выделяет так много свободного места в куче? Понял, что свободным пространством может быть некое Gen 0 / Gen 1 / Gen 2, которое GC-ed во время процесса создания снимка памяти, но я не не думаю, что приложение действительно использует столько памяти.
  2. нормально ли поведение для WCF? Если да, есть ли способ изменить поведение так, чтобы он использовал меньше памяти?
  3. Как найти неуправляемую утечку памяти, особенно если я не использовал неуправляемый код явно?

Благодарим вас за совет по вышеуказанному вопросу.

Заранее спасибо,

Willy

Ответы [ 3 ]

4 голосов
/ 13 ноября 2013

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

Чтобы не создавать новые буферы постоянно, WCF использует BufferManager для повторного использования буферов, до предела, указанного в maxBufferPoolSize (ссылка на элемент здесь ) , который по умолчанию составляет 512 КБ. Любые запросы, превышающие этот предел, приводят к созданию новых буферов, которые никогда не используются повторно и должны быть подвергнуты сборке мусора.

Другая опция для проверки - maxBufferSize, которая ограничивает максимальный размер буфера, который может быть возвращен BufferManager. Большие буферы не объединяются и должны быть удалены. Если вы используете большие сообщения, вы можете уменьшить временные буферы, увеличив это свойство.

Попробуйте увеличить maxBufferPoolSize, чтобы посмотреть, сможете ли вы уменьшить использование памяти. Хотя я бы настоятельно рекомендовал НЕ использовать его максимально, поскольку буферы из пула никогда не освобождаются до тех пор, пока домен приложения (то есть пул приложений) не будет перезагружен. Период большого трафика может привести к тому, что будет использовано много памяти и она никогда не будет освобождена.

1 голос
/ 20 сентября 2011

Что касается "неуправляемой утечки памяти", у меня был такой случай некоторое время назад, и после некоторого копания это был поставщик ADO.NET - исправили это с помощью обновленной версии: -)

В остальном - попробуйте добавить это в конфиг:

<Configuration>
    <runtime>
        <gcServer enabled=“true“ />
    </runtime>
</Configuration>

Кроме этого, в WCF IMHO нет ничего особенного ... может быть утечка памяти, как в любом приложении .NET (например, обработчик событий и статические обработчики / объекты могут создавать утечки памяти, если не отменить подписку должным образом) ...

0 голосов
/ 20 сентября 2011

Просто догадка: вы подписываетесь на какие-либо статические события или события в долгоживущих объектах?

  • Объект, подписанный на статическое событие, будет жить вечно (или до тех пор, пока не отписался).
  • Объект, подписанный на событие объекта, будет жить в течение всего времени существования этого объекта (или до тех пор, пока не будет отписан).

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

...