Drag & drop (tabbar, panels), data grid and others are slow when many DOM nodes are present
krassowski opened this issue · 3 comments
Description
Drag.overrideCursor
sets a cursor and a class on the document.body
:
lumino/packages/dragdrop/src/index.ts
Lines 762 to 812 in a1df432
It is used by a number of places:
- in data grid (DataGrid):
- by BasicMouseHandler in on mouse down handler
- by scrollbars when clicking on them (on mouse down event handler)
- for drag-and-drop which is used in JupyterLab File Browser and when moving Cells in Notebooks
- for drag-and-drop implementation in lumino widgets: dockpanel, splitpanel and tabbar
In Chromium, there is a bug: Issue 664066: Change global cursor without recalculating style which causes exactly this action to recalculate styles of every single element in the document.
A freeze is also observable in Firefox, however there the Style Recalculation is 4 times faster (~250ms vs ~1.7 seconds).
Reproduce (in JupyterLab)
- Download
gh-9757-reproducer.ipynb
- Run all cells
- Either:
- a) Open a CSV file with DataGrid, try clicking on it the body or the header
- b) Move a tab to another/new docking area
- See the UI freeze for 1.5 seconds on mouse down and then freeze again on mouse up
a) DataGrid click
Clicking on the data grid froze the menu for 3 seconds, with both actions attributable to Drag.overrideCursor
call.
b) Moving tabs
Moving a tab to a new dock panel took me 10 seconds. 7 seconds were 4 Recalculate Style actions, one of them (1.7 seconds) can certainly be attributed to this problem and is highlighted on the screenshot below. The remaining issues are layout trashing when creating the blue overlay, possibly avoidable but a separate issue.
Expected behavior
No UI freezes.
Context
- Browser and version: Chrome 107
- JupyterLab version: 3.5.0
Thanks for tracking this down. What solution do we have for this? Shadow nodes?
Shadow DOM should help but we need to test it to be sure (its on my agenda). Since quite a few of the problematic Style Recalculation paths are also issues in Chromium (I hesitate to call them bugs, maybe buglets - they are non optimized code paths in algorithm which should be, and for the most part is, heavily optimized), there is no guarantee theses issues would go away if we just add a shadow DOM boundary.
As for this specific issue I have some things to try. The rough idea is to set the cursor on the closest element which needs to be modified. If all fails we could just add a cursor-like div serving as a drag reminder (kind of like we have the semi-transparent node already when moving cells/file browser items).
We could also start using native https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable which lets browser change the cursor as it wishes, but this may be a larger refactor.