找出性能问题

Xen*_*nor 5 react-native react-native-android

在过去的几天里,我一直在我创建的应用程序中解决 FlatList 的性能问题。

FlatList 由静态标题和 x 行组成。在测量的情况下,有 62 行,每行都由 4 个组件组成 - 其中一个使用了 4 次,总计为 7 个行单元格。此列表的每个单元格都是 TouchableNativeFeedback 或 TouchableOpacity(出于测试目的,那些附加() => null到 onPress。在几个级别(列表容器、行、单个单元格)上使用了 shouldComponentUpdate,我认为渲染性能对于这种列表来说已经足够好了。

对于我使用的一致测量initialNumToRender={data.length},因此整个列表一次呈现。列表是使用按钮呈现的,数据加载不是我测量的一部分 - 它被预加载到组件本地状态。

根据附加的 Chrome 性能配置文件 JS 线程需要 1.33 秒来呈现组件。我使用 CPU 减速 x6 来更准确地模拟 Android 设备。

然而,列表显示在设备上大约 15 秒的标记处,因此从按下按钮到列表显示的实际渲染需要超过 14 秒!

我想弄清楚的是 JS 渲染组件和实际显示在屏幕上的组件之间会发生什么,因为设备在那段时间没有响应。每个触摸事件都会被注册,但只有当列表最终出现在屏幕上时才会播放。

我已经附加了来自 chrome 开发工具的跟踪,使用 android systrace 工具获取的 systrace 和来自 android profiler 的屏幕(遗憾的是我找不到导出后者的选项)。

跟踪几乎同时运行 - 顺序是 systrace、android profiler、chrome dev tools。

我应该采取哪些步骤来帮助我了解应用程序冻结时发生的情况?

简单复现应用(src.js中的代码,第一次提交)

Chrome 性能配置文件 Chrome 性能配置文件

Systrace HTML Systrace HTML

安卓分析器 安卓分析器

Xen*_*nor 2

一段时间以来,我一直在尝试不同的事情,我什至正在考虑包装原生 Android RecyclerView,但公平地说,这似乎是一个很大的挑战,因为我之前没有使用原生 Android 代码的经验。

过去几天我尝试过的事情之一是使用react-native-largelist,但它并没有带来承诺的性能改进。公平地说,它可能比 还要慢FlatList,但我没有进行精确测量。

经过几天的谷歌搜索、编码和分析,我终于成功地得到了这篇 Medium 文章,它引用了recyclerlistview包,它似乎提供了比 FlatList 更好的体验。对于分析案例,渲染时间下降到 2 秒左右,其中 JS 线程工作时间为 300 毫秒。

必须注意的是,初始渲染的改进来自渲染项目数量的减少(在我的例子中为 11)。FlatList设置initialNumToRender={11}最初大约在同一时间渲染。

就我而言,初始渲染虽然仍然很重要,但并不是唯一重要的事情。FlatList对于较大的列表,性能下降主要是因为在滚动时它将所有呈现的行保留在内存中,同时recyclerlistview回收放入新数据的呈现的行。

重新渲染观察者性能提高的原因实际上很容易测试。我已添加console.logshouldComponentUpdate行组件中并计算了实际重新渲染的行数。对于我的行高和测试设备分辨率,recyclerlistview仅重新渲染 17 行,同时FlatList触发shouldComponentUpdate数据集中的每个项目。还值得注意的是,重新渲染的行数recyclerlistview并不依赖于数据集大小。

我的结论是,FlatList随着数据集的增大,性能可能会下降得更多,而recyclerlistview速度应该保持在相似的水平。

TouchableNativeFeedback里面recyclerlistview似乎也更具响应性,因为动画会立即启动,但我无法解释查看分析器的行为。

我的行组件肯定还有改进的空间,但目前我对整体列表渲染性能感到满意。

使用 recyclerlistview 的简单复制应用程序(src.js 中的代码,第二次提交)

Chrome 性能配置文件 (recyclerlistview) Chrome 性能配置文件 (recyclerlistview)

Systrace HTML(回收列表视图) Systrace HTML(回收列表视图)