Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SIEM] Adds performance enhancements such by removing wasted renderer…
…s and adding incremental DOM rendering (#43157) ## Summary Whenever you wiggle the "resize" bar on the timeline or any other action within the UI which alters the redux store, all the components `mapStateProps` will and redux will re-render if it sees any of the properties have a shallow compare that returns false. Ref: https://react-redux.js.org/using-react-redux/connect-mapstate This PR fixes Super Date Selector which unnecessarily causes re-renders due to not using selectors or memoizations per guidance from the react-redux project. --- Super Date Selector will re-render on every single change to the redux store regardless of if it needs to render or not. <img width="2072" alt="Screen Shot 2019-08-12 at 11 49 13 AM" src="https://user-images.githubusercontent.com/1151048/62900648-eaa39f80-bd17-11e9-91fd-ed4b1e81e27b.png"> You can see that with something as simple as a slight wiggle of the resizer of timeline causes around 23'ish re-renders <img width="2338" alt="Screen Shot 2019-08-12 at 11 52 54 AM" src="https://user-images.githubusercontent.com/1151048/62900666-f7c08e80-bd17-11e9-8ddd-77093553aaf9.png"> After the fixes it no longer shows it being re-rendered on a redux change and the number or renders drop significantly when resizing timeline. It renders only once: <img width="1857" alt="Screen Shot 2019-08-12 at 3 51 20 PM" src="https://user-images.githubusercontent.com/1151048/62901080-1c693600-bd19-11e9-8f8e-f19df029dd31.png"> --- Some parts of the application are expensive to render and are wasted renders by something such as anonymous functions. By swapping out the `pure` for `React.memo` and using the property compare we can cut out those renders and speed up the application considerably. Before with all the flyout sections causing re-renders when state did not change: <img width="1718" alt="Screen Shot 2019-08-12 at 4 46 29 PM" src="https://user-images.githubusercontent.com/1151048/62959566-589ea400-bdb6-11e9-89f1-047c268e74fd.png"> After with the fix to where the ms is really cheap and the expensive pieces are not rendered unless needed now: <img width="1682" alt="Screen Shot 2019-08-13 at 10 32 55 AM" src="https://user-images.githubusercontent.com/1151048/62959667-82f06180-bdb6-11e9-9cc9-c9c609a0fb71.png"> --- For the timeline and its properties section it contained a large volume of JSX logic called "PropertiesLeft" and "PropertiesRight" in which both were having re-renders involving expensive calculations such as width changes to the date time when you did something as simple as type in a new title or description into the timeline. I broke those two out into PropertiesLeft and PropertiesRight subsections utilizing `React.Memo` for performance improvements. Before when typing a title of timeline, PropertiesRight renders 49+ times: <img width="2030" alt="properties-right-before" src="https://user-images.githubusercontent.com/1151048/63056285-f7093300-bea4-11e9-8f33-a2e63d0468ac.png"> Now it renders only 2 times and most of the time it is skipped with something as simple as a title changing: <img width="2020" alt="properties-right-after" src="https://user-images.githubusercontent.com/1151048/63056339-10aa7a80-bea5-11e9-9c0c-ae12be5b5851.png"> --- When rending feature rich renderers on the timeline it was having a difficult time rendering them all within a reasonable amount of time. This introduces a simple scheduler of incremental loading using `requestIdleCallback` when it is available from the browser, otherwise this will fall back on a `setTimeout` as a polyfill/shim. Ref: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback https://developers.google.com/web/updates/2015/08/using-requestidlecallback https://www.w3.org/TR/requestidlecallback/ Tested on Safari, Firefox, and Chrome. IE-11 looked like it didn't crash :-) Gif of each of the browsers incrementally rendering the rows: Chrome: ![incremental-load-1](https://user-images.githubusercontent.com/1151048/63057036-8fec7e00-bea6-11e9-83f9-7bad3f79746f.gif) ![incremental-load-2](https://user-images.githubusercontent.com/1151048/63057043-92e76e80-bea6-11e9-8f0d-95ea2559b6c7.gif) Firefox: ![firefox-incremental-1](https://user-images.githubusercontent.com/1151048/63057052-97138c00-bea6-11e9-8e15-19f5b7cb0a5e.gif) ![firefox-incremental-2](https://user-images.githubusercontent.com/1151048/63057060-98dd4f80-bea6-11e9-9bf3-c8ae798db9e4.gif) Safari (polyfil/shim only working): ![safari-polyfill-1](https://user-images.githubusercontent.com/1151048/63057099-adb9e300-bea6-11e9-9b94-32a08b5905ad.gif) ![safari-polyfill-2](https://user-images.githubusercontent.com/1151048/63057101-b01c3d00-bea6-11e9-9261-77444272992d.gif) Before Performance picture of the full load. You can see that it will render all rows of 25+ and that causes a lag of up to 2 seconds depending on how complex the renderers are: <img width="1346" alt="Screen Shot 2019-08-13 at 4 24 56 PM" src="https://user-images.githubusercontent.com/1151048/63059739-77339680-bead-11e9-818a-ee19df596855.png"> Afterwards you can see it chops it more evenly up between the rendering and tries to get in 5 at a time and maintain a 60 FPS: <img width="691" alt="Screen Shot 2019-08-14 at 3 59 31 PM" src="https://user-images.githubusercontent.com/1151048/63059764-83b7ef00-bead-11e9-84da-bf66de8a35e6.png"> ### Checklist Use ~~strikethroughs~~ to remove checklist items you don't feel are applicable to this PR. ~~- [ ] This was checked for cross-browser compatibility, [including a check against IE11](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility)~~ ~~- [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md)~~ ~~- [ ] [Documentation](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#writing-documentation) was added for features that require explanation or tutorials~~ - [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios ~~- [ ] This was checked for [keyboard-only and screenreader accessibility](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Accessibility_testing_checklist)~~ ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process) - [x] This includes a feature addition or change that requires a release note and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)
- Loading branch information