本文由 简悦 SimpRead转码, 原文地址 www.callstack.com
了解如何通过遵循 DMAIC 流程和 monitor...... 使您的 React Native 应用程序在增长过程中保持高性能
以下文章是React Native 优化终极指南的一部分,介绍了 DMAIC 流程和 Reassure 等工具如何帮助您的应用程序长期保持高性能。
为什么这很重要?
您希望您的 React Native 应用程序始终性能良好、运行快速,以保持最佳的用户体验。除非您将性能回归监控作为应用程序开发和维护流程的一部分,否则这是不可能实现的。在本文中,我们将介绍 DMAIC 流程如何帮助您的 React Native 团队持续改进应用程序性能。我们还将介绍您可以使用哪些工具(主要是 Reassure)来确保您的应用程序在成长过程中保持高性能。
在基于《React Native 优化终极指南》的其他博文中,我们涉及了以下与稳定性相关的主题:
- 持续集成(CI)在改进 React Native 应用程序中的应用
- 空中下载(OTA)更新
- 利用持续部署快速发货
- 为应用程序的关键部分运行测试
- 使用 iOS 和 Android 工具剖析 React Native 应用程序
为什么要不断提高应用程序性能?
客户对缓慢的应用程序几乎没有耐心。根据 Unbounce 报告,近 70% 的消费者承认页面速度会影响他们的购买意愿。沃尔玛和亚马逊就是很好的例子,这两家公司都注意到,加载时间每提高 100 毫秒,收入就会增加 1%。
性能对您的业务目标有着明显的影响,但通常情况是,在解决了一个性能问题后,应用程序迟早会再次变慢。这种情况会给企业带来损失,因此您不仅需要修复性能问题,还要确保它们不会再次发生。
使用 DMAIC 流程持续改进 React Native 应用程序性能
您希望您的 React Native 应用程序在任何时候都能性能良好、运行快速,但如何实现这一目标呢?从技术角度来看,这可以归结为避免臆测和做出基于数据的决策。我们还应该记住,提高性能是一个过程;不可能一下子解决所有问题,但小步骤可以带来大效果。
开发应用程序是一个过程,性能改进也是如此。但最重要的是,每个过程都可以优化。在改善 React Native 应用程序性能和性能回归监控方面,最有效的方法之一就是遵循 DMAIC 方法。该方法以数据为导向,结构合理,包括以下步骤:定义、测量、分析、改进和控制。让我们看看如何在应用程序中应用每个阶段。
定义
在 DMAIC 流程的这一阶段,我们应重点定义问题、我们想要实现的目标、改进机会等。在这一阶段,倾听客户的期望和反馈至关重要,因为这有助于更好地了解他们的需求、偏好和问题。
接下来,以某种方式进行衡量非常重要。比方说,客户希望快速结账。在分析了各个组成部分后,我们知道要实现这一目标,我们需要一个快速的结账流程、较短的等待时间以及流畅的动画和过渡。所有这些要点都可以分解为可衡量的 CTQ(质量关键点)。例如,较短的等待时间可以分解为快速的服务器响应和较少的服务器错误。另一个方便的工具是分析常见的用户路径。通过良好的跟踪,我们可以了解用户主要使用应用程序的哪些部分。
选择优先级和确定优化顺序是这一阶段的。任何确定优先级的工具和技术都会对这一阶段有所帮助。如果你想高效地提高应用程序性能,那么在这一阶段,设定可衡量的目标并将其纳入项目范围应该是你的首选。
衡量
既然我们已经知道了方向,那么就该评估起点了。收集尽可能多的数据以了解问题的实际情况 。我们需要确保测量过程的精确性。制定数据收集计划并让开发团队参与进来,对建立衡量标准确实很有帮助。然后,是时候进行剖析了。
在 React Native 中进行剖析时,主要问题是在 JavaScript 还是本机端进行剖析。这在很大程度上取决于应用程序的架构,但大多数情况下,都是两者兼顾。最受欢迎的工具之一是React Profiler,它允许我们封装一个组件,以测量渲染时间和渲染次数。它非常有用,因为许多性能问题都来自不必要的重渲染。
在此了解如何使用它:
import React, { Profiler } from "react";
import { View } from "react-native";
const Component = () => (
<Profiler id="Component" onRender={(...args) => console.log(args)}>
<View />
</Profiler>
);
export default Component;
它将输出数据:
{
id: "Component",
phase: "mount",
actualDuration: 1.3352311453,
baseDuration: 0.95232323318,
...
}
第二个工具是 Shopify 创建的一个库,名为 React Native Performance。它允许您在代码中放置一些标记并测量执行时间。此外,还有一个相当不错的 Flipper 插件,有助于将输出结果可视化:
来源: shopify.github.io/react-nativ…
说到 Flipper,它还有一些插件可以帮助我们测量应用程序性能并加快开发进程。我们可以使用React Native Performance Monitor Plugin获得类似灯塔的体验,或者使用React Native Performance Lists Profiler Plugin。
在原生方面,最常用的方法是使用原生集成开发环境: Xcode 和 Android Studio。有很多有用的见解可以进行分析,并得出一些结论和结果。
测量阶段最重要的方面是测量差异。即使应用程序在同一设备上运行,一些外部因素也可能影响性能测量。这就是为什么我们应该以发布版本为基础进行所有测量。
分析
DMAIC 流程的这一阶段旨在找到问题的根本原因。最好先列出可能导致问题的原因。在这里,与团队一起进行头脑风暴可能会有所帮助。
定义问题最常用的工具之一是因果图。它看起来像一条鱼,我们应该从右向左画。我们从包含问题陈述的头部开始(在定义阶段,我们应该已经有了问题陈述)。然后,我们找出问题的所有潜在主要原因,并将它们分配到鱼骨上。接下来,我们将所有可能的原因分配给每个主要原因。由于影响应用程序性能的原因有很多,因此缩小列表范围非常重要。尽量概括并关注最重要的因素。
最后,是测试假设的时候了。例如,如果主要问题是 FPS 较低,而潜在的主要原因与列表渲染有关,那么我们可以考虑在列表项中的图片方面进行一些改进。我们需要设计一个测试来帮助我们接受或拒绝假设--它可能是某种概念证明。接下来,我们要对结果进行解释,并评估它是否改善了 React Native 应用程序的性能。然后,我们做出最终决定。
因果图示例
改进
既然我们已经知道了目标和实现目标的方法,是时候真正提高应用程序的性能了。在开始之前,最好再召开一次头脑风暴会议,找出潜在的解决方案。根据根本原因,可能会有很多解决方案。基于上一个例子中的图片列表项,我们可以考虑实施适当的图片缓存并减少不必要的渲染。
列出解决方案后,就该选择最佳解决方案了。有时,效果最好的解决方案可能成本极高,例如,当它涉及到架构更改时。一旦实施了解决方案,不要忘记对其进行适当的测试!
控制
DMAIC 流程的最后一步是控制阶段。我们现在需要确保一切运行良好。大家现在都知道,如果不加以控制,应用程序的性能就会下降。人们往往会将其归咎于设备、技术甚至用户,但事实并非如此简单。那么,我们需要做些什么来保持 React Native 应用程序的高性能呢?
我们需要确保有一个控制计划。我们可以利用之前阶段的一些工作来制定该计划。我们应该指出重点、一些测量特征、指标的可接受范围以及测试频率。此外,写下一些程序以及发现问题时应采取的措施也是一种很好的做法。
性能回归监控是开发过程的一部分
控制阶段最重要的方面是监控回归。直到最近,在 React Native 中还很难有效地做到这一点,但现在我们有很多方法来改进我们的监控。
跟踪我们在应用程序中引入的性能改进的一种方法是实时监控工具,如 Firebase Performance Monitoring 或 Sentry Performance Monitoring。
另一种实现性能回归监控的方法是自动测试,我们将对此进行更详细的探讨。在各种设备上进行剖析、测量和运行是一项手动且耗时的工作,开发人员都避免这样做。然而,这很容易在无意中引入性能回归,而这些回归只会在质量保证过程中被发现,甚至被用户发现。值得庆幸的是,我们可以使用Reassure在 JavaScript 中为 React 和 React Native 编写自动化性能回归测试。
Reassure 允许您在 CI 或本地机器上自动执行 React Native 应用程序性能回归测试。就像你编写的集成和单元测试能自动验证你的应用程序是否仍在正常运行一样,你也可以编写性能测试来验证你的应用程序是否仍有性能。你可以把它看作 React 性能测试库。事实上,Reassure 是由维护者和创建者设计的,旨在尽可能多地重用 React 原生测试库 的测试和设置。
它的工作原理是测量您提供的测试场景的某些特性(渲染持续时间和渲染次数),并将其与之前测量的稳定版本进行比较。它会多次重复测试场景,以减少运行环境对渲染时间随机变化的影响。然后,它将进行统计分析,以确定代码更改是否具有统计意义。最后,它会生成一份人类可读的报告,对结果进行总结,并将其显示在 CI 上或作为拉取请求的注释。
最简单的测试可以这样写
import React from "react";
import { View } from "react-native";
import { measurePerformance } from "reassure";
const Component = () => {
return <View />;
};
test("mounts Component", async () => {
await measurePerformance(<Component />);
});
该测试将测量安装过程中 Component 的呈现时间以及由此产生的同步效果。让我们来看一个更复杂的示例。这里我们有一个包含计数器和慢速列表组件的组件:
import React from "react";
import { Pressable, Text, View } from "react-native";
import { SlowList } from "./SlowList";
const AsyncComponent = () => {
const [count, setCount] = React.useState(0);
const handlePress = () => {
setTimeout(() => setCount((c) => c + 1), 10);
};
return (
<View>
<Pressable accessibilityRole="button" onPress={handlePress}>
<Text>Action</Text>
</Pressable>
<Text>Count: {count}</Text>
<SlowList count={200} />
</View>
);
};
性能测试如下:
import React from "react";
import { screen, fireEvent } from "@testing-library/react-native";
import { measurePerformance } from "reassure";
import { AsyncComponent } from "../AsyncComponent";
test("AsyncComponent", async () => {
const scenario = async () => {
const button = screen.getByText("Action");
fireEvent.press(button);
await screen.findByText("Count: 1");
fireEvent.press(button);
await screen.findByText("Count: 2");
fireEvent.press(button);
fireEvent.press(button);
fireEvent.press(button);
await screen.findByText("Count: 5");
};
await measurePerformance(<AsyncComponent />, { scenario });
});
通过 CLI 运行时,Reassure 将生成性能比较报告。需要注意的是,要获得不同的测量结果,我们需要运行两次。第一次使用 --baseline 标志,在 .reassure/ 目录下收集测量结果。
运行该命令后,我们就可以开始优化代码,查看它对组件性能的影响。通常情况下,我们会保留基线测量值,等待 Reassure 捕捉并报告性能下降情况。在这种情况下,我们将跳过这一步,直接开始优化,因为我们刚刚发现了这样做的可能性。由于我们有基线测量结果作为参考,因此可以验证我们的假设,以及改善是客观的还是主观的。
我们注意到的可能性是,<SlowList/> 组件可以备忘录化,因为它不依赖于任何外部变量。在这种情况下,我们可以利用 useMemo:
const slowList = useMemo(() => <SlowList count={200} />, []);
完成后,我们可以再次运行 Reassure。现在不使用 --baseline 标志了。
现在,Reassure 有两个测试运行可以比较--当前测试运行和基线测试运行--它可以准备一份性能比较报告。正如你所注意到的,由于对 AsyncComponent 渲染的 SlowList 组件应用了 memoization,渲染持续时间从 78.4 ms 降至 26.3 ms,性能提高了大约 66%。
测试结果归入以下类别
- 渲染持续时间的显著变化 显示的是一种测试场景,其中的变化在统计上是显著的,应该加以研究,因为它标志着潜在的性能损失/提高。
- 渲染持续时间的无意义变化 显示的是统计意义上变化不大的测试场景。
- 渲染次数变化 显示渲染次数发生变化的测试场景。
- 添加的场景 显示基线测量中不存在的测试场景。
- 删除场景显示当前测量中不存在的测试场景。
当与 Danger JS 连接时,Reassure 可以将此报告输出为 GitHub 注释,这有助于在代码审查时捕捉回归。
您可以在文档中找到更多用例和示例。
让您的应用程序始终保持快速运行
在开发应用程序时,无论其规模大小,都必须有明确的路径来实现我们的目标。在优化 React Native 应用程序时使用 DMAIC 方法的主要好处是,它是一种结构化的直接方法。有时,我们的经验和直觉就足够了。但事实并非总是如此。
将这样的流程作为 React Native 开发的一部分,可以让我们专注于解决问题,不断提高工作效率。**由于采用了 DMAIC 方法,性能优化已成为正常开发工作流程的一部分。**它使您的 React Native 应用程序更接近于默认性能,并能在用户遇到性能问题之前就发现它们。
没有软件是完美无缺的。即使您是团队中经验最丰富的开发人员,也会出现 Bug 和性能问题。但我们可以通过使用 Sentry、Firebase 或 Reassure 等自动化工具来降低这些风险。在您的项目中使用它们,享受它们为您的项目带来的额外信心,以及它们为您的用户带来的更好的用户体验。
如果您正在寻找技术合作伙伴,帮助您在深思熟虑的过程中提高应用程序的性能,请 联系我们。