-
Notifications
You must be signed in to change notification settings - Fork 841
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
[EuiFlyout] Performance cleanup #7462
[EuiFlyout] Performance cleanup #7462
Conversation
expect(add).toHaveBeenLastCalledWith('euiBody--hasFlyout'); | ||
}); | ||
|
||
it('should not remove and re-add "euiBody--hasFlyout" class on resize', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes are mainly an optimization which is sort of hard to test, so instead I wrote some tests for the euiBody--hasFlyout
class and included this test case that would otherwise fail without the optimization.
Hey @davismcphee! Just wanted to check in on this PR - it looks great to me honestly, should I go ahead and mark its as ready for review + add a changelog to it? Happy to take over and bring it across the finish line if you're busy with other things! |
We are currently evaluating EuiDataGrid for the UnifiedDocViewer, and created an instance which applies resizable flyouts and a basic migration of the DocViewer, to measure the performance impact We merged also this fix in this deployment, it resolved the issue in Chrome 🥳 , but still, Firefox + Safari 😿 don't provide the expected performance, Chrome - Left, Firefox - Right Kapture.2024-02-07.at.10.18.22.mp4 |
Adding a throttler/debouncer to the width changes would be the next step to improving performance - would that be something y'all would like to request as a feature/prop as well? |
@cee-chen is this the reason for the performance difference between Chrome and the rest of the gang? If this is the case I think throttling resizing should be applied (not optional) |
It's the most obvious approach that I can think of, but I have no idea if that's the difference between browsers, and it isn't guaranteed to fix the issue per se. The other approach would be to check/optimize the number of rerenders on the rest of the page that's reflowing, as that's likely the culprit of repaint/reflow performance issues, but that's obviously far more involved & harder to do. |
…and styles to be toggled multiple times each render, resulting in a lot of extra reflows in the browser
… prevent layout thrashin g when resizing
b6a5a04
to
ef70c47
Compare
482b9ef
to
f85b22f
Compare
@cee-chen Apologies for taking so long getting back to you on this one! I finally had a chance to revisit this PR and track down the main culprit for the performance issue. It turns out that in addition to toggling the It looks like eui/src/components/observer/resize_observer/resize_observer.tsx Lines 106 to 109 in 635f860
But I assume this code is old and isn't actually needed anymore since |
Super interesting, thanks for discovering this Davis! I actually think this is important enough to address at the WDYT? |
@cee-chen Thanks for opening #7575! I think it's a great idea to implement this at the resize observer level. We'll probably even see performance gains elsewhere in Kibana just from that. For this PR, the resize observer change would of course need to be reverted, but would you be open to still taking the original |
@davismcphee Yes, 100%, I definitely want that change! 😄 |
- add a ternary to *not* instantiate the resize observer if this isn't a push flyout (addresses the old TODO) - DRY out `paddingSide` logic more - move body className comment to multiline format (file organization)
- the body class code is now much simpler, so we can adjust tests accordingly
@davismcphee Alrighty, I've updated the PR with latest main and pushed up the minor changes I had - did you want to re-test the performance impacts to make sure everything's still shipshape, or is this good to merge in your opinion? |
Preview staging links for this PR:
|
💚 Build Succeeded
History
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cee-chen I gave it another try in Discover with the resize observer fix and latest changes, and I can confirm performance is good in Chrome, Firefox, and Safari (relatively)!
|
||
document.body.style[paddingSide] = `${width}px`; | ||
return () => { | ||
document.body.style[paddingSide] = ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed while testing this gets called on each frame as the width
changes when resizing, but it didn't seem to have much if any performance impact in Chrome, Firefox, or Safari.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a million for checking that Davis! 🙇
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merging - thanks again for your awesome work Davis, you rock!! ❤️🔥
`v93.3.0`⏩ `v93.4.0` --- ## [`v93.4.0`](https://github.com/elastic/eui/releases/v93.4.0) - Added the following properties to `EuiButtonGroup`'s `options` configs: `toolTipContent`, `toolTipProps`, and `title`. These new properties allow wrapping buttons in `EuiToolTips`, and additionally customizing or disabling the native browser `title` tooltip. ([#7461](elastic/eui#7461)) - Enhanced `EuiResizeObserver` and `useResizeObserver`'s performance to not trigger page reflows on resize event ([#7575](elastic/eui#7575)) - Updated `EuiSuperUpdateButton` to support custom button text via an optional `children` prop ([#7576](elastic/eui#7576)) **Bug fixes** - Fixed `EuiFlyout` to not repeatedly remove/add a body class on resize ([#7462](elastic/eui#7462)) - Fixed `EuiToast` title text to wrap instead of overflowing out of the container ([#7568](elastic/eui#7568)) - Fixed a visual bug with `EuiHeaderBreadcrumbs` with popovers ([#7580](elastic/eui#7580)) **Deprecations** - Deprecated `euiPalettePositive` and `euiPaletteNegative` in favour of a more culturally inclusive `euiPaletteGreen` and `euiPaletteRed` ([#7570](elastic/eui#7570)) - Deprecated all charts theme exports in favor of `@elastic/charts` exports: ([#7572](elastic/eui#7572)) - Deprecated `EUI_CHARTS_THEME_<DARK|LIGHT>` in favor of `<DARK|LIGHT>_THEME` from `@elastic/charts`. ([#7572](elastic/eui#7572)) - Deprecated `EUI_SPARKLINE_THEME_PARTIAL` in favor of `useSparklineOverrides` theme from the kibana `charts` plugin `theme` service. **Accessibility** - Updated `EuiModal` to set an `aria-modal` attribute and a default `dialog` role ([#7564](elastic/eui#7564)) - Updated `EuiConfirmModal` to set a default `alertdialog` role ([#7564](elastic/eui#7564)) - Fixed `EuiModal` and `EuiConfirmModal` to properly trap Safari+VoiceOver's virtual cursor ([#7564](elastic/eui#7564))
Summary
This PR includes two changes which optimize browser reflows when using
EuiResizableFlyout
, which has a significant impact on the performance of the flyout in heavy pages such as Discover:Switched from theuseResizeObserver
hook to aResizeObserver
directly to track the flyout size, since the use ofgetBoundingClientRect
inuseResizeObserver
causes layout thrashing when combined with the body padding modifications made by the flyout.getBoundingClientRect()
usage on resize #7575, but a small microperf addition has been made to not instantiate a resize observer at all for non-push flyoutseuiBody--hasFlyout
class, or remove/re-add body padding whenever the flyout size changes. Instead the class is only added/removed on mount/unmount, and the body padding is only updated on resize and removed on unmount.In my tests of frantically resizing the Discover flyout for 10 seconds while profiling, these changes brought the time Chrome spent on
Recalculate Style
from 4.8s to 0.8s:Unoptimized:
Optimized:
And a couple of videos from Discover for reference:
Unoptimized:
unoptimized.mp4
Optimized:
chromium.mp4
The optimizations also improve the performance in Firefox and Safari. Performance in Safari is still a bit slow compared to the other browsers, but it's acceptable and at least much better than before.
Firefox:
firefox.mp4
Safari:
safari.mp4
QA
General checklist
- [ ] Checked for accessibility including keyboard-only and screenreader modes- [ ] If applicable, added the breaking change issue label (and filled out the breaking change checklist)