[WPF] Улучшение производительности приложений
От: MxKazan Португалия  
Дата: 05.05.09 18:04
Оценка: 14 (3)
В последнее время появляются темы, касающиеся ускорения приложений, созданных на базе WPF.

Возможно полезным окажется соответствующий раздел MSDN: Optimizing WPF Application Performance
Есть и рашенский вариант: Улучшение производительности приложений WPF

Может у кого еще имеются ссылочки на подобную тему.
Re: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 05.05.09 23:44
Оценка: 28 (4) +2 :)
MK>Может у кого еще имеются ссылочки на подобную тему.
Как-то плохо со ссылками.

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

Во вторую очередь — ничему не верить на слово, проверять с рефлектором.

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

Там, где не можете гарантировать отписку от событий, пользуйтесь WeakEvent паттерном (в MSDN описано).

Если во фрейме происходит навигация, то IDisposable каким-то чудом срабатывает. Похоже, что единственное такое место в WPF, можно пользоваться.
Re[2]: [WPF] Улучшение производительности приложений
От: Sinix  
Дата: 06.05.09 00:45
Оценка:
Здравствуйте, notacat.

N>Если во фрейме происходит навигация, то IDisposable каким-то чудом срабатывает. Похоже, что единственное такое место в WPF, можно пользоваться.


ЫЫЫ Не я один на нелюбовь к IDisposable наталкивался...
Я чаще правда ругаюсь что не вызывается IDisposable на биндинге к DataView. Из-за другого бага в самом DataView ломался биндинг у новых DataView к той же таблице. (В DataView есть багофича — change notifying работает только для одного DataView на таблицу. В winForms BindingSource эту проблему как-то обходят. В WPF — нет.)
Re: [WPF] Улучшение производительности приложений
От: Sinix  
Дата: 06.05.09 00:45
Оценка: 8 (1)
Здравствуйте, MxKazan, Вы писали:

Как всегда — блоги.

Отдельно советую http://blogs.msdn.com/jaimer/ — регулярнейше выкладывает логи с внутренних обсуждений команды.
Кстати у него же — WPF bloggers.

Дальше тулзы. WPF perf suite с SDK (или как там его???) и mole.

Чаще всего попадались грабли с кривыми template. На втором месте по популярности — попытки "быстро сделать красиво". Как говорится — выбирайте что-то одно
Re[2]: [WPF] Улучшение производительности приложений
От: MxKazan Португалия  
Дата: 06.05.09 06:48
Оценка:
Здравствуйте, notacat, Вы писали:

N>В первую очередь, очень советую проверять наличие/отсутствие утечек памяти. Где-то тут уже была тема про это.

Я создавал тему про утечку при привязке к объектам не DependencyObject и без INotifyPropertyChanged: [WPF] Баг: binding memory leak
Автор: MxKazan
Дата: 11.02.09
.

N>Последний memory leak, на который я наткнулась — хотела сделать статическую кисть, заморозить ее и использовать везде. Получилось, что если один раз ей что-нибудь нарисуешь, она не освобождает какие-то ссылки, т.е. каждое следующее рисование занимает все больше времени. Обошла тем, что каждый раз возвращаю клон от этой статической кисти.

Что-то верится с трудом. Ведь тогда получается, что кистями класса Brushes пользоваться вообще нельзя.

N>Там, где не можете гарантировать отписку от событий, пользуйтесь WeakEvent паттерном (в MSDN описано).

+1

N>Если во фрейме происходит навигация, то IDisposable каким-то чудом срабатывает. Похоже, что единственное такое место в WPF, можно пользоваться.

А в чем чудо? WPF сама вызывает GC.Collect, когда появляется много unmanaged-хэндлов. См. MS.Internal.MemoryPressure в PresentationCore.
Re[3]: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 06.05.09 10:26
Оценка:
N>>Последний memory leak, на который я наткнулась — хотела сделать статическую кисть, заморозить ее и использовать везде. Получилось, что если один раз ей что-нибудь нарисуешь, она не освобождает какие-то ссылки, т.е. каждое следующее рисование занимает все больше времени. Обошла тем, что каждый раз возвращаю клон от этой статической кисти.
MK>Что-то верится с трудом. Ведь тогда получается, что кистями класса Brushes пользоваться вообще нельзя.
Не знаю насчет Brushes, возможно это зависит от типа кисти. У меня был градиент, причем сделанный не в xaml, а из кода. Возможно, проблема в этом.

