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

Huge performance issue when dispatching hundreds of actions #263

Closed
elado opened this issue Jan 21, 2016 · 7 comments
Closed

Huge performance issue when dispatching hundreds of actions #263

elado opened this issue Jan 21, 2016 · 7 comments

Comments

@elado
Copy link

elado commented Jan 21, 2016

On boot, the app I'm building gets a stream of data from a server. This stream can have hundreds of messages and entities and each message is handled separately.

It takes a tremendous amount of time to dispatch actions after UI has rendered, because every state change re-renders the @connected component.

I wrote a short example that shows dispatching 1000 actions before render (5-15ms) and 500 after render (~2.5s). So this is clearly not a redux issue.

https://jsbin.com/ruziwa/edit?js,console,output

Obviously component doesn't need to re-render every single dispatched action, but re-rendering should be throttled (say, every 50ms). Is there an established approach for that or does it need to be integrated in @connect?

@elado
Copy link
Author

elado commented Jan 21, 2016

Well, adding

ItemListContainer.prototype.render = _.throttle(ItemListContainer.prototype.render, 20)

really boosts performance.

Updated https://jsbin.com/ruziwa/11/edit?js,console,output

Probably messing with React's methods is not the right approach though.

@esamattis
Copy link
Contributor

Try this: Collect those those messages into an array and flush it with store.dispatch in a single tick with every 50ms (or whatever is required). You must use redux-batched-updates to avoid rendering on every dispatch on the tick.

https://github.com/acdlite/redux-batched-updates

@esamattis
Copy link
Contributor

Probably messing with React's methods is not the right approach though.

Yeah that will break sooner or later...

pseudo code

var store = createStoreWithBatchMiddleware();
var messages = [];

stream.on("message", msg) => messages.push(msg));

setInterval(() => {
  messages.forEach(msg => store.dispach(handleMessage(msg)));
  messages = [];
}, 50);

@elado
Copy link
Author

elado commented Jan 22, 2016

Thanks! I integrated https://github.com/tappleby/redux-batched-subscribe (redux-batched-updates uses deprecated api)

I used _.debounce, not unstable_batchedUpdates (it didn't seem to work at all)

This is the amazing result: https://jsbin.com/wurower/7/edit?js,console,output

Would it make sense to integrate to react-redux? Or to write a note about it in the docs?

@esamattis
Copy link
Contributor

I'm glad it solved your issue but you should note that debouncing and update batching are completely different things.

With debouncing you end up just completely ignoring most of the messages. That can be ok but if your store state requires to see every message, for example you need sum up some numbers from them, that will not work as expected.

React update batching and the setInterval trick I presented will dispatch every message to the store but will only do it batches to avoid excessive rendering.

@elado
Copy link
Author

elado commented Jan 22, 2016

@epeli not sure I understand the issue, can you please explain with code?

So far it seems that the issue of multiple unnecessary renders is gone, due to debouncing it, and store is filled correctly after every single dispatch action (it doesn't wait for the debouce time to execute a bunch of actions together).

@gaearon
Copy link
Contributor

gaearon commented Jan 25, 2016

I'm closing as this doesn't appear to be an issue with this repo—rather an issue with a particular approach. Please feel free to continue discussing!

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

3 participants