记一次rax应用用户体验性能优化

2024-02-01 11:20

本文主要是介绍记一次rax应用用户体验性能优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言


对于前端开发攻城狮们来说,性能优化是一个永恒的话题。随着前端需求复杂度的不断升高,在项目中想始终保持着良好的性能也逐渐成为了一个有挑战的事情。本次分享简述我们在 Rax 项目中常用的一些性能优化方式,并将从近期的一个实际业务需求出发,讲述我在 Rax C端应用场景下所遇到性能问题排查时的心路历程。
本次分享的优化内容,主要是指用户滑动屏幕浏览页面过程中所花费的单帧渲染耗时的降低比例。 单帧渲染耗时通过 chrome dev tools 插件以及手淘端app dev tools测得。一般来说浏览器运行帧率为 60hz,因此对于帧率要求非常高的场景如内容输入后的响应、动画等,需要尽可能的将单帧耗时控制在 16.6ms(1s / 60)以内,用户才能完全感知不到系统的卡顿。对于一般性能要求没那么高的应用场景,单帧耗时能达到33.2ms(2s / 60),也能达到一个相对流畅的用户体验。
实际业务现状
接下来我将从近期参与的一个实际业务需求出发,记录下我在这个项目中遇到性能问题时,发现问题、解决问题的心路历程。
从实际业务场景出发,我们发现不少页面在用户滑动浏览页面的过程中存在卡顿,一些情况下卡顿严重,非常影响用户体验,由于多数安卓机的渲染性能不如IOS系统,安卓端的性能问题会尤其明显

那么如何优化这个性能问题?

在 Rax当前的版本中,rax框架使用同步渲染模式(Synchronous Rendering),也就是说,在处理更新时会阻塞整个 UI 线程,直到所有更新完成才会重新渲染视图。这种方式虽然简单易懂,但是在处理大量或复杂数据时存在明显的性能问题,导致应用程序出现卡顿或者无响应等问题。

React18的并发模式(Concurrent Mode),它可以将渲染任务分解成多个小块,并通过 React 的调度器(Scheduler)来优化执行顺序和时间,从而降低了单次渲染所需的计算资源和时间。并发模式可以在渲染过程中及时响应用户的输入和请求,避免出现 UI 卡顿或者无响应的情况,从而提高了整个应用的用户体验。

目前Rax框架在性能优化上虽然不及react18,但仍然有非常好的应用渲染性能基础,站在了巨人的肩膀上,我们所能做的,便是在不添乱的前提下,帮助Rax更快、更高效的完成遍历渲染的过程,使更新链路尽可能的短的走完

排查流程

通过安卓手淘扫码观察app dev tools的性能分析,每帧普遍在 700ms以上,最严重的长达 1847ms

观察发现最耗时的任务为一个叫appear的函数执行,appear函数出现在trackerLink组件中,是曝光方法,也就是说,每当一个标签需要进行曝光,那么当这个元素出现在浏览器视口,就会触发此appear方法,随着一次又一次的需求迭代,需要曝光的点越来越多,导致每一次元素重新出现在适口,都会有大量的appear方法调用,消耗了大量的性能,在安卓系统性能不够优秀的机型上,用户体验表现就会卡顿。

当我们滑动页面时,由于大量元素需要进行曝光操作,appear函数长时间执行,对于用户来讲,这段时间界面是卡死且无法交互的。

如果我们把这个例子中的appear函数类比成Rax的更新过程:即setState触发了一次更新,而这次更新耗时非常久,比如1800ms。那么在这1800ms的时间内界面是卡死的,用户无法进行交互,非常影响用户的使用体验。

优化思路

雪中送炭

擒贼先擒王,首先解决最影响性能的,怎么让appear方法的执行不影响主线程的渲染?

1.接入react18?

成本太高。pass

2.使用requestIdleCallback来控制appear方法的执行不影响主线程?