N>>Если во фрейме происходит навигация, то IDisposable каким-то чудом срабатывает. Похоже, что единственное такое место в WPF, можно пользоваться.

MK>А в чем чудо? WPF сама вызывает GC.Collect, когда появляется много unmanaged-хэндлов. См. MS.Internal.MemoryPressure в PresentationCore.
Чудо в том, что GC.Collect вызывается, а Dispose — нет. Ну а без Dispose, garbage collector далеко не все умеет чистить.
Re[4]: [WPF] Улучшение производительности приложений
От: MxKazan Португалия  
Дата: 06.05.09 12:06
Оценка:
Здравствуйте, notacat, Вы писали:

N>>>Последний memory leak, на который я наткнулась — хотела сделать статическую кисть, заморозить ее и использовать везде. Получилось, что если один раз ей что-нибудь нарисуешь, она не освобождает какие-то ссылки, т.е. каждое следующее рисование занимает все больше времени. Обошла тем, что каждый раз возвращаю клон от этой статической кисти.

MK>>Что-то верится с трудом. Ведь тогда получается, что кистями класса Brushes пользоваться вообще нельзя.
N>Не знаю насчет Brushes, возможно это зависит от типа кисти. У меня был градиент, причем сделанный не в xaml, а из кода. Возможно, проблема в этом.
Может быть, может быть... ну если вдруг еще раз встретится, то может запостишь пример

N>>>Если во фрейме происходит навигация, то IDisposable каким-то чудом срабатывает. Похоже, что единственное такое место в WPF, можно пользоваться.

MK>>А в чем чудо? WPF сама вызывает GC.Collect, когда появляется много unmanaged-хэндлов. См. MS.Internal.MemoryPressure в PresentationCore.
N>Чудо в том, что GC.Collect вызывается, а Dispose — нет. Ну а без Dispose, garbage collector далеко не все умеет чистить.
Если так, то значит какие-то классы внутри WPF криво написано, потому что по правильному Dispose должен вызываться из финализатора.
Re[5]: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 06.05.09 12:16
Оценка:
N>>>>Если во фрейме происходит навигация, то IDisposable каким-то чудом срабатывает. Похоже, что единственное такое место в WPF, можно пользоваться.
MK>>>А в чем чудо? WPF сама вызывает GC.Collect, когда появляется много unmanaged-хэндлов. См. MS.Internal.MemoryPressure в PresentationCore.
N>>Чудо в том, что GC.Collect вызывается, а Dispose — нет. Ну а без Dispose, garbage collector далеко не все умеет чистить.
MK>Если так, то значит какие-то классы внутри WPF криво написано, потому что по правильному Dispose должен вызываться из финализатора.
не криво, а by design, у них в документации прямо написано, что концепция IDisposable в WPF не работает
Re[6]: [WPF] Улучшение производительности приложений
От: MxKazan Португалия  
Дата: 06.05.09 12:40
Оценка:
Здравствуйте, notacat, Вы писали:

N>>>>>Если во фрейме происходит навигация, то IDisposable каким-то чудом срабатывает. Похоже, что единственное такое место в WPF, можно пользоваться.

MK>>>>А в чем чудо? WPF сама вызывает GC.Collect, когда появляется много unmanaged-хэндлов. См. MS.Internal.MemoryPressure в PresentationCore.
N>>>Чудо в том, что GC.Collect вызывается, а Dispose — нет. Ну а без Dispose, garbage collector далеко не все умеет чистить.
MK>>Если так, то значит какие-то классы внутри WPF криво написано, потому что по правильному Dispose должен вызываться из финализатора.
N>не криво, а by design, у них в документации прямо написано, что концепция IDisposable в WPF не работает
Странный by design. Т.е. идея то понятна и правильна, на мой взгляд. Другое дело, на фига тогда во внутренних классах этот IDisposable применяется и не вызывается при сборке мусора.
Re[7]: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 06.05.09 13:30
Оценка:
MK>Странный by design. Т.е. идея то понятна и правильна, на мой взгляд. Другое дело, на фига тогда во внутренних классах этот IDisposable применяется и не вызывается при сборке мусора.
А это не факт, что для внутренних классов он не вызывается. Я сейчас в связи с переходом на Сильверлайт этот индусский код изнутри изучаю — полно мест, где они для своих классов делают какую-нибудь специальную обработку, причем в таком месте, о котором нарочно не догадаешься. Очень много internal свойств и методов, которые дергаются отовсюду..
Re[8]: [WPF] Улучшение производительности приложений
От: MxKazan Португалия  
Дата: 06.05.09 13:46
Оценка:
Здравствуйте, notacat, Вы писали:

