куда ушла моя память? большое количество частных байтов - PullRequest
7 голосов
/ 10 июня 2009

У меня есть приложение WPF, которое, помимо прочего, отображает множество изображений, больших и маленьких. Моя проблема в том, что приложение использует много памяти, и я не могу понять, откуда оно.

Сценарий, когда я подчеркиваю приложение, я получаю этот график в perfmon:

http://www.imagechicken.com/uploads/1244548604007097000.jpg

Большая черная линия - это Process \ Private bytes, а остальные строки - это счетчики памяти CLR (розовая - Total принятые байты)

Цифрами на графике являются:
Частные байты ~ 350 Мб
Зафиксированные байты ~ 100 МБ

Я много копался с WinDbg и другими инструментами, и все они сообщают, что управляемый стек ведет себя (! Eeheap сообщает об общем управляемом стеке около 100 Мб)

Я возился с такими приложениями, как LeakDiag, LDGrapher, но ничего не нашел.

Итак, наконец, на мой вопрос, как мне узнать, куда уходит моя память?

Даже при запуске приложения используется 100 МБ выделенных байтов, но 190 МБ - в приватных байтах.

Ссылка:

Я много читал об этом, в том числе на замечательных сайтах:

Тесс Феррандес: http://blogs.msdn.com/tess/archive/2009/02/27/net-memory-leak-reader-email-are-you-really-leaking-net-memory.aspx

Рико Мариани: http://blogs.msdn.com/ricom/archive/2004/12/10/279612.aspx

MSDN mag: http://msdn.microsoft.com/en-us/magazine/cc163528.aspx

Ответы [ 5 ]

4 голосов
/ 10 июня 2009

У меня была похожая проблема в приложении WPF, и использовал UMDH для отслеживания , где была выделена собственная память. (Обратите внимание, что обычно полезно установить _NT_SYMBOL_PATH , чтобы получить хорошие следы стека от компонентов ОС.

Журналы показали, что почти вся память была выделена в видеодрайвере. Я обнаружил, что водитель был больше года устаревшим; Я установил последнюю версию с сайта производителя, и это устранило проблему.

3 голосов
/ 10 июня 2009

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

При устранении неполадок в управляемых утечках памяти с помощью WinDbg я делаю следующее:

  • Получите обзор использования кучи с помощью !eeheap (в этом отчете указано использование кучи, а не стека, как вы упомянули - каждый стек имеет размер по умолчанию 1 МБ, поэтому, если вы не изменили это, нет никакого способа вы можете использовать 100 МБ в стеке)

  • Сделайте !dumpheap -stat, чтобы узнать, что находится в куче. Скорее всего, если у вас утечка памяти, виновный тип (ы) будет одним из главных потребителей. Чтобы получить представление о том, как развивается использование кучи, вы можете возобновить работу приложения, разбить его чуть позже и повторить команду !dumpheap -stat.

  • Если вы найдете какие-либо типы с большим количеством экземпляров, чем вы, кроме, перечислите те, которые используют !dumpheap -mt <MT of type>. Это перечислит все экземпляры определенного типа. Выберите случайные экземпляры и проверьте корни с помощью команды !gcroot. Это скажет вам, что поддерживает рассматриваемые экземпляры. Если корня нет, эти экземпляры будут собраны в какой-то момент.

ОБНОВЛЕНИЕ, чтобы ответить на ваши комментарии:

Управляемая куча - это только часть занимаемой памяти управляемой программы. Помните, что приложение .NET на самом деле является приложением внутри другого приложения - хост-процесса, который загружает CLR, который, в свою очередь, загружает ваше приложение. Поэтому, прежде чем ваше приложение начнет использовать какую-либо память, CLR уже заняла справедливую долю. Помимо этого .NET-приложения хранят как код MSIL, так и JIT-скомпилированный код как часть отпечатка. CLR также занимает место для различных вещей бухгалтерии (например, CLR создает два дополнительных AddDomains для внутреннего использования).

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

100 МБ в управляемой куче может быть хорошо, в зависимости от того, что делает ваше приложение. Ты проверил кучу? И если так, что вы нашли?

1 голос
/ 10 июня 2009

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

Вы можете скачать VADump здесь: http://go.microsoft.com/fwlink/?LinkId=149683

Чтобы сломать управляемую кучу, вы можете попробовать профилировщик памяти. Мне лично нравится JetBrains dotTrace .

1 голос
/ 10 июня 2009

Скачать MemProfiler от Scitech. Он имеет 14-дневную пробную версию.

Проблема, о которой вы сообщаете, часто связана с представлениями / ресурсами, которые не могут быть удалены из-за наличия рута в куче. Распространенной причиной является не разводка обработчиков событий.

0 голосов
/ 15 июня 2009

Один ответ: слишком много объединенных словарей ресурсов (вещь WPF)

Детали: чтобы увидеть дизайн во время разработки в Blend и VS, мы использовали, чтобы объединить наш словарь ресурсов темы на большинстве страниц xaml. Это привело к загрузке копии всех ресурсов для каждого элемента управления, дополнительную информацию можно прочитать здесь: [WPF Disciples] [1]

Так что единственное место, где я их сейчас объединяю, это App.xaml.cs:

<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary 
        Source="pack://application:,,,/Company.Themes;Component/AppTheme.xaml"/>
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

Результаты: (запуск приложения через несколько страниц с автоматическим тестом GUI)

До:

  • После загрузки приложения: 63 МБ
  • После использования приложения: 177 Мб

После того, как:

  • После загрузки приложения: 53 МБ
  • После использования приложения: 97 Мб

Я выложу больше ответов, когда найду их! (Я думал, что читателям будет проще увидеть мои выводы как отдельные ответы вместо ответов на комментарии - хорошо?)

[1]: ref: http://groups.google.com/group/wpf-disciples/web/wpf-and-xaml-coding-guidelines?pli=1

...