-
-
Notifications
You must be signed in to change notification settings - Fork 32.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
[core] Regression test is 5 times slower after React 19 upgrade #44920
Comments
@oliviertassinari this looks related (reference): Average CPU usage down to 25% from 75% in around the same dates. Do you know what could cause this? |
It's definitely a React 19 thing: In this PR #44868:
|
Looks like it's related to the Suspense changes: #44935 |
Hey @eps1lon, what might be going on here? After upgrading to React 19, our regressions tests went from 4 minutes to 20. If I remove the Suspense component from the test (see #44935), the test returns to 4 minutes. The Suspense component was added here: #28239. I couldn't find much information about the impact of the Suspense React 19 changes on If you have any ideas or could point me to a resource that might be related, I would greatly appreciate it. |
After React displays a fallback, React will throttle the reveal of the Suspense boundary by 300ms to reduce jank (see facebook/react#31819). Should be fixed by wrapping the initial render in |
Thanks for the response @eps1lon. I don't understand what you meant:
To which initial render are you referring to? Where/how should |
Where you call |
I tried on material-ui/test/regressions/index.js Line 318 in f37ca96
and material-ui/test/regressions/index.js Line 465 in f37ca96
Sadly, none worked. It's maybe due to something we're doing regarding this comment? material-ui/test/regressions/TestViewer.js Lines 12 to 14 in f37ca96
Also, for |
material-ui/test/regressions/index.js Line 395 in f37ca96
startTransition . Basically any state update that triggers a Suspense fallback in your test needs a startTransition .
|
I also tried adding it there, but it doesn't work 😓 The only thing inside the Suspense barrier are the tests, so adding At this point, I will rework the test workflow without suspense. I don't think we need the fallback anyway. Thanks fro the replies, @eps1lon, I appreciate it. |
It doesn't matter whether you use
I don't think you need to do this as far as I remember. Don't we trigger the same function between each test? Just make sure that is wrapped in |
Then why, by just removing
I don't know what function you're referring to. Sorry, I'm not very familiar with this section of the code 😓. |
Looking a bit into this. It looks runtime related. With a small reproduction: import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
function Fallback() {
React.useEffect(() => {
console.time('fallback');
return () => {
console.timeEnd('fallback');
};
}, []);
return <div>fallback</div>;
}
const components = Array.from({ length: 1000 }, (_, i) =>
React.lazy(async () => ({
default: function Foo() {
return <div>foo {i}</div>;
},
})),
);
function App() {
const [counter, setCounter] = React.useState(0);
const Foo = components[counter % components.length];
return (
<div>
<button onClick={() => setCounter((x) => x + 1)}>click</button>
<React.Suspense fallback={<Fallback />}>
<div>hello {counter}</div>
<Foo />
</React.Suspense>
</div>
);
}
ReactDOM.createRoot(document.getElementById('react-root')).render(<App />); This consistently prints ~300ms on every click in our webpack setup. Trying the same in vite prints <1ms each time. @eps1lon given that I nowhere start a transition, even though it's not desired for our use-case I suppose webpack is behaving as expected here and vite has a bug? Will probably just port our test setup to vite if it lets me within reasonable time. We can get a few more wins with this setup. |
If you wrap But, if you are using some external state, such as import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
function Fallback() {
React.useEffect(() => {
console.time('fallback');
return () => {
console.timeEnd('fallback');
};
}, []);
return <div>fallback</div>;
}
const components = Array.from({ length: 1000 }, (_, i) =>
React.lazy(async () => ({
default: function Foo() {
return <div>foo {i}</div>;
},
})),
);
const store = {
counter: 0,
incrementCounter() {
this.counter = this.counter + 1;
this._subscribers.forEach((callback) => callback());
},
_subscribers: new Set(),
subscribe(callback) {
store._subscribers.add(callback);
return () => store._subscribers.delete(callback);
}
};
function useCounter() {
return React.useSyncExternalStore(store.subscribe, () => store.counter);
}
export function App() {
const counter = useCounter();
const Foo = components[counter % components.length];
return (
<div>
<button onClick={() => React.startTransition(() => store.incrementCounter())}>click</button>
<React.Suspense fallback={<Fallback />}>
<div>hello {counter}</div>
<Foo />
</React.Suspense>
</div>
);
} |
Transitions are, but initial render stays >300ms. Even when wrapping |
This issue has been closed. If you have a similar problem but not exactly the same, please open a new issue. |
From #44672 (comment)
Tests speed increased by x2.4 https://app.circleci.com/insights/github/mui/material-ui/workflows/pipeline/overview?reporting-window=last-60-days after December 1st.
It seems to be this PR: #44672. The time it takes to run the visual regression tests:
Some notes:
Search keywords:
The text was updated successfully, but these errors were encountered: