Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repeatedly updating explicit Width property causes frame drops #9602

Open
jumhyn-browser opened this issue May 1, 2024 · 4 comments
Open
Labels
area-Performance bug Something isn't working team-Controls Issue for the Controls team

Comments

@jumhyn-browser
Copy link

Describe the bug

I have a situation where there's an element which contains a fairly complex layout, and the width of this component is user-adjustable. When the user grabs the resize handle and begins dragging, events are generated which update the Width property on the element.

Even when throttling the frequency of the Width updates to ~30/sec, it's possible to get into a state where it seems the layout 'falls behind' and stops rendering new frames at all for this component until it is given a chance to catch up (i.e., user stops moving the mouse generating width updates).

I attempted to wait to set the Width property again until a SizeChanged update comes in with the proper width, but it seems like this is still to soon. If the user grabs the handle and drags it around quickly, it's not difficult to fall into the state where the width stops changing. Even though SizeChanged events continue to come in (quite quickly!) the changed size doesn't actually end up rendering to the screen.

Is there a strategy I'm missing here, or something I might be doing obviously wrong?

Steps to reproduce the bug

  1. Create complex layout with user-adjustable width (e.g. ItemsRepeater with many elements)
  2. Adjust Width property rapidly and repeatedly
  3. Observe that updated width on-screen stops changing

Expected behavior

No response

Screenshots

No response

NuGet package version

None

Windows version

No response

Additional context

No response

@jumhyn-browser jumhyn-browser added the bug Something isn't working label May 1, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label May 1, 2024
@codendone codendone added team-Controls Issue for the Controls team area-Performance and removed needs-triage Issue needs to be triaged by the area owners labels May 2, 2024
@codendone
Copy link
Contributor

Can you share a video of what you're seeing? If layout is complex and takes a long time, then running layout at a high frame rate will be problematic. It might be necessary to do a visual-only update to represent how the layout sizes will change and limit the layout update until the end or at a much lower frequency, for example. Layout is not intended to run at 30 fps in general.

@jumhyn-browser
Copy link
Author

@codendone Yeah I'll see if I can reduce this and post a video. I don't necessarily expect layout to run at 30fps (it's gonna take as long as it takes), but the behavior I'm observing is that if I'm issuing size updates at ~30 fps then I can get into a state where frames stop getting drawn to screen entirely, for multiple seconds, until I stop issuing the size updates. So what I'm looking for is either:

  • Changes to the layout system that would ensure intermediate layouts are getting drawn to screen even if the size gets updated and triggers another layout pass quickly, or
  • A reliable signal for 'the layout pass completed and has drawn a frame to screen' so that I can implement the necessary throttling myself rather than relying on timing-based heuristics. It appears that SizeChanged fires too early to be usable for these purposes; that is, even if I ensure that I only issue size updates as quickly as SizeChanged events are coming in, it's still possible for the layout system to 'fall behind' and stop drawing to screen.

@codendone
Copy link
Contributor

The CompositionTarget.Rendered event fires after a layout+render pass has completed. That might help your scenario.

I don't know why rendering would stop for a while. That suggests that a bunch of input events or something starved rendering. Input should coalesce if there are too many, unless that isn't working for some reason.

@jumhyn-browser
Copy link
Author

Thanks, I'll see if coordinating with the Rendered event achieves the results I want. It's definitely plausible that the input events and rapid size updates are starving rendering somehow, but the input events come in at a rate outside of my control, so my goal is to throttle the size updates to "exactly as fast as the layout/render pass occurs" so that I'm not clogging things up or overly pessimizing things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Performance bug Something isn't working team-Controls Issue for the Controls team
Projects
None yet
Development

No branches or pull requests

2 participants