Использование памяти WPF - PullRequest
9 голосов
/ 09 мая 2009

Применение:

  • Приложение WPF, состоящее из текстового поля сверху и списка ниже
  • Пользователи вводят строку в TextBox для поиска сотрудников, а результаты поиска отображаются в ListBox
  • ListBox использует DataTemplates для отображения элементов (показывает имя сотрудника, отдел, телефон и миниатюру изображения).

Реализация:

  • При запуске приложения я запрашиваю базу данных и извлекаю всех сотрудников и связанную с ними информацию для отображения в ListBox. Это хранится в памяти все время.
  • После запуска приложения все доступные для поиска данные находятся в памяти, и поиск выполняется практически мгновенно. Все поиски выполняются по данным уже в памяти.
  • Результаты поиска отображаются в ListBox с использованием шаблонов данных. Изображение миниатюр, имя, телефон, отдел и т. Д. Отображаются в каждом элементе списка.

Проблема:

  • При запуске использование памяти составляет около 200 МБ.
  • Поскольку данные изменяются в списке, либо с помощью нового поиска, либо просто прокручивая список вниз, потребление памяти увеличивается.
  • Когда пользователи медленно прокручивают список вниз, память увеличивается быстрее. При прокрутке вверх и вниз объем памяти быстро достигает 1 ГБ.

Нет никакого кода, создающего элементы управления вручную - все делается через привязку данных.

Почему я вижу это поведение? Что я могу сделать, чтобы это исправить? Пожалуйста, помогите!

UPDATE: Я понял, что проблема не в утечке памяти. Проблема здесь заключается в том, что список создает объекты для отображения изображений сотрудника, а не освобождает их для сборщика мусора после того, как элемент списка выходит из окна. Событие CleanUpVirtualizedItem происходит, как я и ожидал, но память все еще не освобождена. Есть идеи?

Ответы [ 6 ]

6 голосов
/ 09 мая 2009

С риском быть бойким, у вас есть утечка памяти. Почему бы не попробовать такой инструмент, как ANTS *, чтобы отследить его. У них есть бесплатная пробная версия, я никогда не использовал его, но у него хорошая репутация.

* Доступны другие инструменты профилирования.

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

3 голосов
/ 14 мая 2009

Вы можете использовать

WPF Performance Suite

Оптимизация производительности приложений WPF

Подобная проблема преследует меня .. (что-то вроде)

При запуске приложения я запрашиваю базу данных и извлекаю всех сотрудников и связанную с ними информацию для отображения в ListBox. Это хранится в памяти все время.

Может быть, вы могли бы изменить свой код, чтобы он следовал WPF: Виртуализация данных

3 голосов
/ 09 мая 2009

Запуск LOL 200 МБ и запуск 1 ГБ. Более распространенный штраф на x64 (и он вам понадобится для раздувания) - штраф около 64 МБ для запуска и еще 120 МБ для полу-продвинутой функциональности, которая все еще огромна и, конечно, GC продолжит добавлять больше.

Это должно убить процессор и всю периферию вокруг него в кратчайшие сроки. Теперь представьте, что все работает на этом, все приложения, а также вся ОС и стек (поскольку VS2010 наверняка попытается продвинуться в этом направлении).

Я бы сказал: добро пожаловать в современную манеру распространения вирусов и простоту доступа. Независимо от того, что вы делаете, вы тратите больше времени на поиск обходных путей, чем следуя какой-то «универсальной» среде, быстро и круто, с хорошо разработанными и настраиваемыми приложениями. Конечно, WPF хорош на бумаге, но тратит ресурсы на любое практическое использование (тонны ресурсов и крутая кривая обучения).

И они сказали, что это было и есть будущее (то же самое для приложений JDK, которые очень распространены).

Просто N.U.T.S + самый прекрасный пример того, что речь идет не о скорости (как защитники CLR будут использовать тривиальные примеры) управляемого кода. Речь идет об огромном ухудшении масштабируемости и уничтожении компьютеров, как и в случае с каждой отдельной средой GC и объектно-корневой средой.

Проголосуйте, идите вниз ... идите к ученикам, вы знаете, что хотите.

(и напишите Обаме против сокращения выбросов CO2, которое не произойдет; возможно, умножьте на 1003120x, если этот модный автомобиль продолжит идти своим чередом. Даже Cray Jaguar не будет работать в такой среде в течение следующих 20 лет ).

1 голос
/ 15 мая 2009

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

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

Только некоторые догадки ... Как уже говорили здесь, вы, возможно, захотите взглянуть на свое приложение с помощью профилировщиков производительности и памяти.

0 голосов
/ 22 мая 2009

Одна вещь, которая мне очень помогла, это использование класса, обертывающего класс Stream. Это подробно объясняется здесь и, конечно же, я сэкономил много памяти, используя этот метод. WPF действительно сохраняет ссылку на базовый байт [] и поток для каждого изображения.

0 голосов
/ 12 мая 2009

Я заметил, что есть проблемы с памятью в WPF и .NET 3.5 с пакетом обновления 1 (SP1) w.r.t в на первый взгляд безобидных ситуациях.

Я нашел пару ресурсов, но я не уверен, что они будут вам полезны:

http://blog.ramondeklein.nl/?p=58

Этот пост в блоге описывает ситуацию, когда

  1. Стиль определяется в ResourceDictionary приложения.
  2. Стиль использует шаблон элемента управления, который использует медиаэффекты (т.е. DropShadowEffect).
  3. На эффект мультимедиа следует ссылаться с использованием StaticResource

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

...