requestIdleCallback 会将任务安排在浏览器的空闲时期执行。在当前页面的生命周期内,也不能保证 requestIdleCallback 中的任务一定会执行。如果浏览器长时间忙于处理高优先级任务,低优先级的空闲回调可能会被推迟,直到有足够的空闲时间来执行它们。如果这种情况一直持续,那么这些任务可能会被无限期地推迟。pass

3.如果任务是关键性的,需要在特定时间内一定要执行,那么使用 setTimeout可能是更好的选择。setTimeout这个API提供了更可靠的方式来计划任务的执行,即使它们没有 requestIdleCallback 提供的执行时机那样灵活。

setTimeout将同步任务变为异步任务,当需要trackertLink组件需要曝光时,将曝光函数异步执行,不阻塞影响主线程渲染,提高用户体验性。

改动TrackerLink组件:

// needAsyncSending控制埋点曝光异步进行,不阻塞主线程
if (needAsyncSending) {const sendExpTimer = setTimeout(() => {recordExp();clearTimeout(sendExpTimer);}, 0)
} else {recordExp();
}

优化后:

我们可以看到,当trakcerLink组件异步调用曝光方法时,每帧渲染时间大幅缩减,效果明显,每帧最糟糕的情况从1800ms降低至每帧最糟糕的情况200ms左右,

锦上添花

通过异步发送曝光埋点解决了最大头的性能问题,用户滑动页面时已经不会有明显的延时和滑不动,但是任然有部分顿挫感,由于无法使用react app dev tools工具观察组件的渲染情况,我们使用console.log来判断哪些组件一直在重新渲染,发现在滚动过程中,航班报价列表和报价卡片一直在重新渲染,

但是业务场景下,此种渲染是不必要的,当没有重新发起请求时,是不需要一直重新渲染ota报价卡片

避免 State 的不必要更新

一些业务场景下,不需要一直更新setState,找到不必要的setState,避免这些更新

防止父组件重新渲染重新声明方法导致子组件不必要的重新渲染

纯函数组件使用 Memo 包裹,纯函数组件的function类型的prop使用useCallback包裹

 ===========>>>>>

最终优化效果:

可以看到最终性能分析得到的数据没有明显卡顿的地方,很多帧也达到了16.7ms的理想状态

这篇关于记一次rax应用用户体验性能优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/667126

相关文章

Java实现复杂查询优化的7个技巧小结

《Java实现复杂查询优化的7个技巧小结》在Java项目中,复杂查询是开发者面临的“硬骨头”,本文将通过7个实战技巧,结合代码示例和性能对比,手把手教你如何让复杂查询变得优雅,大家可以根据需求进行选择... 目录一、复杂查询的痛点:为何你的代码“又臭又长”1.1冗余变量与中间状态1.2重复查询与性能陷阱1.

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

PostgreSQL简介及实战应用

《PostgreSQL简介及实战应用》PostgreSQL是一种功能强大的开源关系型数据库管理系统,以其稳定性、高性能、扩展性和复杂查询能力在众多项目中得到广泛应用,本文将从基础概念讲起,逐步深入到高... 目录前言1. PostgreSQL基础1.1 PostgreSQL简介1.2 基础语法1.3 数据库

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

Python中yield的用法和实际应用示例

《Python中yield的用法和实际应用示例》在Python中,yield关键字主要用于生成器函数(generatorfunctions)中,其目的是使函数能够像迭代器一样工作,即可以被遍历,但不会... 目录python中yield的用法详解一、引言二、yield的基本用法1、yield与生成器2、yi

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

MySQL中优化CPU使用的详细指南

《MySQL中优化CPU使用的详细指南》优化MySQL的CPU使用可以显著提高数据库的性能和响应时间,本文为大家整理了一些优化CPU使用的方法,大家可以根据需要进行选择... 目录一、优化查询和索引1.1 优化查询语句1.2 创建和优化索引1.3 避免全表扫描二、调整mysql配置参数2.1 调整线程数2.

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式