-
Notifications
You must be signed in to change notification settings - Fork 605
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
Bug 2053685: (Topology) Performance improvement by reducing rerenderings and deep-copy toJSON() calls #11001
Bug 2053685: (Topology) Performance improvement by reducing rerenderings and deep-copy toJSON() calls #11001
Conversation
/cc @christianvogt @spadgett @jhadvig @invincibleJai |
frontend/packages/console-dynamic-plugin-sdk/src/utils/k8s/hooks/k8s-watcher.ts
Outdated
Show resolved
Hide resolved
@@ -19,7 +19,9 @@ const shallowMapEquals = (a, b) => { | |||
return a.every((v, k) => b.get(k) === v); | |||
}; | |||
|
|||
const processReduxId = ({ k8s }, props) => { | |||
const CACHE_SYMBOL = Symbol('_cachedToJSResult'); |
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.
Safe to use the same symbol as the watcher. However since firehose
is old and would probably be more grief to share the symbol with the sdk.
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.
INTERNAL_REDUX_IMMUTABLE_TOJSON_CACHE_SYMBOL
is fine for you? 🤣 🤣
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 added this to the SDK because we have already an import from firehose.jsx to the SDK. I'm not sure what the "right' import direction here....?!
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.
Having it in the SDK is correct. I dislike exporting such an internal thing but whatever I suppose since we own the console sdk and can manage it ¯\_(ツ)_/¯
@jerolimov I agree that removing immutable JS is something we should look at doing but it's a much larger change. This is a good first step and proves there's a larger issue to address with immutable js and our redux store. |
6489f6d
to
f387c48
Compare
}, | ||
})), | ||
metadata: { resourceVersion: '123' }, | ||
}; |
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.
Looks like this file is duplicate of frontend/packages/console-dynamic-plugin-sdk/src/utils/k8s/hooks/__tests__/useK8sWatchResource.data.tsx
.
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.
Yeah I duplicated the test-data files so that they don't depend on each other.
export const podData = { | ||
apiVersion: 'v1', | ||
kind: 'Pod', | ||
metadata: { | ||
name: 'my-pod', | ||
namespace: 'default', | ||
resourceVersion: '123', | ||
}, | ||
}; | ||
|
||
export const podList = { | ||
apiVersion: 'v1', | ||
kind: 'PodList', | ||
items: ['my-pod1', 'my-pod2', 'my-pod3'].map((name) => ({ | ||
apiVersion: 'v1', | ||
kind: 'Pod', | ||
metadata: { | ||
name, | ||
namespace: 'default', | ||
resourceVersion: '123', | ||
}, | ||
})), | ||
metadata: { resourceVersion: '123' }, | ||
}; |
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.
we can reuse podList
and podData
from useK8sWatchResource.data.tsx
. I think it is better to use podList
and podData
from here and delete useK8sWatchResource.data.tsx
and useK8sWatchResources.data.tsx
. wdyt?
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.
This is a different package. Yes, we have already dependencies from public package (console/internal) to packages/console-dynamic-plugin-sdk but I would like to keep a copy here instead of adding more dependencies between both.
Thanks @jerolimov I tried to verify it and the performance has improved, I verified topology with the below scenario
Verified on
|
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.
/approve
I'm OK with the approach as a short-term fix we can backport. @jerolimov Let's open a follow up issue to remove immutable, which seems like a better long-term approach. We should try to give it priority since this change will increase the in-memory size of the k8s resource data.
@jerolimov: This pull request references Bugzilla bug 2053685, which is valid. The bug has been moved to the POST state. The bug has been updated to refer to the pull request using the external bug tracker. 3 validation(s) were run on this bug
Requesting review from QA contact: In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@jerolimov: This pull request references Bugzilla bug 2053685, which is valid. 3 validation(s) were run on this bug
Requesting review from QA contact: In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
1 similar comment
@jerolimov: This pull request references Bugzilla bug 2053685, which is valid. 3 validation(s) were run on this bug
Requesting review from QA contact: In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/approve |
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.
Verified it using cluster bot. In Chrome and Safari browsers with 100 D and 80 Pods in Topology and it is faster than before.
/lgtm
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: christianvogt, jerolimov, spadgett, vikram-raj The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/retest-required Please review the full test history for this PR and help us cut down flakes. |
@jerolimov: All pull requests linked via external trackers have merged: Bugzilla bug 2053685 has been moved to the MODIFIED state. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@jerolimov: all tests passed! Full PR test history. Your PR dashboard. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
/cherry-pick release-4.10 |
@jerolimov: new pull request created: #11059 In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Fixes:
https://bugzilla.redhat.com/show_bug.cgi?id=2053685
Tl;dr
First commit adds only tests, second commit adds caching for previously deep-cloned data.
This cache of the JSON data which are already used in the topology allows the topology and many other components to do less useMemo, useEffect, re-calculations and re-renderings. In topology, this happens because an object replacement in a GraphNode rerenders it.
Analysis / Root cause:
While analyzing our topology performance issues I found two (main) issues which are addressed in this PR. (This is not the first and not the last PR for topology.)
toJSON()
method.After further investigation I noticed that the toJSON function is called in
Firehose
,useK8sWatchResource
anduseK8sWatchResources
when converting an immutable object to JSON. This happens whenever a component is rendered and uses one of the hooks.It also rerenders or recalculates hooks to often with the same data because the created JSON object contains the same data in a new, deep-clone object or array. But
Memo
d-components, hooks dependencies, and other optimizations like the topologymobx
graph tree depends on an identity to check to rerender components..Solution Description:
This PR improves the topology performance or the performance of many different pages with an "immutable toJSON" result cache in
firehose.jsx
andk8s-watcher.tsx
It adds a cache and saves the converted JSON data at the immutable object itself. (Thanks Christian for this great idea.)
♻️ To see and test what will change with this caching I first added some tests to the Firehose component and the hooks.
❓ Why not just remove Immutable from the Redux store?!
I think removing Immutable would be a good idea. For the future.
But adding this cache has some benefits for the moment: It's easier and safer to add/test/verify and I hope that we can backport this. I don't expect that we would backport a rewrite of the reducers, and selectors, etc.
Videos
Before - Load topology with many deployments (in my case 84)
before-topology-initial-load.mp4
After - Load topology with many deployments (in my case 84)
after-topology-initial-load.mp4
Before - Stay on the topology page with many deployments (here 84) and delete a random pod every 3 second
before-topology-deleting-pods.mp4
After - Stay on the topology page with many deployments (here 84) and delete a random pod every 3 second
after-topology-deleting-pods.mp4
Performance screenshots
Before - Load topology with many deployments (in my case 84)
After - Load topology with many deployments (in my case 84)
Before - Stay on the topology page with many deployments (here 84) and delete a random pod every 3 second
After - Stay on the topology page with many deployments (here 84) and delete a random pod every 3 second
todo
Screen shots / Gifs for design review:
UI isn't changed. Here are som
Unit test coverage report:
Added a lot of tests for the existing components
Firehose
,useK8sWatchResource
anduseK8sWatchResources
to check the status quo and track the difference with this PR.Test setup:
You can find some scripts to create a cluster with a lot of load here: https://github.com/jerolimov/openshift/tree/master/loadtest
Browser conformance: