Open niklasramo opened 4 years ago
Hi Niklas,
I'm finishing the new version of muuri-react, and I was also reflecting on how I can optimize the use cases with thousands of items, since there are several windowing/virtualization libraries for react. I started looking on github but there seems to be nothing compatible with the project.
I thought of a possible implementation but came to the conclusion that it cannot be external and must be provided directly by Muuri.
I take advantage of this issue to show you the idea I was working on.
I don't have a broad vision like yours that you created this library, and I don't know if this could work but I hope it could be useful. Muuri is really fantastic :)
sizes
.'larger'
and 'smaller'
(These terms need a more accurate definition, for now let's say that these items are unique).visible
on the screen.Taking this representation of the grid element:
Grid area
________________________________
| |
| |
| |
|Visible area |
|...............................| <-- top border
|...............................|
|...............................|
|...............................|
|...............................|
|...............................| <-- bottom border
| |
| |
| |
| |
|_______________________________|
We can easily establish (with simple equations) the minimum number of items before the visible area (Vmin) and the maximum number of items within the visible area (Vmax).
Vmin = 3 (Big items) Vmax = 20 (Small items)
________________________________ ________________________________
| ______ ______ ______ | | ___ ___ ___ ___ |
| | | | | | | | | |___| |___| |___| |___| |
| | | | | | | | | ___ ___ ___ ___ |
| |______| |______| |______| | | |___| |___| |___| |___| |
|...............................| <--- top border ---> |...___ ....___....___ ...___...|
|...............................| |..|___|...|___|..|___|..|___|..|
|...............................| |...___ ....___....___ ...___...|
|...............................| |..|___|...|___|..|___|..|___|..|
|...............................| |...___ ....___....___ ...___...|
|...............................| <-- bottom border --> |..|___|...|___|..|___|..|___|..|
| | | |
| | | |
| | | |
| | | |
|_______________________________| |_______________________________|
Now we are sure that the items to be displayed are definitely between the positions [ Vmin, Vmax ].
The layout work will then be minimized to represent the visible items. It could be partially redone for the part that will become visible over time (for example linked to a scroll event).
Reading the tests you did, maybe it's enough to put display none to the non-visible item.
Hi @Paol-imi ! You've done great work with muuri-react, thanks for that 👍
This virtualization problem is very tricky with Muuri, because there's no restrictions on the layout. Any item (regardless of their index in the _items
array) can be positioned anywhere in the grid. This is why we always need to compute all the item positions before we can determine if an item will be visible in the viewport (or the grid) when the positions are applied to the elements. Of course we could provide some heuristics for specific layout modes, but that's a another optimization later down the road.
Ideally, we would render (add to DOM) items only when they are in view and remove them from the DOM when they are out of the view. This would probably be optimal in terms of performance and memory. However, that's also a bit complex to implement compared just setting item's display
value based on if it's in view or not. In my tests display:none
trick worked wonders and made the UI very responsive even in the 5000-10000 item range. That's already a big upgrade compared to the current state of affairs and would be awesome if that optimization just worked out of the box without any extra configuration. Let's see if I can make it happen, it actually should not be that hard to implement.
I've been benchmarking the latest version of Muuri (
dev
branch) with large grids (1000 - 10000 items) and I'm not really happy with the performance. After a bit of thinking and quick testing I identified three bottlenecks:el.style.display = 'none'
to all the grid items that are not in the screen makes that issue go away. In Chrome you can also doel.style.visibility = 'hidden'
, but that trick does not work so well on other browsers. The bottom line is that some kind of "virtualization/windowing" needs to be done to keep the UI smooth and responsive.All of these bottlenecks can be fixed so let's fix them 🙂