MK>>Странный by design. Т.е. идея то понятна и правильна, на мой взгляд. Другое дело, на фига тогда во внутренних классах этот IDisposable применяется и не вызывается при сборке мусора.

N>А это не факт, что для внутренних классов он не вызывается. Я сейчас в связи с переходом на Сильверлайт этот индусский код изнутри изучаю — полно мест, где они для своих классов делают какую-нибудь специальную обработку, причем в таком месте, о котором нарочно не догадаешься. Очень много internal свойств и методов, которые дергаются отовсюду..
Так. Чего то не понимаю. Мне казалось проблема в том, что где-то внутри WPF не зовется Dispose. Если это не внутри, а в собственном коде, то что мешает поместить вызов Dispose в финализатор?
Re[9]: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 06.05.09 16:15
Оценка:
MK>>>Странный by design. Т.е. идея то понятна и правильна, на мой взгляд. Другое дело, на фига тогда во внутренних классах этот IDisposable применяется и не вызывается при сборке мусора.
N>>А это не факт, что для внутренних классов он не вызывается. Я сейчас в связи с переходом на Сильверлайт этот индусский код изнутри изучаю — полно мест, где они для своих классов делают какую-нибудь специальную обработку, причем в таком месте, о котором нарочно не догадаешься. Очень много internal свойств и методов, которые дергаются отовсюду..
MK>Так. Чего то не понимаю. Мне казалось проблема в том, что где-то внутри WPF не зовется Dispose. Если это не внутри, а в собственном коде, то что мешает поместить вызов Dispose в финализатор?
Ничего не мешает, специально сейчас попробовала. В приложении создаются немодальные окна, в которых рисуются мои контролы. Создаю новые окна, закрываю, открываю еще штук 20 окон и т.д... Все это достаточно большое, видно что какая-то сборка мусора происходит, иначе это все разрослось бы до невменяемых размеров. НО финализатор вызывается только при закрытии всего приложения, а там он уже и не нужен, поскольку закрытие приложения все равно память почистит. Мне желательно память освобождать по закрытию окна, чтобы программа у юзера могла сутками работать.
Re[10]: [WPF] Улучшение производительности приложений
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.05.09 16:21
Оценка:
Здравствуйте, notacat, Вы писали:

N>Ничего не мешает, специально сейчас попробовала. В приложении создаются немодальные окна, в которых рисуются мои контролы. Создаю новые окна, закрываю, открываю еще штук 20 окон и т.д... Все это достаточно большое, видно что какая-то сборка мусора происходит, иначе это все разрослось бы до невменяемых размеров. НО финализатор вызывается только при закрытии всего приложения, а там он уже и не нужен,

Сборка второго поколения проходит при этом?
Re[11]: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 06.05.09 16:25
Оценка:
N>>Ничего не мешает, специально сейчас попробовала. В приложении создаются немодальные окна, в которых рисуются мои контролы. Создаю новые окна, закрываю, открываю еще штук 20 окон и т.д... Все это достаточно большое, видно что какая-то сборка мусора происходит, иначе это все разрослось бы до невменяемых размеров. НО финализатор вызывается только при закрытии всего приложения, а там он уже и не нужен,
S>Сборка второго поколения проходит при этом?
Не знаю, как это проверить?
Re[12]: [WPF] Улучшение производительности приложений
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.05.09 17:01
Оценка:
Здравствуйте, notacat, Вы писали:

S>>Сборка второго поколения проходит при этом?

N>Не знаю, как это проверить?
Профайлером
Re[10]: [WPF] Улучшение производительности приложений
От: MxKazan Португалия  
Дата: 06.05.09 17:04
Оценка:
Здравствуйте, notacat, Вы писали:

N>Ничего не мешает, специально сейчас попробовала. В приложении создаются немодальные окна, в которых рисуются мои контролы. Создаю новые окна, закрываю, открываю еще штук 20 окон и т.д... Все это достаточно большое, видно что какая-то сборка мусора происходит, иначе это все разрослось бы до невменяемых размеров. НО финализатор вызывается только при закрытии всего приложения, а там он уже и не нужен, поскольку закрытие приложения все равно память почистит. Мне желательно память освобождать по закрытию окна, чтобы программа у юзера могла сутками работать.

