react-slingshot icon indicating copy to clipboard operation
react-slingshot copied to clipboard

Running development version very slow - any pointers as to why?

Open mstobin opened this issue 7 years ago • 7 comments

I am finding that when I run my app for testing in dev (i.e. "npm start"), the redux portion of it is extremely slow.

This seems to be specific to triggering redux actions via dispatch -- as soon as I dispatch a redux action, it feels like it takes up to a few seconds at times for the full dispatch->reducers->update React components loop to occur.

I am pretty confident it is related to redux dispatch, because I have other UI updates that bypass the redux route by calling setState directly on a React component, and they are responsive as I would expect.

When I run in "dist" mode with "npm run build", all of the speed issues go away, and the app is very responsive in all of the places that crawl in dev.

Is this normal? Or is there something that I am doing to trigger this?

Originally I had thought BrowserSync was to blame, but I see that is being used in the dist server as well.

Could it be something to do with the Hot Reloading, or perhaps some part of React that is logging every action for time-travel debugging or similar that could be causing the problem?

I can't recall making any config changes on my side that would cause this, but I was extremely new to react/redux/webpack etc. when I first started this project (I am coming from a Backbone/gulp background), so I may have inadvertently played with a setting I didn't understand.

Assuming this isn't expected, do you have any pointers towards places I might look to work out what has caused this?

I am deep enough into the project that I would prefer to forge ahead with react-slingshot rather than start again with a new configuration or starter kit to get things up and running, but the performance is killing me right now and makes it more or less unusable in dev.

Thanks for any pointers or suggestions on where to look.

mstobin avatar Mar 27 '18 23:03 mstobin

Can you share your code on GitHub so i can try to reproduce?

coryhouse avatar Mar 28 '18 00:03 coryhouse

Unfortunately, I can't share the entire project due to company policy etc. But if there are specific config files I may be able to share those.

Otherwise, I could copy the project and delete all the proprietary stuff until it rolls back to a minimum test case, and hope that the issue is still there.

mstobin avatar Mar 28 '18 00:03 mstobin

Please try again with the latest version of Slingshot. We've added a Webpack plugin that caches the build that should speed the build.

coryhouse avatar Apr 30 '18 11:04 coryhouse

What's the easiest way to update an existing react-slingshot project without inadvertently overwriting any important files?

I can't recall, but I expect I probably just downloaded the zip from GitHub the first time around rather than using git to clone the repo.

mstobin avatar May 01 '18 07:05 mstobin

The easiest way is to fork the project. If you didn't do that, then it's a manual process.

On Tue, May 1, 2018 at 2:26 AM, mstobin [email protected] wrote:

What's the easiest way to update an existing react-slingshot project without inadvertently overwriting any important files?

I can't recall, but I expect I probably just downloaded the zip from GitHub the first time around rather than using git to clone the repo.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/coryhouse/react-slingshot/issues/551#issuecomment-385615766, or mute the thread https://github.com/notifications/unsubscribe-auth/ABnFpdQgBPPoz-RAM0MUp1NlI59cZSsIks5tuA4egaJpZM4S9xvz .

-- Cory House Principal: reactjsconsulting.com http://www.reactjsconsulting.com Author: Pluralsight Courses http://www.pluralsight.com/author/cory-house

coryhouse avatar May 01 '18 12:05 coryhouse

Sorry for the delay. I updated to the latest version of slingshot, and I didn't see any improvement, which isn't surprising since it was a runtime rather than build time issue.

But I have finally managed to devote some time and find the culprit. It is the reduxImmutableStateInvariant() middleware.

As an example of the kind of timing issues I am seeing:

  • In my app, I have two components: Node and Parent
  • Clicking on Parent dispatches a "parentActive" action.
  • Clicking on Node dispatches a "selectNode" action, and bubbles up to Parent to dispatch the "parentActive" action also.

Timing with reduxImmutableStateInvariant() middleware:

All listed times are elapsed time from the initial click:

  • 0ms: Click occurs on Node
  • 0ms: dispatch() called with "selectNode" from Node
  • 1702ms: root reducer called with "selectNode" action
  • 1703ms: root reducer finishes
  • 1705ms: Parent mapStateToProps() called
  • 2785ms: dispatch() called with "parentActive" from Parent
  • 3846ms: root reducer called with "parentActive" action
  • 3848ms: root reducer finished
  • 4899ms: Node mapStateToProps() called

So all up, it takes almost 5 seconds for the entire system to finish responding to the single click (two dispatched actions) event.

Of that time:

  • Only 3ms is spent in my actual reducer code
  • 2700ms is spent waiting for a dispatch() call to arrive in the reducer
  • approx 2100ms is lost somewhere going the other direction

Timing without reduxImmutableStateInvariant() middleware:

The only change I made was to comment out that line from the middleware, everything else is still the same development build environment.

Here's the new timing:

  • 0ms: Click occurs on Node
  • 0ms: dispatch() called with "selectNode" from Node
  • 0ms: root reducer called with "selectNode" action
  • 1ms: root reducer finishes
  • 2ms: Parent mapStateToProps() called
  • 9ms: dispatch() called with "parentActive" from Parent
  • 9ms: root reducer called with "parentActive" action
  • 10ms: root reducer finished
  • 31ms: Node mapStateToProps() called

As you can see, with the safety check on state invariance removed, we save ourselves almost the full 5 seconds (99% of the time delay), and the app actually becomes usable.

Where to from here? So I guess the question is: is this expected and normal for that module, or might there still be something odd going on with my project for this to have become so slow?

Obviously, I would prefer to leave it in there as it is quite possibly going to save me from a nasty bug at some point, but with the runtime difference we are talking about, I feel like I have no option but to disable it.

Any alternative suggestions?

Thanks, Matt

mstobin avatar May 15 '18 07:05 mstobin

Wow, that's wild. I know reduxImmutableStateInvariant has a perf hit, which is why they say it should only be run in development, but I've never seen a perceivable impact on apps. I suspect there's something unique about your app.

coryhouse avatar May 18 '18 20:05 coryhouse