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

Possible performance regression in v5 #686

Closed
necolas opened this issue Apr 26, 2017 · 20 comments
Closed

Possible performance regression in v5 #686

necolas opened this issue Apr 26, 2017 · 20 comments

Comments

@necolas
Copy link

necolas commented Apr 26, 2017

Hi, this is just a heads up. We tried upgrading Twitter Lite to use v5 but noticed that Tweet update timings increased significantly after we deployed to production. Reverting to v4 caused those timings to fall back to the baseline level. We haven't looked into the cause yet.

/cc @paularmstrong

@markerikson
Copy link
Contributor

Really. That's... disturbing.

The benchmarks in #407 and #416 , and other testing, indicate that v5 should be faster for almost all use cases. I think there were one or two exceptions where v4 was faster - think the discussion/examples were in https://www.reddit.com/r/reactjs/comments/5hf4d4/an_artificial_example_where_mobx_really_shines/ and dtinth/pixelpaint#1 .

Any info you can provide would be greatly appreciated.

@jimbolla
Copy link
Contributor

I'd like to help with this if you can provide more info.

@paularmstrong
Copy link

paularmstrong commented Apr 26, 2017

I'm looking at narrowing down the cause, but it may take a long time and it's not really a priority at the moment. We only have some perf timings around Timelines and Tweets for "time from construct to mount" and "time from willUpdate to didUpdate". This is the graph of p95 and p50 for update timings:

context

(Ignore the noise toward the right on p95, that happens periodically) Please keep in mind that this could be something specific with our setup as well, though we're not doing anything special other than using connect with reselect selectors across many components.

@markerikson
Copy link
Contributor

Any further info you can offer on these performance regressions?

@timdorr
Copy link
Member

timdorr commented May 3, 2017

If @necolas or @paularmstrong could offer a flame graph of the app under 5.0, that would be helpful.

@gaearon
Copy link
Contributor

gaearon commented Jul 20, 2017

@necolas Have you had a chance to look at this again yet?

@necolas
Copy link
Author

necolas commented Jul 21, 2017

No, not yet

@paularmstrong
Copy link

Okay, I've finally gotten some things together that are able to show this.

I've created a component that will run 50 updates to a tree and estimate the amount of time each update takes. I did this because I want to be able to do this in a production build of React and not need to rely on react-addons for performance measurements. The implementation of this shouldn't matter at the moment, but I hope to decouple it a bit and open source it in the next week or so.

Specs

  • System: Mac OS X
  • Chrome: 60.0.3112.113
  • CPU: 3.1GHz Intel Core i7 (simulated 10x slowdown in Chrome)
  • Packages:
    • reselect@2.5.3
    • react@15.5.4
    • react-dom@15.5.4

Note: These timings are much more apparent on mobile browsers, but they still show up on desktop Chrome enough that these recordings should be good enough

React Redux v4.4.8

Chrome DevTools Timeline

v4-desktop-10x


React Redux v5.0.6

Chrome DevTools Timeline

v5-desktop-10x


Component Tree

The following is the connected component tree that I'm rendering in the above recordings.

import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import React, { Component } from 'react';

const exampleMapStateToProps = createSelector(
  (state, props) => 'foobar',
  (foo) => ({ foo })
);

const foobar = () => {};
const exampleMapDispatchToProps = { foobar };

class Internal extends Component {
  render() {
    return <div>barfoo</div>;
  }
}

class InternalContainer extends Component {
  render() {
    return <Internal />;
  }
}

const InternalContainerConnected = connect(exampleMapStateToProps, exampleMapDispatchToProps)(
  InternalContainer
);

class Example extends Component {
  render() {
    return <InternalContainerConnected />;
  }
}

class ExampleContainer extends Component {
  render() {
    return <Example />;
  }
}

export default connect(exampleMapStateToProps, exampleMapDispatchToProps)(ExampleContainer);

@markerikson
Copy link
Contributor

Unfortunately haven't had time to swing back and look at this myself. @jimbolla , you had a whole bunch of benchmarks when we did the v5 rewrite. Any ideas on how this scenario compares so differently to those?

@paularmstrong
Copy link

@jimbolla @markerikson any update on this? I can help narrow down traces if needed, but a bit too busy with other things to dive much deeper into react-redux itself.

@jimbolla
Copy link
Contributor

I haven't done anything concrete. I'm not sure how to make it any faster for React 15. Looking at the changes for React 16, it's might be possible to make it faster for that, but slowing down 15. I haven't tested this theory at all though.

@paularmstrong
Copy link

@jimbolla we found the same results after upgrading to react 16

@jimbolla
Copy link
Contributor

Yeah. I'd expect that. What I meant was that if we make a version of React Redux that targets React 16's new capabilities, we ought to be able to improve perf. I made an untested proof of concept here: #856. I haven't had a chance yet to put it through its paces, but if this POC moves forward, would you be willing to test it in your environment?

@paularmstrong
Copy link

@jimbolla absolutely. Just let me know!

@cellog
Copy link
Contributor

cellog commented Aug 25, 2018

@paularmstrong can you post the part of the benchmark app that does updating? I'm trying to port your example connected component into the performance test suite @markerikson wrote. I just want to be sure I'm actually catching the behavior you found, so we can first verify that 5 is slower.

Did you use this repo?

https://github.com/necolas/react-component-benchmark

@paularmstrong
Copy link

paularmstrong commented Aug 25, 2018

@cellog I used/wrote the source that's forked from: https://github.com/paularmstrong/react-component-benchmark

@cellog
Copy link
Contributor

cellog commented Sep 4, 2018

@paularmstrong I need more info. What is the createStore and so on look like? How are you setting up the default run of the benchmark? What props are passed to the sample component? What exactly are you trying to measure? I can't reproduce a benchmark that shows any difference in versions

@paularmstrong
Copy link

paularmstrong commented Sep 5, 2018

@cellog I'm trying to create some reduced test cases in codesandbox, but suddenly not able to see the issue anymore. I'll need a few days to test this out at Twitter as well to see if perhaps the issue is mysteriously gone.

Work-in-progress, slowly adding more things from our setup:

@cellog
Copy link
Contributor

cellog commented Sep 6, 2018

really appreciate the work, thank you

@markerikson
Copy link
Contributor

I know this issue is closed, but I see that Twitter is still using v4.

I'd love to know if v7 is an improvement!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants