WPF Performance. Wrong dirty rect calculation

1.4k Views Asked by At

I currently work in a customer assignment related to performance problems in a WPF rich client LOB application.

The problem is that the application runs very slow/sluggish. Especially data table handling (scrolling, sorting, selection) is extremely slow and leaves the application unusable.

I analyzed the system state when a single tab containing a few textboxes, comboboxes and labels is opened and left idle (waiting for user input).

These are my findings:

  • All the rendering is calculated on the GPU
  • There are no performance heavy features such as animations, bitmap effects, transparency, etc.
  • When the tab is idle (only the cursor is blinking in the focused textbox, the rest of the tab is static and does not even contain any data) the GPU runs up to 90%
  • GPU drops to 0 whenever the tab loses focus
  • GPU percentage directly relates to the window size. A small window brings it down to a few percent, full screen makes it go up to almost 100%
  • WPF Perforator tells me that WPF calculates the dirty region for the entire tab instead of only the blinking cursor
  • WPF Perforator reports dirty rect update rates larger than 20/sec on the idle tab and they directly correlate to GPU usage

My conclusion: During development a lot of custom code (layout, event handling, etc..) has been introduced in order to fit WPF to the backend-driven architecture of the system as a whole. My guess is that due to some of the custom code the dirty-rect-mechanism of WPF has been broken. This leads to too much drawing activity and thus very high GPU usage. These innecessary activities lead to the problems described above.

Now I am looking for any advice where I should start my investigation. Or in other words: What are typical mistakes that a developer can make in order to break the WPF dirty-rect update algorithm. Any input is highly appreciated.

Many thanks and best regards!

Manuel

1

There are 1 best solutions below

0
On

Thanks for the input. Let me clarify backend-driven: The UI is highly dynamic. A message from the backend defines the structure of the ui and the data to be displayed. Therefore, we do not have any xaml for the structure of the tabs, only c#.

In the meantime, I could solve the problem. I used Snoop and collapsed every element one by one while monitoring GPU usage. I found out that there was a very tiny pixelshader effect (DropShadowEffect) on one of the borders. As soon as I removed the effect, the GPU dropped from 80% to 1%. WPF drew correct dirty rectangles over small portions of the UI. Problem solved, case closed.

Things that seem interesting to me: 1. The tremendous impact that this small effect has on the GPU usage. 2. That it breaks the dirty-rect calculation. 3. Since it was not a BitmapEffect but a PixelshaderEffect I could not reveal it by disabling BitmapEffects in Perforator.

Thanks! MM