Skip to content

Performance issues with large collections #1751

Closed
@JAndritsch

Description

Update: Disregard. Performance with large data sets is not an issue. Read the closing remarks for more info.

I'm seeing a pretty huge performance hit when attempting to dispatch several updates to state when the state contains a very large data set.

Background

I'm developing an image slider that is composed of two separate components: the Slider and the Preview. The Slider renders a list of 10 small thumbnails and allows a user to rapidly scroll through them via keybindings. The Preview displays a larger and higher quality version of the currently active slide in the Slider. The Preview updates as the Slider's active slide changes because they both subscribe to the same piece of state: currentSlideIndex. In addition to this state, the Redux store contains the entire collection of images.

The state object looks something like this:

{
  currentSlideIndex: 0,
  images: [
    { _id: '1234', path: '/path/to/image.jpg', thumb: '/path/to/thumb.jpg' },
   ...etc
  ]
}

I have one parent component, Index, which houses both the Slider and Preview components. The Index component uses React Redux's connect function to map the two pieces of state to properties. These properties are then passed down to both the Slider and Preview components.

Here's a simple example:

class Index extends React.Component {
  render() {
    return (
      <div>
        <Preview {...this.props} />
        <Slider {...this.props} />
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    images: state.images,
    currentSlideIndex: state.currentSlideIndex
  };
};

export default connect(mapStateToProps)(Index);

When a user changes the current slide, the Slider component dispatches an action to update the currentSlideIndex in the Redux store. This tells the Index component to re-render itself since currentSlideIndex changed, which means the Preview and Slider also re-render.

The problem

I've noticed as my collection of images grows, the performance of the Slider and Preview components degrade pretty dramatically.

At 500 images, things move pretty quickly. To illustrate how fast, imagine that each image represented a single frame in a movie. If I were to press and hold down the right arrow key, the Slider and Preview component would re-render fast enough that it would look like you're actually watching a movie. It's pretty sweet!

However, at 1500 images things begin to lag and get really choppy. Any number larger than that and things go from bad to worse. The store dispatches seem to lag considerably and the animation of the Preview and Slider updates goes from "movie-like" quality to "flip book with pages stuck together" quality.

Just for kicks, I decided to disconnect my Index component from the currentSlideIndex state and instead move that down into the Slider component as an internal piece of state. Instead of dispatching an action on keypress (which would update the Redux store), I changed it to run this.setState({ currentSlideIndex: newIndex }). Obviously keeping this as a piece of state that's not in the Redux store isn't ideal because the Preview component won't automatically update as the current index changes. But just for academic reasons, I decided to see what would happen.

The results are pretty interesting. After moving that piece of state out of the Redux store and into the Slider, I can now scroll seamlessly and with "movie-like" quality when my collection of images contains 7000+ items.

The conclusion/question

It seems that dispatching updates to a Redux store when the state contains a large collection of fairly-sized objects does not perform well. What's puzzling is that the piece of state I'm updating is entirely separate from the images collection. The only piece of data that's changing on store.dispatch() is currentSlideIndex (which is just a simple number), so I don't suspect that my reducer for the images state is at fault because it should just be a simple passthrough.

Is the behavior that I described expected or a known issue, or is there some fundamental thing I'm missing that could address this?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions