Skip to content
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

perf(sqllab): Rendering perf improvement using immutable state #20877

Conversation

justinpark
Copy link
Member

@justinpark justinpark commented Jul 26, 2022

SUMMARY

The main rendering in SqlLab is managed by the queryEditors state from redux(state machine).
Each queryEditor state has been updated whenever an editor configuration has updated.

Since most components observes entire queryEditor state not specific attributes, any queryEditor updates trigger multiple repainting even if no visual changes impacted.

For example, when a user types any single character in the ace(sql) editor, it triggers the update for selectedText value in the active queryEditor state. This single change will trigger the following components repainted (though this change won't impact the left and bottom panels at all)

Screen_Shot_2022-07-26_at_3_10_16_PM

This unrelated repainting job causes the performance delay especially when table list is humongous.

Screen_Shot_2022-07-26_at_3_24_05_PM

The delay can be found in the following performance analysis due to the unnecessary repainting/redux post processes.

Screen_Shot_2022-07-25_at_4_08_35_PM

This commit fixes this performance issue by optimizing observers in each component to subscribe only related items.
To minimize the regression issue from existing persistence state, this commit keeps the existing queryEditors state but make it immutable during the tab is active and only updates when the tab is switched. It introduces unsavedQueryEditor state which stores all these active changes.

With this update, the page rendering performance improved 3.5x faster(from 4.5s to 1.3s) and verified all unnecessary tasks cleaned.

Screen Shot 2022-07-25 at 4 18 45 PM

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Before (4.5s):

slow-sqllab.mov

After (1.3s):

Screen_Shot_2022-07-25_at_4_19_14_PM

TESTING INSTRUCTIONS

  1. Go to SqlLab
  2. Choose a database and a schema that includes a large set of table list
  3. Open chrome console > Performance tab
  4. Select Caption settings on right menu
  5. Change CPU throttling to 6x slowdown
  6. type a string in the sql editor and then watch the refresh icon on the left panel (it will blink during repainting)

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@codecov
Copy link

codecov bot commented Jul 27, 2022

Codecov Report

Merging #20877 (dfb30fc) into master (8005b7f) will increase coverage by 0.07%.
The diff coverage is 64.66%.

@@            Coverage Diff             @@
##           master   #20877      +/-   ##
==========================================
+ Coverage   66.27%   66.34%   +0.07%     
==========================================
  Files        1770     1772       +2     
  Lines       67543    67570      +27     
  Branches     7185     7187       +2     
==========================================
+ Hits        44764    44831      +67     
+ Misses      20940    20893      -47     
- Partials     1839     1846       +7     
Flag Coverage Δ
javascript 52.15% <64.66%> (+0.15%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
superset-frontend/src/SqlLab/App.jsx 0.00% <0.00%> (ø)
superset-frontend/src/SqlLab/types.ts 57.14% <ø> (ø)
...uperset-frontend/src/components/Dropdown/index.tsx 100.00% <ø> (ø)
...et-frontend/src/components/TableSelector/index.tsx 78.26% <ø> (+2.17%) ⬆️
superset-frontend/src/SqlLab/actions/sqlLab.js 61.37% <41.66%> (+1.26%) ⬆️
superset-frontend/src/SqlLab/reducers/sqlLab.js 34.85% <43.75%> (+1.52%) ⬆️
...frontend/src/SqlLab/components/SqlEditor/index.jsx 50.58% <47.05%> (-1.05%) ⬇️
...c/SqlLab/components/TemplateParamsEditor/index.tsx 82.35% <50.00%> (+7.35%) ⬆️
...et-frontend/src/SqlLab/reducers/getInitialState.js 46.66% <50.00%> (+0.23%) ⬆️
...d/src/SqlLab/components/SqlEditorLeftBar/index.tsx 50.00% <66.66%> (+0.79%) ⬆️
... and 17 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@github-actions
Copy link
Contributor

@justinpark Ephemeral environment creation is currently limited to committers.

@ktmud
Copy link
Member

ktmud commented Jul 28, 2022

/testenv up

@ktmud ktmud requested review from ktmud and etr2460 July 28, 2022 00:21
@ktmud
Copy link
Member

ktmud commented Jul 28, 2022

/testenv up

@github-actions
Copy link
Contributor

@ktmud Ephemeral environment spinning up at http://34.220.154.64:8080. Credentials are admin/admin. Please allow several minutes for bootstrapping and startup.

@justinpark justinpark force-pushed the perf--sqllab-rendering-delay-improvement branch from 4ca0186 to e4d3876 Compare August 2, 2022 18:24
@ktmud
Copy link
Member

ktmud commented Aug 2, 2022

/testenv up

@github-actions
Copy link
Contributor

github-actions bot commented Aug 2, 2022

@ktmud Ephemeral environment spinning up at http://34.217.34.22:8080. Credentials are admin/admin. Please allow several minutes for bootstrapping and startup.

Copy link
Member

@ktmud ktmud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the SQL Lab code is a mystery to me. But I've tested this quite extensively locally and did see significant improvements in typing performance in SQL editor. I trust the test cases to make sure the majority of the happy paths are still happy.

sql: 'SELECT *\nFROM\nWHERE',
name: 'Untitled Query 1',
schemaOptions: [{ value: 'main', label: 'main', name: 'main' }],
schemaOptions: [{ value: 'main', label: 'main', title: 'main' }],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we changing this to title

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hughhhh This change(title -> name) accidentally happened here while the PR made the change for queryEditor title to name.

cc: @lyndsiWilliams

I reverted this change to pass the type role since I'm following this type definition

and it's also allocated as title here:

const options = json.result.map((s: string) => ({
value: s,
label: s,
title: s,
}));

@justinpark justinpark force-pushed the perf--sqllab-rendering-delay-improvement branch from a4dcfe2 to f282688 Compare August 5, 2022 03:37
@hughhhh
Copy link
Member

hughhhh commented Aug 5, 2022

/testenv up

@@ -178,7 +193,9 @@ export default function SaveQuery({
onHide={() => setShowSaveDatasetModal(false)}
buttonTextOnSave={t('Save & Explore')}
buttonTextOnOverwrite={t('Overwrite & Explore')}
datasource={getDatasourceAsSaveableDataset(query)}
datasource={
getDatasourceAsSaveableDataset(query) as any as ISaveableDatasource
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are casting as any and then ISaveableDatasource here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh it needed this custom type cast but no longer needed. I reverted this change.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 5, 2022

@hughhhh Ephemeral environment spinning up at http://34.217.110.42:8080. Credentials are admin/admin. Please allow several minutes for bootstrapping and startup.

@justinpark justinpark force-pushed the perf--sqllab-rendering-delay-improvement branch from f282688 to 7417f72 Compare August 5, 2022 17:50
Copy link
Member

@eschutho eschutho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nits, but one could pose a runtime error.

@@ -91,6 +94,12 @@ const sqlLabPersistStateConfig = {
const result = {
...initialState,
...persistedState,
sqlLab: {
...(persistedState && persistedState.sqlLab),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if persistedState is null or undefined, this will error when you try to spread it. I'd recommend a default of an empty object.. maybe something like

Suggested change
...(persistedState && persistedState.sqlLab),
...(persistedState?.sqlLab || {}),

@@ -620,6 +677,7 @@ export function switchQueryEditor(queryEditor, displayLimit) {
return function (dispatch) {
if (
isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE) &&
queryEditor &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe use optional chaining here as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good

const qe = getUpToDateQuery(getState(), queryEditor, queryEditor.id);
const query = {
dbId: qe.dbId,
sql: qe.selectedText ? qe.selectedText : qe.sql,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
sql: qe.selectedText ? qe.selectedText : qe.sql,
sql: qe.selectedText || qe.sql,

Copy link
Member

@jinghua-qa jinghua-qa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cypress change LGTM


return (
<TabTitleWrapper>
<Dropdown
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this was expected, but can we bring back the trigger={['click']} on this component, too?

- keep queryEditors immutable during active state
- add unsavedQueryEditor to store all active changes
- refactor each component to subscribe the related unsaved editor state only
@justinpark justinpark force-pushed the perf--sqllab-rendering-delay-improvement branch from 0b1fa32 to dfb30fc Compare August 17, 2022 16:19
@justinpark
Copy link
Member Author

@eschutho I updated the commit. Can you review the update? thanks!

@EugeneTorap
Copy link
Contributor

@eschutho @michael-s-molina Can we merge the PR?

@michael-s-molina michael-s-molina merged commit f77b910 into apache:master Aug 23, 2022
@github-actions
Copy link
Contributor

Ephemeral environment shutdown and build artifacts deleted.

john-bodley pushed a commit to airbnb/superset-fork that referenced this pull request Aug 24, 2022
…e#20877)

* perf(sqllab): Rendering perf improvement using immutable state

- keep queryEditors immutable during active state
- add unsavedQueryEditor to store all active changes
- refactor each component to subscribe the related unsaved editor state only

* revert ISaveableDatasource type cast

* missing trigger prop

* a default of an empty object and optional operator

(cherry picked from commit ddb5fcdc0cb597c2fd947d39a05055c2949c29a7)
hughhhh added a commit that referenced this pull request Sep 1, 2022
sadpandajoe added a commit to preset-io/superset that referenced this pull request Sep 2, 2022
justinpark added a commit to airbnb/superset-fork that referenced this pull request Sep 16, 2022
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 2.1.0 and removed 🚢 2.1.3 labels Mar 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels size/XXL 🚢 2.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants