Skip to content

[DataGrid] Remove try/catch from GridCell due to performance issues #15616

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

Merged
merged 1 commit into from
Nov 26, 2024

Conversation

lauri865
Copy link
Contributor

@lauri865 lauri865 commented Nov 26, 2024

Fixes the performance issue described in #15615

We had about 150ms of scripting overhead when updating rows fast on typing via external filters (e.g. typing 5 letters, so 5 updates = 150ms in ~1s of user interaction). The larger the viewport, the larger the overhead. After this small change, all of it is gone, and it's mostly layout updates now.

@mui-bot
Copy link

mui-bot commented Nov 26, 2024

Deploy preview: https://deploy-preview-15616--material-ui-x.netlify.app/

Generated by 🚫 dangerJS against 24149ee

@michelengelen michelengelen added scope: data grid Changes or issues related to the data grid product type: enhancement This is not a bug, nor a new feature labels Nov 26, 2024
@cherniavskii cherniavskii changed the title Remove try/catch from GridCell due to performance issues [DataGrid] Remove try/catch from GridCell due to performance issues Nov 26, 2024
Copy link
Member

@cherniavskii cherniavskii left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@cherniavskii cherniavskii added needs cherry-pick The PR should be auto-cherry-picked to a version branch after merge—add a version label as target v7.x labels Nov 26, 2024
@cherniavskii cherniavskii merged commit 80a1e03 into mui:master Nov 26, 2024
27 of 28 checks passed
Copy link

Cherry-pick PRs will be created targeting branches: v7.x

@romgrk
Copy link
Contributor

romgrk commented Nov 26, 2024

Did you have a chance to benchmark the perf impact outside of updating rows? This PR introduces an additional .getRow() call, for a large dataset that's indexing into a large hashmap (rowsLookup[id]), it can be expensive.

Initially I kept the try/catch because I couldn't change the getCellParams API to return an empty value because it would be a breaking change, but now that we're preparing v8, we could get rid of the throw.

@lauri865
Copy link
Contributor Author

getRowParams calls getRow anyways – I doubt calling it twice in a row has any impact in any modern javascript engine. Pretty sure that try/catch would have a higher overhead than that even in a passing case.

@lauri865
Copy link
Contributor Author

lauri865 commented Nov 27, 2024

Just did a test in all major browsers – sequential reads are virtually for free. Even when accessing random keys on the same object, but certainly the same key. There's a tiny bit of overhead when .getRow() is called from different functions, but even that is encountered once per row at most (and probably less).

Even if a viewport would fit 100 rows, it probably wouldn't register, as only the first row during first access of the object would be the slowest.

Theoretically, of course better to return a null. But there are probably lower hanging fruits wrt performance, like fixing memoization, state propagation, and potentially virtualization.

While I have you here – have you guys benchmarked your approach to virtualization? Is it a conscious choice performance-wise to transform the whole RenderZone at once vs. individual rows? In theory, the browser may need to do more work painting when individual rows change – larger paintable area + potential containment issues. But haven't benchmarked myself, just a hunch. Most other virtualization implementations I've seen and used have settled on per-row transforms for whatever reason (incl. Ag-grid).

@romgrk
Copy link
Contributor

romgrk commented Nov 27, 2024

Pretty sure that try/catch would have a higher overhead than that even in a passing case.

IIRC, the relevant engines have removed try/catch deoptimizations, so it should be as efficient as normal code as long as it doesn't throw.

While I have you here – have you guys benchmarked your approach to virtualization?

I did extensive work on virtualization last year, when we reworked the layout to use CSS sticky headers. Back then I benchmarked heavily a few different approaches (and profiled ag-grid extensively to understand how they perform), including transform: translate() rows with contain: strict. In theory it could prevent some painting, in practice I couldn't find a substantial difference, though the exploration reached its time limit so maybe there's something to do, but I don't think it would be a huge improvement. Letting the browser layout rows also allows CSS open/close animations on the detail panels, which wouldn't work with transform positioning.

But there are probably lower hanging fruits wrt performance, like fixing memoization, state propagation, and potentially virtualization.

Yes, there seems to have been perf regressions, back last year the memoization was working correctly.

@lauri865
Copy link
Contributor Author

lauri865 commented Nov 27, 2024

You're right about try/catch in case it doesn't throw, my knowledge there was outdated.

Appreciate the context about virtualization. It does make some features like dynamic rowHeight also easier to implement I suppose.

After thinking a bit more about the getCellParams API, I'm not sure making it return null is necessarily good for DX either. We use it in a few different places in our app code (8 instances), and in every use, it's very explicit that the cell/row does exist. Say, we're focusing in on a cell or hovering it or triggering a context menu on it or copying a value from it, and need to access the cell's props. Why wouldn't it suddenly exist? Then we need to write extra code only to please typescript. We don't have any try catch logic either, and haven't had issues so far at least 🤔. One way or the other, it would be better if the cell value existed until the row has unmounted.

@cherniavskii
Copy link
Member

Should I merge the same changes into v7? #15621

@lauri865
Copy link
Contributor Author

From our side, yes please 🙏

LukasTy pushed a commit to LukasTy/mui-x that referenced this pull request Dec 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs cherry-pick The PR should be auto-cherry-picked to a version branch after merge—add a version label as target performance scope: data grid Changes or issues related to the data grid product type: enhancement This is not a bug, nor a new feature v7.x
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[data grid] Updating rows has a performance bottleneck (MissingRowIdError + try/catch)
5 participants