Очень странно. Я когда определял, что избавился от описанной ранее утечки в Binding, ставил breakpoint'ы на финализаторы. Закрытые окна со временем собирались, а не только, когда завершалось приложение. Возможно где-то осталась лишняя ссылка.
Re[11]: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 06.05.09 17:22
Оценка:
N>>Ничего не мешает, специально сейчас попробовала. В приложении создаются немодальные окна, в которых рисуются мои контролы. Создаю новые окна, закрываю, открываю еще штук 20 окон и т.д... Все это достаточно большое, видно что какая-то сборка мусора происходит, иначе это все разрослось бы до невменяемых размеров. НО финализатор вызывается только при закрытии всего приложения, а там он уже и не нужен, поскольку закрытие приложения все равно память почистит. Мне желательно память освобождать по закрытию окна, чтобы программа у юзера могла сутками работать.
MK>Очень странно. Я когда определял, что избавился от описанной ранее утечки в Binding, ставил breakpoint'ы на финализаторы. Закрытые окна со временем собирались, а не только, когда завершалось приложение. Возможно где-то осталась лишняя ссылка.
Естественно, лишняя ссылка, как бы только эту ссылку убирать при удалении контрола, если учесть, что контрол может хоститься в окне, на странице, еще где-нибудь, может удаляться из окна, когда окно никто не закрывает, и т.д. (юзеры придумывали мне кучу вариантов). По Unloaded этого делать нельзя, поскольку один и тот же контрол может быть после Unloaded снова Loaded. А если лишних ссылок нет — то и Dispose наверное не нужен.
А сгружать эту задачу на юзера моих контролов — нехорошо. Самое главное, что в WinForms с этим проблем вообще не было, там Dispose отрабатывал когда нужно.
Re[13]: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 06.05.09 17:24
Оценка:
S>>>Сборка второго поколения проходит при этом?
N>>Не знаю, как это проверить?
S>Профайлером
научи меня, ты каким профайлером пользуешься? У меня только то, что в Team System входит.
Re[12]: [WPF] Улучшение производительности приложений
От: MxKazan Португалия  
Дата: 06.05.09 17:56
Оценка:
Здравствуйте, notacat, Вы писали:

N>>>Ничего не мешает, специально сейчас попробовала. В приложении создаются немодальные окна, в которых рисуются мои контролы. Создаю новые окна, закрываю, открываю еще штук 20 окон и т.д... Все это достаточно большое, видно что какая-то сборка мусора происходит, иначе это все разрослось бы до невменяемых размеров. НО финализатор вызывается только при закрытии всего приложения, а там он уже и не нужен, поскольку закрытие приложения все равно память почистит. Мне желательно память освобождать по закрытию окна, чтобы программа у юзера могла сутками работать.

MK>>Очень странно. Я когда определял, что избавился от описанной ранее утечки в Binding, ставил breakpoint'ы на финализаторы. Закрытые окна со временем собирались, а не только, когда завершалось приложение. Возможно где-то осталась лишняя ссылка.
N>Естественно, лишняя ссылка, как бы только эту ссылку убирать при удалении контрола, если учесть, что контрол может хоститься в окне, на странице, еще где-нибудь, может удаляться из окна, когда окно никто не закрывает, и т.д. (юзеры придумывали мне кучу вариантов). По Unloaded этого делать нельзя, поскольку один и тот же контрол может быть после Unloaded снова Loaded. А если лишних ссылок нет — то и Dispose наверное не нужен.
Я говорил о лишних ссылках на контрол, о ссылках, которые не позволяют GC вызвать финализатор до закрытия приложения. Если же речь идет о детерминированном высвобождении ресурсов, то да, WPF это не поддерживает.
Re[14]: [WPF] Улучшение производительности приложений
От: notacat  
Дата: 06.05.09 18:57
Оценка:
S>>>>Сборка второго поколения проходит при этом?
N>>>Не знаю, как это проверить?
S>>Профайлером
N>научи меня, ты каким профайлером пользуешься? У меня только то, что в Team System входит.
Починила счетчики производительности в системе, посмотрела — собирается второе поколение тоже.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.