-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Dashboard Performance: Debounce loadWidgets #4724
Conversation
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 can't put my finger on it, but this feels wrong. I feel like we're adding complexity to the implementation that might be avoided with different architecture. Did you understand why debouncing helped here?
Also, it will be interesting to compare scripting time with v7. In one of the other PRs, you mentioned you tested with v7 -- was it using Netlify?
Yes, because currently the widgets loading triggers a dashboard state change, which makes React recheck all widgets for re-renders. That basically creates a quadratic rise on those recheck numbers when you add new widgets. Debouncing helps because it groups widget state changes, it does not seem ideal, but was the best I thought when having the DashboardPage managing widgets loading. If each Widget managed its own loading, it would solve the problem as well. I tried to come with solutions on this direction, but it ended up on even worse code as I'd need to access individual rendered widgets to request their loading. The different architecture that I thought of was, as I said above, having each widget to manage more their own state, and relieve the Dashboard from that. Just didn't continue on it because of such component communication issues. Is this the general lines of the different architecture you were thinking, or was it sth else?
I'm actually running tests locally with webpack-dev, but pointing backend to preview-backend. |
Re V7: here's its Netlify preview: https://deploy-preview-3674--redash-preview.netlify.com/ for easier comparisons in the future. Re. architecture:
|
👍 The advantage of running locally is to have access to the components and function names for debugging. But in that case I didn't need any of those anyway. I made a few more tests with #4734 with and without the debouncing (since the widgets are memoized, the pain of rerendering reduced considerably): Even witth that, the scripting time I got was 10s vs 16s (with vs without deboucing). When I open the Profiler to see what could be the reason to that: The screenshots show the result rendering for a loading widget state change, overall it's not that painful (takes ~20ms), but it scales up with the number of widgets. Most of those ~20ms are now coming from ReactGridLayout and its components (GridItems). That was a lot worse without memoized widgets, but I don't have a solid idea on how to reduce more the impact of those renderings, hence why I attempted to reduce the number of renders. |
RGL suggests to memoize the children. I'm not sure how easy it is given the current implementation. Another quick-win to consider is to stop passing around redash/client/app/components/dashboards/dashboard-widget/VisualizationWidget.jsx Lines 223 to 236 in 33131c1
If it helps avoid passing You can quickly test if this will help by passing Beyond this change which feels quick & easy, let's table this and see how the work you already did affects less busy dashboards. |
This was one of my first attempts (#4714 (comment)) 😅, it was actually resulting in more time. Eventually I realized that memoizing the children wouldn't be that relevant (and could indeed add time) as whenever one child element changed, that would trigger it to memoize all over again. Basically, their example is quite simple, ours hold quite a few variables.
I had considered and tested this one too, but the |
I propose this as an alternative to this change (of separate loadingWidget state). |
Any reason why you want to centralize it in the I changed it because I felt there was no reason to trigger an update for all |
BTW I tested here, none of those changes alone (remove dashboard attr or separating the loadingWidgets state) actually help on any significant time 😅. In the context of this PR the |
Just to make sure I understand, in terms of performance If this is correct, then let's implement removing dashboard prop and memoize. It's a much simpler change. |
👍. I'll decouple #4734 from this PR |
@gabrieldutra , thanks for the PR! We've updated a lot of things now that we're Community-driven so - if you're still interested in getting this merged - would you mind rebasing off master to re-run the CI, as well as updating merge conflicts? We're trying to clean up our PR todo list, so if you're not interested, that's fine - we'll close the PR in about a week if we don't hear back. If you're interested in reopening the PR afterwards, we would also very much welcome that. |
Assume mostly automated message 😂. But I'll close this PR, it wasn't relevant back then, as I had merged a separate, but equivalent PR. And if it was today, there would be other alternatives I'd invest in for Dashboard frontend performance, which should be better. |
Indeed :) but I still wanted to be nice! |
What type of PR is this? (check all applicable)
Description
This PR is basically how I decided to incorporate this:
From my experiments this was the biggest individual improvement so far.
A few data from Chrome's performance Scripting Time for dashboard loading (you should see a noticeable improvement on dashboards manually too):
(The performance analysis were run with the same time for each dashboard to make sure results more reliable)
Related Tickets & Documents
#4714
Mobile & Desktop Screenshots/Recordings (if there are UI changes)
--