Skip to content

[internal] perf: sx#44254

Open
romgrk wants to merge 62 commits intomui:masterfrom
romgrk:perf-sx
Open

[internal] perf: sx#44254
romgrk wants to merge 62 commits intomui:masterfrom
romgrk:perf-sx

Conversation

@romgrk
Copy link
Contributor

@romgrk romgrk commented Oct 29, 2024

Improve sx performance by removing allocations.

Example user code:

Before: 23.4ms +-1.6
After:  15.2ms +-1.1

n=100

We get roughly 35% less rendering time for the example above which makes heavy use of the sx prop, so I guess user-code would see something in the 0-40% less rendering time depending on how much they use that prop.

We can still get a lot more improvement by eliminating more memory allocations (I think we can get that example to at least 50% less rendering time), but the remaining changes would require more substantial work. The format of the style({ [prop]: value, theme }) sx style handlers is expensive, we could instead use something like style(prop, value, theme), though IIUC the system props also use those so there's a bit of refactoring to do.

The logic to create an empty breakpoint object for each sx object/subobject is also expensive, I've tried to remove it by lazily initializing the breakpoints but handleBreakpoints is used too much in the codebase so that's another large refactor.

@romgrk romgrk added performance internal Behind-the-scenes enhancement. Formerly called “core”. labels Oct 29, 2024
@mui-bot
Copy link

mui-bot commented Oct 29, 2024

Netlify deploy preview

https://deploy-preview-44254--material-ui.netlify.app/

Bundle size report

Bundle Parsed size Gzip size
@mui/material 🔺+1.08KB(+0.21%) 🔺+445B(+0.29%)
@mui/lab 🔺+2.46KB(+7.54%) 🔺+946B(+11.54%)
@mui/system 🔺+1.24KB(+1.80%) 🔺+481B(+1.92%)
@mui/utils 🔺+849B(+6.61%) 🔺+255B(+5.06%)

Details of bundle changes

Generated by 🚫 dangerJS against 71fc34e

@romgrk romgrk marked this pull request as ready for review November 4, 2024 16:10
@romgrk romgrk requested a review from a team November 4, 2024 16:10
getCssVar,
spacing: getSpacingVal(spacing),
font: { ...prepareTypographyVars(mergedScales.typography), ...mergedScales.font },
internal_cache: {},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would have expected to have to add .internal_cache to the system's createTheme function only, but I ended up needing to add it at various locations. It would be neat to pass all our themes through that function to avoid repeating internal details in various places.

Copy link
Member

Choose a reason for hiding this comment

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

Why couldn't we just add it in the createTheme function? What was the issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Some created theme objects don't go through system's createTheme at all. I don't feel confident enough to pass them all through it at this point, I'm not sure what edge-cases I might find doing so.

<Div color="white" bgcolor="palevioletred" p={1}>
Styled components
</Div>
<ThemeProvider theme={theme}>
Copy link
Member

Choose a reason for hiding this comment

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

Why did we need to change this demo?

getCssVar,
spacing: getSpacingVal(spacing),
font: { ...prepareTypographyVars(mergedScales.typography), ...mergedScales.font },
internal_cache: {},
Copy link
Member

Choose a reason for hiding this comment

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

Why couldn't we just add it in the createTheme function? What was the issue?

@@ -1,7 +1,12 @@
import PropTypes from 'prop-types';
import isObjectEmpty from '@mui/utils/isObjectEmpty';
import fastDeepAssign from '@mui/utils/fastDeepAssign';
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
import fastDeepAssign from '@mui/utils/fastDeepAssign';
import deepAssign from '@mui/utils/deepAssign';

Copy link
Contributor Author

@romgrk romgrk Nov 12, 2024

Choose a reason for hiding this comment

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

When I name something fast... it usually means there's a trade-off with correctness to focus on being "fast". Here it's that it doesn't handle exotic objects as other implementations will, as in, it will also traverse enumerable properties on the object's prototype. In the cases where we use this function (to create React props objects copies, or to create CSS style objects) we can safely assume that invariant is true. I should add this to the jsdoc, but I like having some sort of warning in the name.

Copy link
Member

@mnajdova mnajdova Nov 13, 2024

Choose a reason for hiding this comment

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

Adding this to the jsdoc would definitely help. On the other hand, I would recommend maybe moving this util outside of @mui/utils, if it is only used in the mui-system, to avoid developers accidently using it in other places where it may not be the right thing. If you already plan to use it in other places, then probably we can keep it in @mui/utils.


if (isPrimitive(source)) {
return source;
} else if (isPrimitiveOrBuiltIn(target)) {
Copy link
Member

Choose a reason for hiding this comment

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

Why not just check for built in here? We have the primitive check already on the previous condition.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't write it, I pulled it from the source listed at the top and made a few modifications to simplify it. I could simplify it further.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I thought is a new code, we can update it later in that case, up to you.

@DiegoAndai
Copy link
Member

@romgrk let me know if/when you need a new review on this

@romgrk
Copy link
Contributor Author

romgrk commented Feb 18, 2025

This is nearly complete, the only remaining issue would be the failing Joy UI argos test and adressing Marija's comments, but I don't have enough bandwidth for this with the upcoming DataGrid release. I'll try to finish it when I find some time, but if anyone has interest in getting it merged feel free to take over.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Mar 7, 2025
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Apr 29, 2025
@siriwatknp
Copy link
Member

I will spend time on this next week.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jun 12, 2025
@oliviertassinari oliviertassinari changed the title [core] perf: sx [internal] perf: sx Aug 16, 2025
# Conflicts:
#	docs/data/system/getting-started/custom-components/CombiningStyleFunctionsDemo.js
#	docs/data/system/getting-started/custom-components/CombiningStyleFunctionsDemo.tsx
#	packages/mui-system/src/createStyled/createStyled.js
#	packages/mui-system/src/cssContainerQueries/cssContainerQueries.ts
#	packages/mui-system/src/merge/merge.ts
#	packages/mui-system/src/style/style.d.ts
#	packages/mui-system/src/styleFunctionSx/styleFunctionSx.js
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Behind-the-scenes enhancement. Formerly called “core”. performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants