-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Discover] Fix performance regression in sidebar #109999
[Discover] Fix performance regression in sidebar #109999
Conversation
Pinging @elastic/kibana-app (Team:KibanaApp) |
@elasticmachine merge upstream |
@kertal - its already past FF for 7.14.1 , but bug fixes are still ok , Do you think it will make it or move the label to 7.14.2 ? |
…of github.com:kertal/kibana into kertal-pr-2021-08-25-discover-fix-sidebar-performance
@rashmivkulkarni it would be neat to fix this in 7.14.1, I see the tag is not available now, so let's see if I can make it today |
@@ -15,6 +15,11 @@ import { IndexPatternField } from '../../../../../../../data/public'; | |||
import { stubIndexPattern } from '../../../../../../../data/common/stubs'; | |||
|
|||
jest.mock('../../../../../kibana_services', () => ({ | |||
getUiActions: jest.fn(() => { |
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.
less error messages when executing the test
if (fieldCounts.current === null) { | ||
fieldCounts.current = calcFieldCounts( | ||
{}, | ||
props.documents$.getValue().result, | ||
props.selectedIndexPattern | ||
); | ||
} |
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.
make surecalcFieldCounts
is just executed once
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 think this can be moved to useEffect, before subscription, which should initialized after mounting
@@ -358,7 +358,36 @@ function DiscoverFieldComponent({ | |||
</EuiPopoverTitle> | |||
); | |||
|
|||
const details = getDetails(field); | |||
const renderPopover = () => { | |||
const details = getDetails(field); |
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.
making sure getDetails
is just executed when needed (popover is displayed)
💚 Build SucceededMetrics [docs]Async chunks
History
To update your PR or re-run it, just comment with: cc @kertal |
|
||
const [documentState, setDocumentState] = useState(props.documents$.getValue()); | ||
useEffect(() => { | ||
const subscription = props.documents$.subscribe((next) => { | ||
if (next.fetchStatus !== documentState.fetchStatus) { | ||
if (next.result) { | ||
fieldCounts.current = calcFieldCounts( | ||
next.result.length ? fieldCounts.current : {}, | ||
next.result.length && fieldCounts.current ? fieldCounts.current : {}, |
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'm still having trouble understanding this logic. we're calculating fieldCounts, passing in the value that we got as a result of passing in the previous result of calcFieldCounts
?
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.
yes, it's like it behaved for a long time, didn't change, but I think it should be in the future.
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 believe this logic needs some revisiting, but after testing I don't think it's broken. Let's see if we can do some cleanup here in a follow-up PR.
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.
👍 wanna add an issue for that?
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.
Tested in Chrome on Mac OSX, can confirm that functionality-wise it works same as before. Haven't done a detailed profiling on performance optimization, but it seems pretty clear from the code.
💔 Backport failed
Successful backport PRs will be merged automatically after passing CI. To backport manually run: |
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.
LGTM, tested in Chrome. One of the thing should be changed in follow up PR here is subscription after mounting.
props.documents$.getValue().result, | ||
props.selectedIndexPattern | ||
); | ||
} | ||
|
||
const [documentState, setDocumentState] = useState(props.documents$.getValue()); | ||
useEffect(() => { | ||
const subscription = props.documents$.subscribe((next) => { |
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.
documentState
dependency change leads to initializing subscription two times. So the first listener will not be cleaned up, but I guess it was before.
if (fieldCounts.current === null) { | ||
fieldCounts.current = calcFieldCounts( | ||
{}, | ||
props.documents$.getValue().result, | ||
props.selectedIndexPattern | ||
); | ||
} |
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 think this can be moved to useEffect, before subscription, which should initialized after mounting
Co-authored-by: Matthias Wilhelm <[email protected]>
# Conflicts: # src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.test.tsx
# Conflicts: # src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.test.tsx # src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx
# Conflicts: # src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.test.tsx # src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx
Summary
This PR fixes a performance regression in Discover sidebar introduced in 7.14 when searching the sidebar containing lots of fields that need to be grouped (so it's not just the number of fields, but the structure). The function to calculate details displayed in the popover was executed without the popover being displayed. So when 25 fields were displayed, it was calculated 25 times (luckily we just render the fields that are visible to the user). What's more
calc_field_count
had redundant executions, which also worsens performance.Here's an example how the performance profile looked like on a system with performance problems:
Testing
I'm adding a files (sidebar-stress.zip) so you can reproduce it. You can use it to provision 500 records with a structure to trigger the performance troubles.
Before that you need to configure the created index so it can contain lot's of fields by running
When ingested, you need to create an index pattern for
sidebar-search-test
, go to Discover, search in the sidebar, this should no longer be very, very slow.fixes #109998
Checklist