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

[Lens] Optimize async chunks #211921

Merged
merged 27 commits into from
Mar 28, 2025
Merged

[Lens] Optimize async chunks #211921

merged 27 commits into from
Mar 28, 2025

Conversation

dej611
Copy link
Contributor

@dej611 dej611 commented Feb 20, 2025

Summary

While documenting some Lens architecture I've noticed how chunks are organized in Lens, so I've taken a quick spin to reduce the amount of requests to load a dashboard panel and more in general the number of async chunks produced by webpack.

This PR aims to do 2 things:

  • optimize the number of chunks generated by webpack
  • optimize the number of requests done to load a Lens embedable panel
  • optimize any await flow to do **other things ™️ ** while in idle to load

Final results

Reduce the number of chunks

The final number of chunks got reduced from 24 to 15. The bundle size has remained almost the same.

Before After
Screenshot 2025-03-10 at 12 53 21 Screenshot 2025-03-10 at 12 51 53

There's still some improvement margin here, but the changes mainly includes he followings:

  • the embeddable is now bundled together with the async_services bundle
    • as both are required to render the panel in a dashboard, this change should speed up a bit the dashboard use case vs the Lens editor one
  • Expression implementations has been deferred into their separate bundles
    • this should reduce a bit the initial plugin.js bundle by few kb
    • most of the times the bundled expressions are used together, so it makes sense to bundle those 3/4 together rather than have 4 tiny bundles to async load and prevent waterfall async import calls which led to poor performance
  • Defer a component in the @kbn/unified-field-list component
    • this was making load some edit component within the async_services bundle even in dashboard.
    • because this is a component only required in Lens editor, this has been deferred
  • Async register actions as recommended by @nreese

Reduce the number of requests

The final number of chunks requested to load a lens panel on a dashboard went from 12 to 4.
The overall bundle size has remained almost the same, but the distributions of weights have slightly changed.
Surprisingly there's 1 MB which is gone somewhere, but that doesn't seem to have an actual impact on the overall loading experience yet.

Before After
Screenshot 2025-03-10 at 12 58 08 Screenshot 2025-03-10 at 12 58 32

Optimize any await call

Well, this is hard to test. So I have no direct proof at the moment. 🤷

cc @thomasneirynck

@dej611 dej611 added Team:Visualizations Visualization editors, elastic-charts and infrastructure release_note:skip Skip the PR/issue when compiling release notes Feature:Lens labels Feb 20, 2025
@dej611
Copy link
Contributor Author

dej611 commented Feb 20, 2025

/ci

@dej611
Copy link
Contributor Author

dej611 commented Feb 21, 2025

/ci

@dej611
Copy link
Contributor Author

dej611 commented Feb 21, 2025

/ci

@dej611
Copy link
Contributor Author

dej611 commented Feb 21, 2025

/ci

@dej611
Copy link
Contributor Author

dej611 commented Mar 3, 2025

/ci

@dej611 dej611 marked this pull request as ready for review March 12, 2025 14:37
@dej611 dej611 requested review from a team as code owners March 12, 2025 14:37
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-visualizations (Team:Visualizations)

@dej611 dej611 self-assigned this Mar 12, 2025
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
lens 1527 1528 +1

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/unified-field-list 288 289 +1

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
discover 960.5KB 961.0KB +554.0B
lens 1.5MB 1.5MB -5.5KB
securitySolution 8.9MB 8.9MB +826.0B
slo 921.8KB 922.6KB +785.0B
total -3.4KB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
lens 58.8KB 57.4KB -1.4KB
Unknown metric groups

async chunk count

id before after diff
discover 33 34 +1
lens 27 16 -11
securitySolution 128 129 +1
slo 32 33 +1
total -8

References to deprecated APIs

id before after diff
lens 90 85 -5

History

cc @dej611

@dej611 dej611 added the backport:skip This commit does not require backporting label Mar 14, 2025
Copy link
Member

@markov00 markov00 left a comment

Choose a reason for hiding this comment

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

All good here, the room for improvement exist, but this is a great step toward that.
Thanks

Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

I just have a couple of questions about the Data Discovery changes.

Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

I don't think you need my review anymore with the latest changes, but LGTM nonetheless!

@dej611 dej611 requested review from markov00 and davismcphee March 25, 2025 08:37
@dej611
Copy link
Contributor Author

dej611 commented Mar 25, 2025

