OnPropertyChanged вызывает огромное количество выделений Action

У меня есть приложение WPF, которое отображает изображения в сетке. Пользователь имеет возможность быстро прокручивать изображения, перемещая мышь и щелкая левой кнопкой мыши. Это означает, что множество изображений меняется с большой скоростью.

Я заметил снижение производительности для сеток размером 24 и 40 элементов (которые являются самыми большими). Я определил, что причиной замедления было создание большого количества мусора, что вызвало множество блокировок сборок мусора gen0 и gen1. Уменьшив количество выделений, я смог улучшить производительность примерно с 10 до 25 кадров в секунду.

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

Я отследил это с помощью профилировщика памяти, и причиной является одно событие PropertyChanged, которое срабатывает каждый раз, когда изображение должно измениться. Это вызывает внутреннюю регистрацию и отмену регистрации некоторых событий, этот диспетчер событий использовал класс ReaderWriterLockWrapper. Действительно, каждый раз, когда осуществляется доступ к свойствам WriteLock или ReadLock, будет выделяться Action, как показано в справочном источнике:

https://referencesource.microsoft.com/#WindowsBase/Shared/MS/Internal/ReaderWriterLockWrapper.cs,7553fcec2d50ae8a,references

CallWithNonPumpingWait(()=>{_rwLock.EnterWriteLock();});

Я заметил, что код такой, начиная с версии фреймворка 4.7. Это предназначено? Одно это вызывает в моем приложении экземпляры Action объемом 16 МБ, когда я непрерывно прокручиваю в течение 8 секунд. Кроме того, как я понимаю, эта лямбда может быть просто членом экземпляра.

Вы тщательно проанализировали проблему, но каков ваш настоящий вопрос к сообществу StackOverflow? Вы не спрашиваете нас, был ли код в справочном источнике намеренно написан авторами .NET Framework?

Clemens 11.08.2018 14:05

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

Marius Herzog 11.08.2018 14:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
142
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эта проблема решена в .NET 4.8 путем включения EnableWeakEventMemoryImprovements.

Другие вопросы по теме