What size ScrollView starts to affect performance (React Native) - javascript

I'm trying to implement a scroll animation on my FlatList using react-native-reanimated2 but I'm having trouble doing so. However, I am able to implement the animation using a ScrollView. The list is of a fixed size (no more than 20 items). I was just wondering, how many items can the ScrollView render before it starts to cause performance issues (because it renders all items at once). Is there a benchmark value? I'm asking because I don't want to have performance issues in my app because the Scrollview. Thanks.

Why don't you try it? Make a ScrollView with one item, twenty, a hundred, a thousand. Scroll to test, or build in native editors and use their perf monitors. For an accurate representation, use release builds - dev builds will always be slower.
It largely depends on how complex the items are, and the capabilities of the device. Single lines of text on a recent phone? Should be fine with lots. Multiple animations and images per item? More than a couple might choke on an old device.

Related

React-Native FlatList performance problems with large list

My code gets Json data to an array lists the data using a FlatList. It looks like a phonebook photo and text in a row.
Here is My code:
renderItem = ({ item }) =>
(
<ListItem
title={item.username}
avatar={{ uri: item.photo }}
/>
)
render() {
console.log(this.state.myData);
return (
<View style={styles.container}>
<FlatList
data={this.state.myData}
renderItem={this.renderItem}
/>
</View>
);
}
Its works and I get the output, but the performance is slow. Rendering takes approximately 10 seconds which is annoying to the user. What should I do to make it faster?
Edit Dec 20 '19: The information on this answer became part of the official docs. You should check it out!
Edit May 26 '18: This answer became a bigger and more complete post on github
If you follow this thread, you'll see that react's team is already aware of this performance issue.
There is no silver bullet for this issue, you have to consider the trade offs of every approach and what you think is a good experience for your audience. But fortunately there are several tweaks you can try and improve your FlatList.
Terms and meanings
There are a lot of terms used (on docs or some issues) that were confusing for me at first. So, let's get this out of the way from the start.
VirtualizedList is the component behind FlatList, and is React Native's implementation of the 'virtual list' concept.
Performance, in this context, imply a smooth (not choppy) scroll (and navigation in or out of your list) experience.
Memory consumption, in this context, is how much information about your list is being stored in memory, which could lead to a app crash.
Blank areas means that the VirtualizedList couldn't render your items fast enough, so you enter on a part of your list with non rendered components.
Window here is not your viewport but rather, size of the area in which items should be rendered.
Props
One way to improve your FlatList is by tweaking it's props. Here are a list of props that can help your with that.
removeClippedSubviews
You can set the removeClippedSubviews prop to true, which unmount components that are off of the window.
Win: This is very memory friendly, as you will always have a little rendered list.
Trade offs: Be aware, that this implementation can have bugs, such as missing content if you use it on a component that will not unmount (such as a navigation route).
It also can be less performant, having choppy scroll animations for big lists with complex items on not-so-good devices, as it make crazy amounts of calculations per scroll.
maxToRenderPerBatch
You can set the maxToRenderPerBatch={number}, which is a VirtualizedList prop that can be passed directly to FlatList. With this, you can control the amount of items rendered per batch, which is the next chunk of items rendered on every scroll.
Win: Setting a bigger number means less visual blank areas when scrolling (a better the fill rate).
Trade offs: More items per batch means less JavaScript performance, which means less responsiveness (clicking a item and opening the detail). If you have a static and non-interactive list, this could be the way to go.
initialNumToRender
You can set the initialNumToRender={number}. This means the initial amount of items to render.
Win: You can set this value to the precise number of items that would cover the screen for every device. This can be a big performance boost when rendering the list component.
Trade offs: You are most likely to see blank areas when setting a low initialNumToRender.
windowSize
You can set the windowSize={number}. The number passed here is a measurement unit where 1 is equivalent to your viewport height. The default value is 21, being 10 viewports above, 10 below, and one in between.
Win: If you're worried mainly about performance, you can set a bigger windowSize so your list will run smoothly and with less blank space. If you're mainly worried about memory consumption, you can set a lower windowSize so your rendered list will be smaller.
Trade offs: For a bigger windowSize, you will have a bigger memory consumption. For a lower windowSize, you will have lower performance and bigger change of seeing blank areas.
legacyImplementation
This prop, when true, make your FlatList rely on the older ListView, instead of VirtualizedList.
Win: This will make your list definitely perform better, as it removes virtualization and render all your items at once.
Trade offs: Your memory consumption goes to the roof and chances are good that a big list (100+) with complex items will crash your app.
It also fires a warning that the above tweaks will not work, because you're now on a ListView.
disableVirtualization
You will see people advocation the use of this prop on some issues. But this is deprecated now. This used to do something similar to legacyImplementation.
List items
There are also some win-win strategies that involves your list item components. They are being managed by VirtualizedList a lot, so they need to be fast.
Use simple components
The more complex your components are, the slower they will render. Try to avoid a lot of logic and nesting in your list items. If you are reusing this list item component a lot in your app, create a duplicate just for your big lists and make them with less logic as possible and less nested as possible.
Use light components
The heavier your components are, the slower they render. Avoid heavy images (use a cropped version for list items, as small as possible). Talk to your design team, use as little effects and interactions and information as possible in your list. Save them to your item's detail.
Use shouldComponentUpdate
Implement update verification to your components. React's PureComponent is mostly for when you don't have time to think. If you're reading this, you do have time, so, create the strictest rules for your list item components. If your list is simple enough, you could even use
shouldComponentUpdate() {
return false
}
Here are some improvements you can do to optimize your flatlist:
Pagination
You can paginate your data in your backend and refetch it when your scroll gets closer to the end. onEndReached and onEndReachedThreshold can help you.
Update your React Native version to 49 or latest
Fiber 16 has amazing performance improvement which makes everything runs faster and smoother
Use PureComponent for render item
PureComponent improves the rendering and memory usage of your component, creating render items as pure gives you a better performance experience
Define getItemLayout prop
It improves item rendering since React will previously know its layout definition
Hope it helps
Wrap your <FlatList> within a <ScrollView> to prevent white pages and performance issues on large datasets

scroll-link effect is deprecated, what's a better alternative in modern browsers?

I'm currently maintaining an old legacy project, where I just noticed a message from my browser about how scroll-linked effects reduce rendering performance.
The application is rendering a large form, on the bottom there is a slider with lots of data, which will be loaded asynchronously (and only if the user scrolls down, so it gets into his view). Afterwards it creates a lot DOM-elements (a lot means a typical of 100-300 figures with an image, texts and some attributes each) that will be added into the slider.
So I was reading about Scroll-linked effects on MDN to take care about this performance issue, but I don't know what's the best practice is. Neither I can use the examples about "sticky positioning" nor "scroll snapping". Also I do not want to customize scrolling in any way.
The goal is of this behavior is to delay loading the big bunch of data as much as possible (since only when the user scrolls this page down, he really needs this data).
Can you please help me how to take advantage on this, to optimize the scrolling performance of the application without losing the lazy-loading feature?
You can use a combination of check element visible in the viewport + requestAnimationframe
https://stackoverflow.com/a/125106/800765

Improve performance when using GoJS

I have to deal with very big data sources lately and was wondering if there was a way to increase the performance of GoJS.
GoJS is very efficiently processing my data, and the TreeView I am trying to make is displayed shortly after the site is fully loaded. Unfortunately, when panning the view, the diagram somehow begins to lag a little.
I am now looking for a way to decrease that lag to a minimum.
I tried fiddling with the Layout options but it did not result in significant performance increase.
To the diagram, I have a diagram with "relatively" few nodes (498 to be precise), but my template is unfortunately rather complicated. It has a nested itemArray, which generates rows and columns inside that row. Another thing is that I use a slightly modified version of the "LayeredTreeView" model.
These nodes are in 388 invisible groups. Generating it without using layout things like crossing reduction only takes a moderate amount of time.
Also i have just discovered the performance site of the GoJS introduction. It has been mentioned there, that complex templates make GoJS slow. Could this here be the case?
Complicated templates take longer to build than simple ones, so the loading time will take longer when the nodes are complex and detailed.
However, once all of the Nodes and Links have been created and initialized in the Diagram, scrolling (a.k.a panning) should be pretty fast.
Virtualization decreases load time because there should be very few nodes and links to create and show initially. However virtualization does slow down scrolling and zooming because nodes and links have to be created as the viewport changes. And as that Performance page suggests, implementing virtualization requires a lot more programming work. And it might not even be feasible or faster, depending on the circumstances.

Will Isotope filtering perform well with several hundred items & multiple categories?

I'm hoping to use the Isotope Jquery plugin (http://isotope.metafizzy.co/) to display and filter several hundred items (around 700). Each item will contain a thumbnail image and a name, and be filterable by three categories. (To stop the page being ridiculously long, the whole thing will be contained inside a scrollable div).
If possible, I would like to enable the animation effect too (using the 'best-available' animation engine, which will fall back on JS if CSS3 transitions are unavailable).
I've tested it locally with about 100 items and it performs very quickly in Chrome and both the CSS3 and JS animations are pretty fast. But I'm worried that out there in the wild, it may turn out to be unusably slow for older clients and browsers (and of course, there's a very tight deadline so not much time to build a better prototype!).
Does anyone have experience of using it on a similar scale?
Thank you,
Peter
I'd recommend your item count should be around 50 items max if you're doing filtering or sorting. That doesn't mean you can try pushing it. For example, Leafly's item count is close to 300.
Okay well I can answer my own question now, because we tried to build it. The answer was it was too slow in pretty much all browsers except Chrome where it was just about acceptable. Even in Firefox on a fast Mac laptop, it was taking roughly 5 seconds to load the page from scratch and not much less than that to change the filters back to 'all'. It even gave an unresponsive script warning for a couple of people who checked it in Safari and IE.
So I rewrote it to just simply add/remove a 'hide' class on each item instead. From a quick comparison this is roughly about 50% quicker. Obviously this loses all the fancy animation though. So I would recommend Isotope for smaller datasets where snazzy visual effects are important, but not to work with hundreds of items.

I have a couple thousand javascript objects which I need to display and scroll through. What are my options?

I'm working off of designs which show a scrollable box containing a list of a user's "contacts".
Users may have up to 10,000 contacts.
For now assume that all contacts are already in memory, and I'm simply trying to draw them. If you want to comment on the question of how wise it is to load 10k items of data in a browser, please do it here.
There are two techniques I've seen for managing a huge list like this inside a scrollable box.
Just Load Them All
This seems to be how gmail approaches displaying contacts. I currently have 2k contacts in gmail. If I click "all contacts", I get a short delay, then the scrollable box at the right begins to fill with contacts. It looks like they're breaking the task into chunks, probably separating the DOM additions into smaller steps and putting those steps into timeouts in order to not freeze the entire interface while the process completes.
pros:
Simple to implement
Uses native UI elements the way they were designed to be used
Google does it, it must be ok
cons
Not totally snappy -- there is some delay involved, even on my development machine running Firefox. There will probably be quite a lot of delay for a user running a slower machine running IE6
I don't know what sort of limits there are in how large I can allow the DOM to grow, but it seems to me there must be some limit to how many nodes I can add to it. How will an older browser on an older machine react if I ask it to hold 10k nodes in the DOM?
Draw As Needed
This seems to be how Yahoo deals with displaying contact lists. The create a scrollable box, put a super-tall, empty placeholder inside it, and draw contacts only when the user scrolls to reveal them.
pros:
DOM nodes are drawn only as needed, so there's very little delay while loading, and much less risk of overloading the browser with too many DOM nodes
cons:
Trickier to implement, and more opportunity for bugs. For example, if I scroll quickly in the yahoo mail contact manager as soon as the page loads, I'm able to get contacts to load on top of one another. Of course, bugs can be worked out, but obviously this approach will introduce more bugs.
There's still the potential to add a huge number of DOM nodes. If the user scrolls slowly through the entire list, every item will get drawn, and we'll still end up with an enormous DOM
Are there other approaches in common use for displaying a huge list? Any more pros or cons with each approach to add? Any experience/problems/success using either of these approaches?
I would chunk up the DOM-writing into handle-able amounts (say, 25 or 50), then draw the chunks on demand. I wouldn't worry about removing the old DOM elements until the amount drawn gets quite large.
I would divide the contacts into chunks, and keep a sort of view buffer alive that changes which chunks are written to the DOM as the user scrolls through the list. That way the total number of dom elements never rises above a certain threshold. Could be fairly tricky to implement, however.
Using this method you can also dynamically modify the size of chunks and the size of the buffer, depending on the browser's performance (dynamic performance optimization), which could help out quite a bit.
It's definitely non-trivial to implement, however.
The bug you see in Yahoo may be due to absolutely positioned elements: if you keep your CSS simple and avoid absolutely/relatively positioning your contact entries, it shouldn't happen.

Categories

Resources