Sorry folks for the new ping. After some changes I've settled with this setup which makes the async bundle size go a little bit higher, but with fewer async chunks to load.
Now 9 chunks out of 18 are from the unified-field-list package (so not loaded when inline editing) and the remaining half are Lens feature specific.

Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

Latest Data Discovery changes to export GenericFieldItemButtonType make sense to me now that I understand the challenges with generic components and lazy loading 👍

@dej611 dej611 enabled auto-merge (squash) March 27, 2025 14:57
@dej611 dej611 merged commit db98203 into elastic:main Mar 28, 2025
10 checks passed
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
lens 1359 1364 +5

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/unified-field-list 288 290 +2

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
lens 1.4MB 1.4MB +24.8KB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
lens 58.7KB 57.9KB -789.0B
Unknown metric groups

API count

id before after diff
@kbn/unified-field-list 317 319 +2

async chunk count

id before after diff
lens 27 18 -9

References to deprecated APIs

id before after diff
lens 88 83 -5

History

cc @dej611

@thomasneirynck
Copy link
Contributor

This PR, and another Lens-focussed one (#215792), have shown a big improvement in how long it takes to load a dashboard.

Both of them together have caused the median dashboard_duration-time (ie. time after the spinner until all data is loaded on screen) to drop 0.5 second (3.9s->3.4s) on our benchmarks.

Comparing before they merged to after they merged:
image
image

cqliu1 pushed a commit to cqliu1/kibana that referenced this pull request Mar 31, 2025
## Summary

While documenting some Lens architecture I've noticed how chunks are
organized in Lens, so I've taken a quick spin to reduce the amount of
requests to load a dashboard panel and more in general the number of
async chunks produced by webpack.

This PR aims to do 2 things:
* optimize the number of chunks generated by webpack
* optimize the number of requests done to load a Lens embedable panel
* optimize any `await` flow to do **other things ™️ ** while in idle to
load

### Final results

#### Reduce the number of chunks

The final number of chunks got reduced from 24 to 15. The bundle size
has remained almost the same.

| Before  | After |
| ------------- | ------------- |
| <img width="1443" alt="Screenshot 2025-03-10 at 12 53 21"
src="https://github.com/user-attachments/assets/65030955-7b7c-493c-9559-fbb9ef9089d4"
/> | <img width="1101" alt="Screenshot 2025-03-10 at 12 51 53"
src="https://github.com/user-attachments/assets/99b9b78d-931a-40ed-bda6-820584c1337e"
/> |

There's still some improvement margin here, but the changes mainly
includes he followings:
* the embeddable is now bundled together with the `async_services`
bundle
* as both are required to render the panel in a dashboard, this change
should speed up a bit the dashboard use case vs the Lens editor one
* Expression implementations has been deferred into their separate
bundles
  *  this should reduce a bit the initial `plugin.js` bundle by few kb
* most of the times the bundled expressions are used together, so it
makes sense to bundle those 3/4 together rather than have 4 tiny bundles
to async load and prevent waterfall `async import` calls which led to
poor performance
* Defer a component in the `@kbn/unified-field-list` component
* this was making load some edit component within the `async_services`
bundle even in dashboard.
* because this is a component only required in Lens editor, this has
been deferred
* Async register actions as recommended by @nreese  

#### Reduce the number of requests

The final number of chunks requested to load a lens panel on a dashboard
went from 12 to 4.
The overall bundle size has remained almost the same, but the
distributions of weights have slightly changed.
Surprisingly there's 1 MB which is gone somewhere, but that doesn't seem
to have an actual impact on the overall loading experience yet.

| Before  | After |
| ------------- | ------------- |
| <img width="1445" alt="Screenshot 2025-03-10 at 12 58 08"
src="https://github.com/user-attachments/assets/faab091b-305d-43ad-8be2-2f3bb83913a3"
/> | <img width="1110" alt="Screenshot 2025-03-10 at 12 58 32"
src="https://github.com/user-attachments/assets/f88ac9f5-80a6-42d3-8e3b-3013df05cb8b"
/> |

#### Optimize any `await` call

Well, this is hard to test. So I have no direct proof at the moment. 🤷 

cc @thomasneirynck

---------

Co-authored-by: kibanamachine <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting ci:build-webpack-bundle-analyzer Feature:Lens release_note:skip Skip the PR/issue when compiling release notes Team:Visualizations Visualization editors, elastic-charts and infrastructure v9.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants