Bug 511802 - SashLayout performs unnecessary forced layout + repaint during resize
Summary: SashLayout performs unnecessary forced layout + repaint during resize
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.6   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 4.15 M1   Edit
Assignee: Platform-UI-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
: 501227 (view as bug list)
Depends on:
Blocks: 558392 558394 553533
  Show dependency tree
 
Reported: 2017-02-06 16:33 EST by Stefan Xenos CLA
Modified: 2019-12-18 08:04 EST (History)
8 users (show)

See Also:


Attachments
Effect of the latest change (defered layout) on Windows 7 (428.02 KB, video/x-matroska)
2019-12-13 07:33 EST, Paul Pazderski CLA
no flags Details
Deferred Layout on Linux (1.37 MB, image/gif)
2019-12-17 13:39 EST, Lars Vogel CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan Xenos CLA 2017-02-06 16:33:43 EST
I recently had a UI freeze in my log. After investigation, I discovered that SashLayout is forcing a synchronous uncached layout and full repaint on each mouse event. Neither of these are necessary. They can be replaced by a call to requestLayout.

It performs an asynchronous layout that merges with other layout events, doesn't block the event loop, and will only repaint those regions of the screen whose size actually changed.
Comment 1 Eclipse Genie CLA 2017-02-06 16:36:25 EST
New Gerrit change created: https://git.eclipse.org/r/90460
Comment 3 Lars Vogel CLA 2017-02-07 03:39:07 EST
SashLayout is not API, so we can simply remove "layoutUpdateInProgress". Gerrit patch to follow.
Comment 4 Eclipse Genie CLA 2017-02-07 03:41:59 EST
New Gerrit change created: https://git.eclipse.org/r/90493
Comment 5 Stefan Xenos CLA 2017-02-07 08:07:46 EST
Why is it not API? It looks to me like an exported package without the word internal. Doesn't that make it API?
Comment 6 Lars Vogel CLA 2017-02-07 08:18:53 EST
(In reply to Stefan Xenos from comment #5)
> Why is it not API? It looks to me like an exported package without the word
> internal. Doesn't that make it API?

Everything which is marked as x-internal or x-friends in the MANIFEST.MF is not API.

Export-Package: org.eclipse.e4.ui.internal.workbench.renderers.swt;x-friends:="org.eclipse.ui.workbench",
 org.eclipse.e4.ui.workbench.renderers.swt;x-friends:="org.eclipse.e4.ui.workbench.addons.swt,org.eclipse.ui.workbench"
Comment 8 Andrey Loskutov CLA 2017-02-12 06:31:00 EST
This change ruines drag/drop views re-layout. Just grab the resize handler shown if you mouse hovers in the top left corner of the problems view and try to resize vies. The resize doesn't follow the mouse anymore, it feels as if this waits seconds to relayout itself.
Comment 9 Eclipse Genie CLA 2017-02-12 06:32:43 EST
New Gerrit change created: https://git.eclipse.org/r/90889
Comment 11 Stefan Xenos CLA 2017-02-12 12:13:11 EST
Andrey, what platform are you using? It works great for me on GTK.
Comment 12 Andrey Loskutov CLA 2017-02-12 12:13:55 EST
(In reply to Stefan Xenos from comment #11)
> Andrey, what platform are you using? It works great for me on GTK.

Windows 10, sorry.
Comment 13 Stefan Xenos CLA 2017-02-13 09:49:05 EST
Either we'll need a plaform-specific fix or we'll need to fix the windows port of SWT such that it repaints properly in such situations. My inclination is the latter, since we've had other reports of windows not repainting and there's quite a few workarounds in place. Fixing this at the SWT layer would eliminate the need for such platform-specific workarounds and would also fix other similar bugs.
Comment 14 Lars Vogel CLA 2017-03-03 03:49:17 EST
Mass move. Please move back to M6, if necessary
Comment 15 Lars Vogel CLA 2017-05-08 04:01:11 EDT
I assume this is to late for 4.7. Stefan, please move back in case you have something planned here.
Comment 16 Stefan Xenos CLA 2017-05-08 13:05:01 EDT
Nothing planned for M7.
Comment 17 Dani Megert CLA 2018-05-24 12:55:48 EDT
Removing target milestone for all bugs that are not major or above.
Comment 18 Dani Megert CLA 2018-05-25 04:06:12 EDT
> Removing target milestone for all bugs that are not major or above.

Of course I meant "major or below".

Sorry for the noise!
Comment 19 Lars Vogel CLA 2019-12-13 03:36:41 EST
*** Bug 501227 has been marked as a duplicate of this bug. ***
Comment 20 Lars Vogel CLA 2019-12-13 03:44:28 EST
Woh, a full synchronous layout call within a mouse move listener in SashLayout? No wonder the UI is laggy.
Comment 21 Eclipse Genie CLA 2019-12-13 03:54:44 EST
New Gerrit change created: https://git.eclipse.org/r/154452
Comment 22 Lars Vogel CLA 2019-12-13 04:09:02 EST
See also Bug 558290.
Comment 23 Paul Pazderski CLA 2019-12-13 07:33:04 EST
Created attachment 281231 [details]
Effect of the latest change (defered layout) on Windows 7

(In reply to Stefan Xenos from comment #0)
> I recently had a UI freeze in my log. After investigation, I discovered that
> SashLayout is forcing a synchronous uncached layout and full repaint on each
> mouse event. Neither of these are necessary. They can be replaced by a call
> to requestLayout.
> 
> It performs an asynchronous layout that merges with other layout events,
> doesn't block the event loop, and will only repaint those regions of the
> screen whose size actually changed.

I don't think a synchronous layout/repaint is avoidable. While dragging the sash you want to see the changes. I would expect any asynchronicity or deferral to be visible as lagging or tearing. (what Andrey described in comment 8) In fact I'm surprised it works on Linux. I assume it does the layout quite fast after request and only reduce the total number of layouts a bit.

Imo 'blocking' the event loop (I would not expect it is fully blocked) isn't so bad in this context. I would expect user produced messages are most impotent with regard to responsiveness but user is already engaged in changing the layout.

Where I agree is the uncached and probably the full repaint part. Unfortunately simply changing the layout call to not flush caches will not help because the layout method of SashLayout is ignoring this flag atm.

So (from my current state of knowledge) improving the layout implementation and reducing the area of redraw is something that should be possible and improve the freezing part. Such a change isn't be trivial but I would give it a try.

PS: the tearing seen in attached video was almost nothing influenced by the capturing. It might cleanup the tearing a bit more often without but the overall effect is absolutely the same.
Comment 24 Lars Vogel CLA 2019-12-13 07:47:17 EST
(In reply to Paul Pazderski from comment #23)

> So (from my current state of knowledge) improving the layout implementation
> and reducing the area of redraw is something that should be possible and
> improve the freezing part. Such a change isn't be trivial but I would give
> it a try.

Thanks. I read this as that you are planning to give it try.
Comment 25 Paul Pazderski CLA 2019-12-13 07:49:09 EST
(In reply to Lars Vogel from comment #24)
> (In reply to Paul Pazderski from comment #23)
> 
> > So (from my current state of knowledge) improving the layout implementation
> > and reducing the area of redraw is something that should be possible and
> > improve the freezing part. Such a change isn't be trivial but I would give
> > it a try.
> 
> Thanks. I read this as that you are planning to give it try.

Yes, as long as nobody comes and shows me where my explanation is totally wrong.
Comment 26 Stefan Xenos CLA 2019-12-16 14:51:26 EST
> While dragging the sash you want to see the changes. I would expect
> any asynchronicity or deferral to be visible as lagging or tearing. 

"Deferring" a layout only defers it until control returns to the event loop, which is generally a matter of milliseconds. You don't see it. Normally it still happens before the next vsync, so it's generally completely invisible.

However, this deferral is extremely important for the asymptotic runtime of the layouts, since multiple controls can (and do) change on a single pass through the event loop. If each control in your hierarchy performed a synchronous layout the runtime would be O(n^2). If each control performs an asynchronous layout, the runtime is O(n).

It seems like each time I filed one of these, someone encounters asynchronous layouts for the first time and says they shouldn't be asynchronous. I then generally responded by posting a benchmark comparing that particular layout coded in synchronous versus asynchronous algorithms that shows the asynchronous version outperforming the synchronous one by at least an order of magnitude.

Since I don't work on Eclipse anymore, I won't code up another one this time. However, if you search through bugzilla you'll find at least 4 other instances of this discussion with sample code and benchmarks. (The first occurrence was with Steve Northover. It should be easy to find since the benchmarks there were the reason he introduced deferred layouts to SWT in the first place.)

Rendering is (and needs to be) an asynchronous pipeline. App code modifies controls, which dirty layouts. Then a layout pass happens asynchronously which dirties controls for painting. Trying to force a synchronous layout or synchronous paint never makes things faster.
Comment 27 Lars Vogel CLA 2019-12-16 14:56:08 EST
(In reply to Stefan Xenos from comment #26)

> Rendering is (and needs to be) an asynchronous pipeline. App code modifies
> controls, which dirty layouts. Then a layout pass happens asynchronously
> which dirties controls for painting. Trying to force a synchronous layout or
> synchronous paint never makes things faster.

Thanks Stefan for still listening it. The issue here seems to be that Windows SWT does not repaint if no sync layout call is triggered. Maybe this is buggy on SWT Win. Works fine on Linux, not sure about Mac.
Comment 28 Stefan Xenos CLA 2019-12-16 15:04:08 EST
> The issue here seems to be that Windows SWT does not repaint if no sync layout
> call is triggered. 

Fair enough. But the fix would be to figure out why the async layouts aren't running, not force a synchronous one.
Comment 29 Paul Pazderski CLA 2019-12-16 20:20:11 EST
(In reply to Stefan Xenos from comment #26)
> > While dragging the sash you want to see the changes. I would expect
> > any asynchronicity or deferral to be visible as lagging or tearing. 
> 
> "Deferring" a layout only defers it until control returns to the event loop,
> which is generally a matter of milliseconds. You don't see it. Normally it
> still happens before the next vsync, so it's generally completely invisible.

Right. I overlooked that deferred layout is run after *any* OS event. It kind of crossed my mind it would layout after current event queue was exhausted. I'm a bit biased because my first deeper contact with SWT layouts was a bug where deferred layout failed and was deferred for seconds, minutes or forever.


(In reply to Stefan Xenos from comment #28)
> > The issue here seems to be that Windows SWT does not repaint if no sync layout
> > call is triggered. 
> 
> Fair enough. But the fix would be to figure out why the async layouts aren't
> running, not force a synchronous one.

One of the reasons is that another patch for deferred layout problems was applied for GTK but not for Windows and Mac.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=416845

But even with this change applied there remain ugly rendering problems on Windows.
Comment 30 Lars Vogel CLA 2019-12-17 04:31:03 EST
Matthias checked MacOS and it also behaves fine. I plan to push later tonight a patch which uses requestLayout on Linux and MacOS and the evil layout call only on Windows. No need to suffer from Windows bugs on other OSs.

From Paul: 

> One of the reasons is that another patch for deferred layout problems was >applied for GTK but not for Windows and Mac.
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=416845

Thanks Paul for looking into this. I don't see a patch in Bug 416845. Could you point me to the corresponding commit / bug report? Or even better, could you open a bug for Windows / Mac for the missing fix?
Comment 31 Paul Pazderski CLA 2019-12-17 04:59:53 EST
(In reply to Lars Vogel from comment #30)
> Matthias checked MacOS and it also behaves fine.

With or without bug 416845?

> From Paul: 
> 
> > One of the reasons is that another patch for deferred layout problems was >applied for GTK but not for Windows and Mac.
> > https://bugs.eclipse.org/bugs/show_bug.cgi?id=416845
> 
> Thanks Paul for looking into this. I don't see a patch in Bug 416845. Could
> you point me to the corresponding commit / bug report? Or even better, could
> you open a bug for Windows / Mac for the missing fix?

One reason you see no patch is because I linked the wrong bug in my comment. Correct is bug 354762. Added the corresponding commit there.

I'll not open for Mac. It seem to work fine on Mac and if it also works with deferred layout I would not add the update() without reason.
For Windows the change does not fix the problem. I opened bug 558392 instead and depending on the outcome it may include this change.

Regardless of the sync vs async stuff I still think the SashLayout layout() implementation is improvable and should not ignore the flushCache flag.
Comment 32 Paul Pazderski CLA 2019-12-17 05:00:36 EST
(In reply to Paul Pazderski from comment #31)
> (In reply to Lars Vogel from comment #30)
> > Matthias checked MacOS and it also behaves fine.
> 
> With or without bug 416845?

Sorry. Copied wrong number again. With or without bug 354762?
Comment 33 Lars Vogel CLA 2019-12-17 05:46:29 EST
(In reply to Paul Pazderski from comment #31)

> Regardless of the sync vs async stuff I still think the SashLayout layout()
> implementation is improvable and should not ignore the flushCache flag.

+1 I opened Bug 558394 for that.
Comment 34 Matthias Becker CLA 2019-12-17 08:29:16 EST
(In reply to Paul Pazderski from comment #32)
> (In reply to Paul Pazderski from comment #31)
> > (In reply to Lars Vogel from comment #30)
> > > Matthias checked MacOS and it also behaves fine.
> > 
> > With or without bug 416845?
> 
> Sorry. Copied wrong number again. With or without bug 354762?

I just fetched https://git.eclipse.org/r/#/c/153948/ into my workspace. That's all.
Comment 35 Lars Vogel CLA 2019-12-17 13:39:13 EST
Created attachment 281257 [details]
Deferred Layout on Linux
Comment 37 Lars Vogel CLA 2019-12-18 07:19:42 EST
Marking the follow-up bugs as dependent bugs so that he can easier correlate them. Marking as fixed as Mac and Linux benefit from this change.

Likelihood that this causes also issues on these platform is there, so we may see a reopen soon. :-)