【QClient】ReactNative应用自动化性能采集、分析和量化评估方案

背景

近几年React Native技术栈的普及增速快,但其生态尚处于早期阶段,在架构、性能质量、周边设施上仍有很多优化、填充和演进的空间。尤其在性能监控评估方面以往针对原生、web的方式方法在React Native上不适用,目前Qunar大客户端机票团队已经规模化使用React Native,在收获跨平台交付效率、快速迭代热发布能力的同时我们希望能规范化应用的性能水平,具备性能自动化监控评估的APM设施。

解决什么问题

回到这个方案的初衷,是要解决这几个方面的问题:

1.png

性能应用水难以量化并导致调优工作滞后

客户端怎么样算是性能好性能坏,在通常是没有一个明确的界定方式的,事实上客户端的性能调优工作多数是被动滞后,开发阶段大家用几个手机点一点觉得流畅就是流畅,但其他真实用户或是对体验有较高要求的群体确实会有不一样的感受结论。

RD对性能认知不足

即便生态发展迅速,React Native确实是一项非官方生态的新技术,这个生态所积累的深度学习资源和最佳实践经验不足够丰富,部分开发者对其性能方面的认知还不足。

怎么办 -- 设计目标与实现拆解

针对开发和项目过程痛点,我们期望的目标如下:

  • 项目性能评估客观可量化
  • 自动化侦测性能缺陷
  • 问题定位辅助决策

方案拆解思路:首先是找到针对React Native的性能相关性数据,也就是当性能出现下滑时,可以通过哪些维度的数据表现出来;然后有了数据样本需要进行记录;之后时对瞬时和一段周期内的样本进行自动化分析;最后时提供结果反馈。

2.png

解决方案

首先是性能相关性数据的实时采样模块,包括MRT(消息响应及时性)、GCP(绘图指令生效推迟)、逻辑同步帧率等。
其次是对样本的记录,记录模块目前支持两种记录模式,一种是存储在手机本地,一种是提供外放协议可以把数据投递到外部对接系统。
之后是实时分析,基于记录的各个维度数据进行缺陷侦测并生成预警。通过输出模块输出到开发者日志和可视化报表,这里我们后期有计划自动生成对应项目的性能bug对接到QA系统。

2.png

如何采集相关性数据、分析规则与调优策略

在行业缺乏相关方案的背景下,最难地方在于寻找React Native应用的性能相关性数据都是什么,在哪里,围绕RN的实现原理我们挖掘到了这些维度:

  • MRT(消息相响应及时性)
  • GCP(绘图指令延迟)
  • 无SCU优化、冗余render调用侦测
  • 绘图帧率与逻辑同步帧率
  • 关键线程CPU负载
  • 内存用量
  • 流量消耗
2.png

下面着重讲解几个代表性的性能相关性数据自动化采集分析和对应的调优策略

MRT(消息响应及时性)

抛开具体实现,React Native中Native域与JS域互操作的最简化模型如下,两边各有一个基于消息队列模型的线程,js侧这个线程就是javascript代码执行的线程,native侧是native_module_thread用来执行js测投递过来的NativeModule调用。两侧的互操作是基于jni向对方投递消息,不同于大多数原生开发的单域仅是内存地址对应的代码块,因为涉及到线程切换、反射、任务队列、双向异步,这个过程并没有那么及时,尤其涉及到视图频繁变更、手势事件传递这些场景下相对原生方案延迟还是蛮大的。

图片.png

MRT侦测、预警

我们的APM支持对这个指标进行实时采样,并针对异常峰值进行自动化预警反馈。这样RD在开发阶段可以及时感知到诸“如按钮点击了onPress没有调用“、“js函数执行了但没有在native上生效的“这些在过去比较隐蔽的性能缺陷。

图片.png

MRT优化策略

  • 减少native/js互操作频次,比如移到单域处理(比如Animation的useNativeDriver的设计符合这一原则)
  • 减少native_module_thread任务堆积。比如提高算法效率、利用多核CPU设计并行计算算法、使用异步来优化调用等待链
  • 减少js_thread上任务堆积。比如单线程模型上对大任务做拆解、优化调度顺序。
附React Native中Native与JS互操作原理图
图片.png

图片.png

侦测无SCU优化的组件和计算

SCU优化(shouldComponentUpdate optimization)是在reactjs/react native中经常强调的一个调优项。我们通过hook组件的componentDidUpdate对先后的props和state做deepdiff,根据结果分为深比较值不等、深比较仅函数不等、浅比较为开发者提供优化建议。在反馈报表中可以清晰感知到哪些组件发生了冗余的render以及优化收益预估。

图片.png

防止冗余render调用调优策略

对于使用Redux管理数据事件流的项目
  • store使用不可变数据结构
  • 根据组件需要的最小化依赖按需定制mapStateToProps
  • 使用PureComponent或redux connect、qrn-reduxPlugin赋予浅比较规则
  • 避免单个render函数/stateless function生成深度和广度较大的JSX Tree
对于使用MobX的项目

MobX的自动化依赖收集机制在数据变更后会定向更新最小粒度的组件,且observer组件的SCU函数已经被替换无需考虑SCU,非observer组件使用PureComponent并遵循性能编程规范即可。

渲染帧率与逻辑帧率

样本采集
图片.png

React Native的实际渲染执行和视图属性计算声明是彼此异步进行,以往针对原生应用的帧率监控指标在RN应用下会非常“好看”,几乎不可能出现ANR,极少会掉帧。但事实是js域的每次render执行并不是实时生效到实际界面上,js域上的视图数据计算和属性配置成为瓶颈。以安卓为例我们通过VSYNC特性在每两帧间检查是否发生JSInstance.onBatchCompleted视图操作事务提交以及是否期间完成了对BatchedOperation Queue的执行来判定native上每次渲染是否真的生效了来自js域提交的视图操作。

图片.png
对应的针对渲染帧率与逻辑帧率的自动化分析规则

持续性弱体验侦测

  • 渲染帧率或逻辑帧率连续n次连续掉帧
  • 过去5s内渲染帧率或逻辑帧率的P80分位数是否>30fps

潜在缺陷侦测:

  • 瞬时帧率异常侦测(渲染帧率和逻辑帧率)

执行过程限时超标侦测

通常在设计上我们会对一些模块的初始化、数据处理和计算的关键体验环节设定执行耗时的限制,通过构建AOP样式的decorator,对同步函数和基于Promise/async/await协程的异步函数进行trace并统计是否实际执行耗时不符合设计要求的环节。

@tracePerf({ expectedTimeCost: 200, strict: true })
async function invokeHeavyThingsXXX() {
    const result = await hotdog.invoke(...);
    await parallel.compute(result);
}

其他周边:CPU关键线程负载、内存用量、应用流量用量监测

关键线程(JS线程、native_module线程、UI线程)的持续性高负载侦测
内存用量:vm heap用量、native heap用量、低内存预警
流量:流量消耗飙升侦测

目前Profiler支持的自动化分析预警规则总结

图片.png

可视化输出反馈

开发者可以实时观测性能评估过程的各项指标表现,并从中收集反馈信息和优化建议指引,将性能缺陷的挖掘和调优前置到开发和测试阶段。


图片.png

适用范围、如何接入

适用于所有基于React Native及其衍生方案如QRN的应用
只需配置依赖,SDK化使用

图片.png

对APM未来的思考

  • 开放式架构:将流程、设计约定、基础功能和算法抽离为轻便的APM Core,把具体的sampler和profiler和output作为其上的插件实现进行剥离,各业务线团队和开发者根据自身需要定制、扩展性能维度和分析规则。
  • 功能延展:扩展Output模块和应用范围,对性能评级标准化并对接QA流程。
  • 自身性能优化:部分js代码移交到native去实现,降低APM本身对js域单线程的负载损耗。
图片.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容