-
Notifications
You must be signed in to change notification settings - Fork 45.8k
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
1000% performance improvement for intensive react apps #6322
Comments
Wow... |
@amized have you tried ReactPerf, and |
I don’t think ReactPerf would give any results here: the author already nailed it down to a very specific issue, which is selection restoration. I don’t have a good knowledge of that part of the codebase but I wonder if we can opt out of that if there was no selection in the first place, or if we can make it faster. |
@alexeyraspopov That only helps for unnecessary renders, which is a piece of the puzzle... but the OP is specifically digging into React-side performance matters. |
@yaycmyk by eliminating unnecessary render cycles you will decrease amount of work per frame. |
@amized Have you tried stripping your code down to a minimum, with which you're experiencing the bug? I can't really reproduce it. The stack is mentioning "ReactInput...abilities", so I've followed SELECTION_RESTORATION to this function, that matches the name:
But I don't really see why this would be responsible (?) Is this the same function that is taking this long in your stack? Edit: Might be connected to getActiveElement ? |
Interesting! @amized couple of questions to might help debugging further the issue:
|
Thanks for all the tips, I am using React 0.14.7. I've done some further investigation. I didn’t mention what seems to be an important fact now, that a video was playing on the page together with react components updating. (This is a JW player using flash streaming) I did some more experiments with adding/removing the video: Test 1: Test 2: Test 3: Test 4: Given the bug only seems to be triggered with Flash, I wouldn't expect this to be on the top of the priority list to fix, although it may be indicative of some other problem in SELECTION_RESTORATION. |
Your initial flame graph showed I wonder if reading properties off a flash object requires doing some expensive IPC / context switches. We could potentially special case flash, but flash is dying anyway so I'm not sure it's worth the headache. We would probably take a PR for this, but probably wouldn't do it ourselves because there are higher priority issues. |
I'm going to close this out, since I don't think it's something that we would invest in. We would probably take a PR for this if anyone cares to implement it. |
I have a real-time redux-react app that is performance critical. I have lot’s of components on the page that may update very frequently.
I noticed that some of my animations were running jerkily and general component updates were lagging when lots of actions were being dispatched in a small space of time (say 40 per second). I run a Mac 10.9.5 with the latest chrome.
I ran performance diagnostics using the react tools and then optimised my app as much as possible (mainly using shouldComponentUpdate), making sure no time was wasted in unnecessary DOM reconciliation or rendering.
But even after doing this, my app was still lagging. So I dug deeper by running a CPU profile in chrome devtools. I noticed that at the times when my animations were running jerkily or slow, the react setState() method calls were taking up to 25 ms - 30 ms on average.
That would only allow a maximum of 30 component updates a second before performance hits the wall, which in my case is an unacceptable limit. I also ran a timeline to see if it was browser painting that was slow - turns out no. Below you can see the majority of the work was being done inside scripts, not rendering. This seemed very odd to me.
So I looked at the function stack:
In this example the setState method took 24 ms purely in scripting (not rendering) and you can see a large chuck of that was spent in ReactInputSelection.hasSelectionCapabilities, the light blue method in the bottom row.
Tracing it back this was being called from the ReactReconcileTransaction.js module.
In here, supposedly React uses ReactInputSelection to restore an input selection after
<input>
and<textarea>
components get updated. Naturally I wanted to see what would happen if I turned it off, so I took the SELECTION_RESTORATION task out of the transaction wrapper.And guess what happened:
The extract same setState() calls took only 1ms - 3ms! Notice the aggregated total time went from 4.91 s in the first example to only 174 ms after turning off SELECTION_RESTORATION.
In others word, a > 1000% performance increase.
For my app this was huge, and afterwards everything ran perfectly smooth.
So I have a few questions:
<input>
or<textarea>
elements in my components?The text was updated successfully, but these errors were encountered: