bvaughn / react-virtualized

React components for efficiently rendering large lists and tabular data
http://bvaughn.github.io/react-virtualized/
MIT License
26.1k stars 3.05k forks source link

CellMeasurerCache is really slow if you scroll to the bottom. Would you be open to a PR? #1747

Open distinctdan opened 2 years ago

distinctdan commented 2 years ago

Bug Report

I'm trying to build a table with fixed headers. To do it, I'm using a MultiGrid with a CellMeasurer. However, if the user scrolls to the bottom, the performance becomes unusable. From profiling, I can see that the bottleneck is in CellMeasurerCache. _updateCachedColumnAndRowSizes.

Here's an example grid with 100k rows. If you scroll at the top, it's fine, but once you scroll to the bottom, any future scrolling locks the browser: https://codesandbox.io/s/react-virtualized-list-with-width-100-forked-mmu5r8?file=/Example.js

What is the current behavior?

This is caused by how the CellMeasurerCache recalculates the max width and height when you call set. It keeps a record of the farthest index visited, and it iterates all rows/cols up until that index whenever you call set. This is to determine the new max height/width. However, for large data sets, this becomes really slow because it's an O(n) algorithm.

What is the expected behavior?

It looks like we only care about the max value for width and height, so we could make this a lot faster, something like O(log(n), by storing them as a max heap or a sorted array instead. Would you be open to a PR to implement this?

Which versions of React and react-virtualized, and which browser / OS are affected by this issue? Did this work in previous versions of react-virtualized?

Browser Any
OS Any
React Any
React DOM Any
react-virtualized 9.22.3

Screenshot from Chrome's profiler:

Screen Shot 2022-05-03 at 6 09 49 PM
distinctdan commented 2 years ago

For my use case, I can guarantee that my cells never get removed or change size, so I've copied the CellMeasurerCache and modified it to not iterate all the rows, and to just keep the max updated like this:

this._columnWidthCache[columnKey] = Math.max(this._columnWidthCache[columnKey] || 0, width);
fabricioAburto commented 2 years ago

if someone use this lib is obvio that will use it with a remote data, with unknown height for every cell, so why the docs dont put more priory over that? The creator is thinking data come from local? Is very difficult to make it work. anyone know a wrapper library for this that encaplate the complexity of this in a very friendly and easy to use one?

CaptainHoangLe commented 2 years ago

i have the same issue with my infiniteLoader Table when scrolling up and down.i think A large number of element in each row may be my reason. So i am looking forward Anyone has solution can help me. Thanks of All !