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

[data grid] Performance: separate row cleanup #12023

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ad9e8bf
perf: remove cellContent
romgrk Feb 9, 2024
f7c1fee
perf: remove emotion wrapper
romgrk Feb 9, 2024
c5e6102
fix: resizing
romgrk Feb 9, 2024
012266d
fix: resize styles
romgrk Feb 9, 2024
fbb071e
lint
romgrk Feb 9, 2024
64cba14
docs: update
romgrk Feb 9, 2024
7dabf06
fix: alignment
romgrk Feb 9, 2024
dd65a9a
test: fix reorder
romgrk Feb 9, 2024
bb5c5f6
fix: rating style
romgrk Feb 9, 2024
7f6ee6a
fix: styles
romgrk Feb 10, 2024
6331a57
fix: style invalidation
romgrk Feb 10, 2024
c7a7dd8
lint
romgrk Feb 10, 2024
3eff377
lint
romgrk Feb 10, 2024
c5dc461
fix: pinned border
romgrk Feb 10, 2024
da2c2f1
fix: empty columns bug
romgrk Feb 10, 2024
f1a819f
fix: empty rows bug
romgrk Feb 10, 2024
a821c66
fix: layout ownerState test failing
romgrk Feb 10, 2024
380995c
test: fix offset top
romgrk Feb 10, 2024
2b3c933
docs: api
romgrk Feb 10, 2024
1a03542
lint
romgrk Feb 10, 2024
490d429
fix: styles
romgrk Feb 10, 2024
959f038
docs: api
romgrk Feb 10, 2024
aed570f
lint
romgrk Feb 10, 2024
169c302
fix: style
romgrk Feb 10, 2024
c90621c
Merge branches 'perf-dom-changes' and 'perf-style-invalidation' into my
romgrk Feb 10, 2024
6f60b7f
refactor: remove render zone, use position:absolute
romgrk Feb 10, 2024
9510b61
draft: append-only scroll
romgrk Feb 10, 2024
2b41c33
perf: remove offsets.top, keep offsetLeft
romgrk Feb 11, 2024
69e22fe
draft: benchmark
romgrk Feb 11, 2024
f338d47
lint
romgrk Feb 11, 2024
4a2a643
Merge branch 'perf-style-invalidation' into perf-scrolling-complex
romgrk Feb 11, 2024
e529580
perf: avoid colSpan computations when not needed
romgrk Feb 11, 2024
d2e3313
refactor: focus cell handling
romgrk Feb 12, 2024
9c8333e
feat: virtualization cleanup
romgrk Feb 12, 2024
551fbda
lint
romgrk Feb 12, 2024
db15000
lint
romgrk Feb 13, 2024
f367e0a
Merge branch 'perf-dom-changes' into perf-scrolling-complex
romgrk Feb 13, 2024
c4b35ab
Merge branch 'next' into perf-scrolling-complex
romgrk Feb 23, 2024
167322e
lint
romgrk Feb 23, 2024
c71ffcc
fix: missed offsets
romgrk Feb 23, 2024
f82c480
Merge branch 'next' into perf-scrolling-complex
romgrk Feb 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/pages/x/api/data-grid/data-grid-premium.json
Original file line number Diff line number Diff line change
Expand Up @@ -1821,6 +1821,30 @@
"description": "Styles applied to the horizontal scrollbar.",
"isGlobal": false
},
{
"key": "scrollbarFiller",
"className": "MuiDataGridPremium-scrollbarFiller",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--borderTop",
"className": "MuiDataGridPremium-scrollbarFiller--borderTop",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--header",
"className": "MuiDataGridPremium-scrollbarFiller--header",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--pinnedRight",
"className": "MuiDataGridPremium-scrollbarFiller--pinnedRight",
"description": "",
"isGlobal": false
},
{
"key": "selectedRowCount",
"className": "MuiDataGridPremium-selectedRowCount",
Expand Down
24 changes: 24 additions & 0 deletions docs/pages/x/api/data-grid/data-grid-pro.json
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,30 @@
"description": "Styles applied to the horizontal scrollbar.",
"isGlobal": false
},
{
"key": "scrollbarFiller",
"className": "MuiDataGridPro-scrollbarFiller",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--borderTop",
"className": "MuiDataGridPro-scrollbarFiller--borderTop",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--header",
"className": "MuiDataGridPro-scrollbarFiller--header",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--pinnedRight",
"className": "MuiDataGridPro-scrollbarFiller--pinnedRight",
"description": "",
"isGlobal": false
},
{
"key": "selectedRowCount",
"className": "MuiDataGridPro-selectedRowCount",
Expand Down
24 changes: 24 additions & 0 deletions docs/pages/x/api/data-grid/data-grid.json
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,30 @@
"description": "Styles applied to the horizontal scrollbar.",
"isGlobal": false
},
{
"key": "scrollbarFiller",
"className": "MuiDataGrid-scrollbarFiller",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--borderTop",
"className": "MuiDataGrid-scrollbarFiller--borderTop",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--header",
"className": "MuiDataGrid-scrollbarFiller--header",
"description": "",
"isGlobal": false
},
{
"key": "scrollbarFiller--pinnedRight",
"className": "MuiDataGrid-scrollbarFiller--pinnedRight",
"description": "",
"isGlobal": false
},
{
"key": "selectedRowCount",
"className": "MuiDataGrid-selectedRowCount",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,10 @@
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the horizontal scrollbar"
},
"scrollbarFiller": { "description": "" },
"scrollbarFiller--borderTop": { "description": "" },
"scrollbarFiller--header": { "description": "" },
"scrollbarFiller--pinnedRight": { "description": "" },
"selectedRowCount": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the footer selected row count element"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,10 @@
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the horizontal scrollbar"
},
"scrollbarFiller": { "description": "" },
"scrollbarFiller--borderTop": { "description": "" },
"scrollbarFiller--header": { "description": "" },
"scrollbarFiller--pinnedRight": { "description": "" },
"selectedRowCount": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the footer selected row count element"
Expand Down
4 changes: 4 additions & 0 deletions docs/translations/api-docs/data-grid/data-grid/data-grid.json
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,10 @@
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the horizontal scrollbar"
},
"scrollbarFiller": { "description": "" },
"scrollbarFiller--borderTop": { "description": "" },
"scrollbarFiller--header": { "description": "" },
"scrollbarFiller--pinnedRight": { "description": "" },
"selectedRowCount": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the footer selected row count element"
Expand Down
15 changes: 10 additions & 5 deletions packages/x-data-grid-pro/src/components/GridDetailPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,32 @@ const DetailPanel = styled('div', {
name: 'MuiDataGrid',
slot: 'DetailPanel',
overridesResolver: (props, styles) => styles.detailPanel,
})<{ ownerState: OwnerState }>(({ theme }) => ({
})<{ ownerState: OwnerState }>({
position: 'relative',
width:
'calc(var(--DataGrid-rowWidth) - var(--DataGrid-hasScrollY) * var(--DataGrid-scrollbarSize))',
backgroundColor: (theme.vars || theme).palette.background.default,
backgroundColor: 'var(--DataGrid-containerBackground)',
overflow: 'auto',
}));
});

interface GridDetailPanelProps
extends Pick<React.HTMLAttributes<HTMLDivElement>, 'className' | 'children'> {
/**
* The row ID that this panel belongs to.
*/
rowId: GridRowId;
/**
* The top position.
*/
top: number;
/**
* The panel height.
*/
height: number | 'auto';
}

function GridDetailPanel(props: GridDetailPanelProps) {
const { rowId, height, className, children } = props;
const { rowId, height, top, className, children } = props;
const apiRef = useGridPrivateApiContext();
const ref = React.useRef<HTMLDivElement | null>(null);
const rootProps = useGridRootProps();
Expand Down Expand Up @@ -65,7 +70,7 @@ function GridDetailPanel(props: GridDetailPanelProps) {
ref={ref}
ownerState={ownerState}
role="presentation"
style={{ height }}
style={{ top, height }}
className={className}
>
{children}
Expand Down
12 changes: 10 additions & 2 deletions packages/x-data-grid-pro/src/components/GridDetailPanels.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import * as React from 'react';
import { unstable_composeClasses as composeClasses } from '@mui/utils';
import { getDataGridUtilityClass, useGridSelector, GridRowId } from '@mui/x-data-grid';
import {
getDataGridUtilityClass,
gridRowsMetaSelector,
useGridSelector,
GridRowId,
} from '@mui/x-data-grid';
import { GridDetailPanelsProps, EMPTY_DETAIL_PANELS } from '@mui/x-data-grid/internals';
import { useGridPrivateApiContext } from '../hooks/utils/useGridPrivateApiContext';
import { useGridRootProps } from '../hooks/utils/useGridRootProps';
Expand Down Expand Up @@ -31,6 +36,7 @@ function GridDetailPanelsImpl({ virtualScroller }: GridDetailPanelsProps) {
const classes = useUtilityClasses();
const { setPanels } = virtualScroller;

const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector);
const expandedRowIds = useGridSelector(apiRef, gridDetailPanelExpandedRowIdsSelector);
const detailPanelsContent = useGridSelector(
apiRef,
Expand All @@ -55,19 +61,21 @@ function GridDetailPanelsImpl({ virtualScroller }: GridDetailPanelsProps) {

const hasAutoHeight = apiRef.current.detailPanelHasAutoHeight(rowId);
const height = hasAutoHeight ? 'auto' : detailPanelsHeights[rowId];
const top = rowsMeta.positions[rowIndex] + apiRef.current.unstable_getRowHeight(rowId);

return (
<GridDetailPanel
key={`panel-${rowId}`}
rowId={rowId}
top={top}
height={height}
className={classes.detailPanel}
>
{content}
</GridDetailPanel>
);
},
[apiRef, classes.detailPanel, detailPanelsHeights, detailPanelsContent],
[apiRef, classes.detailPanel, rowsMeta, detailPanelsHeights, detailPanelsContent],
);

React.useEffect(() => {
Expand Down
15 changes: 14 additions & 1 deletion packages/x-data-grid-pro/src/components/GridPinnedRows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getDataGridUtilityClass, gridClasses, useGridSelector } from '@mui/x-da
import {
GridPinnedRowsProps,
gridPinnedRowsSelector,
gridRenderContextSelector,
useGridPrivateApiContext,
} from '@mui/x-data-grid/internals';

Expand All @@ -19,10 +20,22 @@ export function GridPinnedRows({ position, virtualScroller, ...other }: GridPinn
const classes = useUtilityClasses();
const apiRef = useGridPrivateApiContext();

const renderContext = useGridSelector(apiRef, gridRenderContextSelector);
const pinnedRowsData = useGridSelector(apiRef, gridPinnedRowsSelector);
const rows = pinnedRowsData[position];

const pinnedRows = virtualScroller.getRows({
position,
rows: pinnedRowsData[position],
rows,
renderContext: React.useMemo(
() => ({
firstRowIndex: 0,
lastRowIndex: rows.length,
firstColumnIndex: renderContext.firstColumnIndex,
lastColumnIndex: renderContext.lastColumnIndex,
}),
[rows, renderContext.firstColumnIndex, renderContext.lastColumnIndex],
),
});

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,20 +365,20 @@ describe('<DataGridPro /> - Column pinning', () => {
it('should change the side when called on a pinned column', () => {
render(<TestCase />);

const renderZone = $(`.${gridClasses.virtualScrollerRenderZone}`)!;
const content = $(`.${gridClasses.virtualScrollerContent}`)!;

expect($(renderZone, '[data-field="currencyPair"]')!.className).not.to.include('pinned');
expect($(content, '[data-field="currencyPair"]')!.className).not.to.include('pinned');

act(() => apiRef.current.pinColumn('currencyPair', GridPinnedColumnPosition.LEFT));
expect(
$(renderZone, `.${gridClasses['cell--pinnedLeft']}[data-field="currencyPair"]`),
$(content, `.${gridClasses['cell--pinnedLeft']}[data-field="currencyPair"]`),
).not.to.equal(null);
expect($(renderZone, '[data-field="currencyPair"]')!.className).to.include('pinned');
expect($(content, '[data-field="currencyPair"]')!.className).to.include('pinned');

act(() => apiRef.current.pinColumn('currencyPair', GridPinnedColumnPosition.RIGHT));
expect($$(renderZone, `.${gridClasses['cell--pinnedLeft']}`).length).to.equal(0);
expect($$(content, `.${gridClasses['cell--pinnedLeft']}`).length).to.equal(0);
expect(
$(renderZone, `.${gridClasses['cell--pinnedRight']}[data-field="currencyPair"]`),
$(content, `.${gridClasses['cell--pinnedRight']}[data-field="currencyPair"]`),
).not.to.equal(null);
});

Expand All @@ -398,8 +398,8 @@ describe('<DataGridPro /> - Column pinning', () => {
expect($$(`.${gridClasses['cell--pinnedLeft']}`).length).not.to.equal(0);
act(() => apiRef.current.unpinColumn('currencyPair'));
expect($$(`.${gridClasses['cell--pinnedLeft']}`).length).to.equal(0);
const renderZone = $(`.${gridClasses.virtualScrollerRenderZone}`)!;
expect(renderZone.querySelector('[data-field="currencyPair"]')).not.to.equal(null);
const content = $(`.${gridClasses.virtualScrollerContent}`)!;
expect(content.querySelector('[data-field="currencyPair"]')).not.to.equal(null);
});
});

Expand Down
24 changes: 11 additions & 13 deletions packages/x-data-grid-pro/src/tests/rows.DataGridPro.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -447,17 +447,15 @@ describe('<DataGridPro /> - Rows', () => {
);

const virtualScroller = grid('virtualScroller')!;
const renderingZone = grid('virtualScrollerRenderZone')!;
const content = grid('virtualScrollerContent')!.querySelectorAll('[role="row"]');
virtualScroller.scrollTop = 10e6; // scroll to the bottom
act(() => virtualScroller.dispatchEvent(new Event('scroll')));

const lastCell = $$('[role="row"]:last-child [role="gridcell"]')[0];
expect(lastCell).to.have.text('995');
expect(renderingZone.children.length).to.equal(
Math.floor((height - 1) / rowHeight) + rowBuffer,
); // Subtracting 1 is needed because of the column header borders
expect(content.length).to.equal(Math.floor((height - 1) / rowHeight) + rowBuffer); // Subtracting 1 is needed because of the column header borders
const scrollbarSize = apiRef.current.state.dimensions.scrollbarSize;
const distanceToFirstRow = (nbRows - renderingZone.children.length) * rowHeight;
const distanceToFirstRow = (nbRows - content.length) * rowHeight;
expect(gridOffsetTop()).to.equal(distanceToFirstRow);
expect(virtualScroller.scrollHeight - scrollbarSize).to.equal(nbRows * rowHeight);
});
Expand Down Expand Up @@ -503,12 +501,12 @@ describe('<DataGridPro /> - Rows', () => {
<TestCaseVirtualization rowHeight={rowHeight} rowBuffer={0} rowThreshold={rowThreshold} />,
);
const virtualScroller = document.querySelector('.MuiDataGrid-virtualScroller')!;
const renderingZone = document.querySelector('.MuiDataGrid-virtualScrollerRenderZone')!;
let firstRow = renderingZone.firstChild;
const content = document.querySelector('.MuiDataGrid-virtualScrollerContent')!;
let firstRow = content.firstChild;
expect(firstRow).to.have.attr('data-rowindex', '0');
virtualScroller.scrollTop = rowThreshold * rowHeight;
act(() => virtualScroller.dispatchEvent(new Event('scroll')));
firstRow = renderingZone.firstChild;
firstRow = content.firstChild;
expect(firstRow).to.have.attr('data-rowindex', '3');
});

Expand All @@ -519,13 +517,13 @@ describe('<DataGridPro /> - Rows', () => {
<TestCaseVirtualization nbRows={1} columnBuffer={0} columnThreshold={columnThreshold} />,
);
const virtualScroller = grid('virtualScroller')!;
const renderingZone = grid('virtualScrollerRenderZone')!;
const firstRow = $(renderingZone, '[role="row"]:first-child')!;
const content = grid('virtualScrollerContent')!;
const firstRow = $(content, '[role="row"]:first-child')!;
let firstColumn = $$(firstRow, '[role="gridcell"]')[0];
expect(firstColumn).to.have.attr('data-colindex', '0');
virtualScroller.scrollLeft = columnThreshold * columnWidth;
act(() => virtualScroller.dispatchEvent(new Event('scroll')));
firstColumn = $(renderingZone, '[role="row"] > [role="gridcell"]')!;
firstColumn = $(content, '[role="row"] > [role="gridcell"]')!;
expect(firstColumn).to.have.attr('data-colindex', '3');
});

Expand Down Expand Up @@ -570,7 +568,7 @@ describe('<DataGridPro /> - Rows', () => {
expect(lastCell).to.have.text('99');
expect(virtualScroller.scrollTop).to.equal(0);
expect(virtualScroller.scrollHeight).to.equal(virtualScroller.clientHeight);
expect(grid('virtualScrollerRenderZone')!.children).to.have.length(4);
expect(grid('virtualScrollerContent')!.children).to.have.length(4);
});

it('should paginate small dataset in auto page-size #1492', () => {
Expand All @@ -586,7 +584,7 @@ describe('<DataGridPro /> - Rows', () => {

expect(virtualScroller.scrollTop).to.equal(0);
expect(virtualScroller.scrollHeight).to.equal(virtualScroller.clientHeight);
expect(grid('virtualScrollerRenderZone')!.children).to.have.length(7);
expect(grid('virtualScrollerContent')!.children).to.have.length(7);
});
});

Expand Down
Loading
Loading