Devin
Devin

Reputation: 1064

Performance issue with "Measure"

I'm encountering a performance issue in my application. Essentially I click a button, and a list is populated with databound data (this is virtualized because of the large amount of data), and then click another button which will add a row to an associated list view. I'm being vague because I think it's just necessary to illustrate how little is actually going on in the UI.

Here's what I know:

Right now I'm assuming that the issue is with the GPU. I've updated the driver with no improvements.

  1. Even though I don't think it's an issue with code, is there a WPF equivalent to "SuspendLayout()"
  2. Is there a way to profile GPU performance to see if it is being hammered during certain processes
  3. (far shot) Has anyone had similar performance issues that seem to be computer specific and suggestions on how to track them down?

Sorry if this is a vague question. I tried to make it comply with SO's usage reqs. Let me know if you want any more info.

Just as an addendum: The program is using WPF, C# 4.0, the issue seems to be around Telerik controls (though I don't think they're suspect since we use them elsewhere without issue).

Upvotes: 3

Views: 2613

Answers (2)

Glenn Slayden
Glenn Slayden

Reputation: 18829

1. Answer

To to prevent rampant MeasureOverride calls originating from the WPF ContextLayoutManager:

protected override void OnChildDesiredSizeChanged(UIElement el)
{
    /* base.OnChildDesiredSizeChanged(el); */       // avoid rampant remeasuring
}

2. Relevant citation

UIElement.OnChildDesiredSizeChanged(UIElement) Method
  ...

The OnChildDesiredSizeChanged(UIElement) method has the default implementation of calling InvalidateMeasure() on itself. A typical implementation would be: do whatever optimization your own element supports, and then typically call base OnChildDesiredSizeChanged(UIElement) from a̲t̲ l̲e̲a̲s̲t̲ o̲n̲e̲ of the code branches...

...the implication (and fact-of-the-matter) being that, for any single parent layout pass originated by any one of its children, the parent's MeasureOverride will be called additionally—and likely extraneously—once for each of its children whose size(s) have changed as well.

3. Discussion

In the case where multiple children change their sizes "at the same time", the parent will typically detect and account for the new overall layout amongst all of its children entirely during just the first of these calls. This is standard practice in WPF, and is encouraged by MeasureOverride(…) deliberately excluding any indication of some specific triggering child. Besides the fact that in the most common cases there is no such child (see above link for details), it makes code for attempting any sort of "partial layout" onerous. But mostly, why would any layout calculation ever want to proceed without first obtaining all the very latest available measurements anyway?

So we see that after a single MeasureOverride call, triggered by whichever child happened to be "first" (it shouldn't matter), the layout of the parent should actually be final regarding all of its latest child size information. But this doesn't mean that any queued OnChildDesiredSizeChanged notifications—for other children whose size(s) had also changed—have gone away. Those calls are still pending with the parent, and unless the virtual base call is explicitly abandoned (as shown in bullet #1), each will generate one additional, now-extraneous MeasureOverride call.

4. Caveat

The code shown here disables a̲l̲l̲ child-initiated measure invalidations, which is appropriate for cases where the parent either willfully forbids such changes, or is inherently already aware of them. This is not uncommon; for example, it includes any parent that always fully determines and enforces the size of its children, or more generally, any parent that only adopts DesiredSize values from its children during its own measure pass. What's important is that the measuring of the parent be sufficiently guaranteed by its own parent only.

The situation where a parent might wish to cancel some of the child-initiated measure notifications while preserving/allowing others will naturally depend on additional particular circumstances. It seems more obscure, so it is not addressed here.

Upvotes: 2

Devin
Devin

Reputation: 1064

Turns out it's caused by a known Microsoft issue. I’d try to explain, but I won’t. Mainly because I can’t.

Article talking about fix (see post by Viðar on 3 August 2010):

Microsoft Hotfix site: http://support.microsoft.com/kb/2484841/en-us

Fix: http://archive.msdn.microsoft.com/KB2484841/Release/ProjectReleases.aspx?ReleaseId=5583

Upvotes: 2

Related Questions