查看: 187|回复: 0

RNOH性能调优:trace采集、关键标记与定界方法

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在RNOH(React Native for OpenHarmony)应用里做性能调优,第一步不是直接改代码,而是定界:确认问题发生在哪个线程、哪个渲染阶段、哪段trace时间窗。本文面向RNOH应用开发者,围绕线程模型与渲染链路、trace采集与查看、RNOH关键标记和常见定界误区展开。原文强调,“使用了RNOH”不等于“RNOH框架问题”,定界结论要能落到具体责任域。

一、线程模型与渲染链路
RNOH内部有四类线程,各自承担不同职责。关键通信方向是:JS→Main通过任务投递进入主线程事件循环;Main→JS通过消息队列投递到JS线程。trace中常见MAIN线程和两个JS线程实例。需要特别注意:RNOH_MAIN就是应用主线程,RNOH在其事件循环上注册回调,不创建新线程;trace中通常要结合应用主线程身份和RNOH调用栈确认,不能只按线程名匹配。RNOH_JS是独立线程,但线程名也只是线索,最终仍需用调用栈和时间关系确认。

RNOH的渲染流程继承React Native新架构,分为三个阶段:Render在JS线程执行,React执行业务代码创建React元素树,再通过JSI在C++中创建React影子树;Commit阶段由Yoga引擎做布局计算,并与上一次影子树对比,生成变更指令列表mutations;Mount阶段把mutations提交到主线程,转化为ArkUI组件树操作(CREATE/INSERT/UPDATE/REMOVE/DELETE),最终由ArkUI完成绘制和合成。mutations是Fabric对新旧影子树做diff后生成的变更指令列表,每条指令描述一个组件操作,例如创建tag=42的Text组件、更新tag=10的View属性、将tag=5插入到tag=3下。主线程逐条执行这些指令完成界面更新。

一次RN页面更新通常跨越多个环节,分析时要按时间顺序把JS线程、主线程和ArkUI/Render Service的活动串起来,不能只盯一个切片。原文给出点击跳转到1500个Text组件页面的trace实例,用于展示渲染三阶段和性能链路;实际定界时也要用这种跨线程时间线还原输入到上屏的过程。

二、先统一指标和测试条件
分析trace前要统一指标定义。帧预算由问题窗口内实际目标刷新率决定:单帧预算(ms)=1000/目标刷新率(Hz)。60 Hz、90 Hz、120 Hz对应约16.7 ms、11.1 ms、8.3 ms。设备可能动态切换刷新率,不能固定用16.7 ms,也不能仅用“FPS低于60”判断丢帧。应在DevEco Profiler中读取Display、H:PreferredFrameRate或等价信息,并结合App Frame、RS Frame判断。

响应时延描述输入事件到首个可见反馈之间的时间,数值与起止点选取直接相关。起点通常取点击事件上报时刻,而不是物理触屏时刻;终点通常取首个响应帧上屏。报告中必须记录所用工具和起止点定义。不同工具、不同版本对起止点取法可能不同,不能把RNOH内部的触摸trace直接当作端到端响应时延。

完成时延描述操作开始到目标页面达到工具所定义“完成状态”的时间。不同测试工具可能以页面切换后的目标帧、动画结束或占位内容加载完成作为终点,业务也可能把“关键内容可见”定义为完成。测试基线、问题复现和优化前后对比必须使用同一终点。RNOH的CONTENT_APPEARED表示根节点挂载到ArkUI内容容器(NodeContent);ROOT_VIEW_TTI计算为从APP_STARTUP_START到CONTENT_APPEARED的耗时。它们是RNOH内部阶段标记,不证明像素已经上屏、页面内容完整,也不证明页面已经可交互。HarmonyOS指标和工具限制以官方性能分析文档为准。

正式采集前要固定测试条件:使用release构建和release bundle,关闭Metro、HMR、Inspector和高频调试日志;固定设备型号、HarmonyOS版本、RNOH版本、刷新率策略、网络和测试数据;记录温度、是否充电、电量和电源模式;先预热,再重复相同操作至少5次;性能浮层只用于快速观察,正式测量时关闭浮层、录屏和其他可能改变负载的调试功能;同时保留基线数据与问题数据,避免只分析单次偶发trace。

三、trace采集与查看
RNOH在trace中留下的标记分两类:RNOHMarker是阶段级异步trace,适合分析“某个阶段花了多久”,如Bundle加载、启动;TraceSection是函数级同步trace,适合分析“哪个函数耗时”,如挂载、触摸分发。两类标记用途不同,不能混用。

两个编译宏默认关闭,需要手动开启:WITH_HITRACE_SYSTRACE和WITH_HITRACE_REACT_MARKER。注意开关要在CMake引入RNOH目录(add_subdirectory)之前设置,才能对RNOH源码生效。普通应用工程推荐在entry的CMakeLists.txt中设置:
  1. set(WITH_HITRACE_SYSTRACE ON)
  2. set(WITH_HITRACE_REACT_MARKER ON)
复制代码
不想改CMakeLists.txt时,可在build-profile.json5的externalNativeOptions.arguments中传递:
  1. "externalNativeOptions": {
  2.   "arguments": [
  3.     "-DWITH_HITRACE_SYSTRACE=ON",
  4.     "-DWITH_HITRACE_REACT_MARKER=ON"
  5.   ]
  6. }
复制代码
三方库/HAR场景可在第三方工程CMakeLists.txt中用add_compile_definitions:
  1. set(WITH_HITRACE_SYSTRACE 1)
  2. add_compile_definitions(WITH_HITRACE_SYSTRACE)
  3. set(WITH_HITRACE_REACT_MARKER 1)
  4. add_compile_definitions(WITH_HITRACE_REACT_MARKER)
复制代码

使用DevEco Profiler深度录制抓取trace的主要步骤:用release或debugOptimized构建模式安装应用并连接设备;打开DevEco Studio→Profiler,选择设备和进程;在新建任务区域选择场景模板并Create Session;在录制详情区域按需添加录制选项,在泳道区域调整录制功能,录制前指定泳道。对RNOH应用,建议泳道至少包含App Frame、RS Frame、应用主线程、RNOH_JS、Render Service。启动录制后等待状态由“initializing”变为“recording”,在设备上复现问题;录制中不能操作其他模板,需更换模板要结束本次录制重新创建会话。复现完成后停止,状态由“analyzing”变为“rendering”表示解析结束,右侧详情区域显示结果。数据量大时解析需要时间;若ArkTS Callstack、Callstack等泳道显示No Data,可将光标悬浮在泳道名称处三角告警图标查看原因。最后保存.htrace文件,便于查询和复核。更详细的命令行方式、采样配置、trace文件解析以及Snapshot、Allocation、ArkUI、Energy、ArkWeb、Network、Concurrency、GPU、CPU等场景模板,以HarmonyOS官方Deep Recording文档为准。

查看trace时可用这些技巧:搜索线程名RNOH_JS定位JS线程;搜索ReactMarker::定位启动、Bundle加载、Fabric提交等阶段起止;搜索#RNOH::定位具体函数调用区间,如挂载、触摸分发、TurboModule调用;先看App Frame和RS Frame中的红色异常帧,再缩放到该时间区间查看各线程活动;确认线程身份时,RNOH_MAIN不在trace中直接显示此名称,需通过应用主线程加#RNOH::TaskExecutor::runTask等TraceSection调用栈确认。

采集清单建议每个问题至少提供:复现步骤和问题时间点、应用包类型和版本信息、DevEco Profiler trace文件、App Frame/RS Frame/主线程/RNOH_JS泳道数据、操作录屏或截图、基线版本与问题版本对照数据。

四、ReactMarker与TraceSection的读法
ReactMarker的作用是监听RN应用生命周期中的关键事件并打点,覆盖从启动到渲染的完整时间线,可归纳为四类:启动初始化(运行时/实例/上下文创建、ArkUI模块注册);Bundle加载(下载、格式转换、分段注册、执行);页面内容显示(内容出现、Surface前后台切换);Fabric渲染(提交、布局、diff、挂载)。该类trace需要开启WITH_HITRACE_REACT_MARKER。

查看ReactMarker时要注意标记名与trace显示名的映射:标记大多成对出现,带_START/_STOP(或_END)后缀,例如RUN_JS_BUNDLE_START和RUN_JS_BUNDLE_STOP;成对的两个标记在trace中显示为同一个名称,如ReactMarker::RUN_JS_BUNDLE(部分工具显示为H:ReactMarker::RUN_JS_BUNDLE::Tag::),_START/_STOP后缀不体现在名称中,而是分别对应该异步trace时间条的开始和结束;带tag的标记会在名称后追加::Tag::;个别标记名与trace显示名不同,如JS_BUNDLE_STRING_CONVERT_START/STOP在trace中显示为ReactMarker::loadApplicationScript_StringConvert。完整56个ReactMarker标记定义见源码RNOH/Performance/RNOHMarker.h;其中部分标记(如INIT_JS_RUNTIME、TURBO_MODULE_SETUP)不会输出到trace,仅供Marker监听器(日志、性能指标等)使用。

TraceSection是函数级同步trace,在trace中显示为连续区间切片,可直接看函数执行时长。常用标记覆盖触摸与事件、挂载(Mount)、Scheduler(Fabric调度)、TaskExecutor(任务调度)、实例与通信等分组。完整的TraceSection字符串可通过在源码中搜索TraceSection s(或SystraceSection s(获取。

按时间轴分析一次点击响应时,单个切片只能说明某个环节的执行区间,要把多个切片串联还原从输入到上屏的完整过程。可以按以下间隔判断耗时集中点:如果onTouchEvent::DOWN到runOnQueue之间很长,倾向主线程调度或触摸分发慢;如果FABRIC_COMMIT到FABRIC_FINISH_TRANSACTION之间很长,倾向JS侧React render/layout/diff慢;如果FABRIC_BATCH_EXECUTION到didMount之间很长,倾向主线程挂载慢;如果didMount到首个响应帧上屏之间很长,倾向ArkUI布局/绘制或Render Service合成慢。

五、定界方法与常见错误
一次有效定界至少给出以下结论之一,明确责任域。“使用了RNOH”不等于“RNOH框架问题”。例如,大量业务组件一次性提交后,挂载耗时发生在RNOH主线程,但如果耗时随业务节点数增长且最小RNOH页面正常,通常应先归为RN业务负载或组件使用问题,而不是框架缺陷。定界前要确认WITH_HITRACE_REACT_MARKER和WITH_HITRACE_SYSTRACE已在构建配置中设置为ON,并按前述要求固定测试条件。

滑动卡顿丢帧要结合帧预算和异常帧分析,详细方法见滑动卡顿专题。响应时延按“输入锚点→首个响应帧上屏”分段测量,定位耗时最长的一段:输入→应用触摸入口慢,倾向系统输入分发/主线程调度;触摸分发完成→JS事件晚,倾向RNOH_JS排队或阻塞;JS提交→首个变化上屏晚,倾向挂载、ArkUI或RS;全程无任何视觉变化,先检查业务是否设计了即时反馈。完成时延要先定义“完成”终点,再分段定位责任方:数据/网络未就绪,倾向业务或服务侧;JS render/commit晚,倾向RN JS业务或三方组件;mutations已产生但挂载晚,倾向RNOH_MAIN、节点规模或同步阻塞;应用按时提交但上屏晚,倾向ArkUI/RS/系统侧;仅CONTENT_APPEARED早,不能据此判定页面已经完成。

常见错误包括:只看JS FPS/UI FPS就分责,浮层是采样指标,适合发现趋势,不足以证明一次异常的关键路径;只看一个超过帧预算的函数,它可能不在异常帧、可能运行在非关键线程,也可能被后续流水线吸收;应用和RS同时红就判系统问题,应用晚提交也会向RS传导,必须看最早异常点;RNOH调用栈长就判框架问题,需要结合输入规模、最小示例和版本对照;把CONTENT_APPEARED当完成时延终点,该标记早于实际上屏和业务内容完整;用debug数据和release基线比较,构建、日志、Inspector和bundle差异会破坏对照条件;把平均值当全部结论,平均FPS会掩盖最大连续丢帧,平均时延会掩盖P95/P99尖峰。

结语:RNOH性能定界的核心是把线程、渲染阶段、指标定义和trace标记对齐,再用时间轴还原一次操作的完整链路。先确认“慢在哪一段”,再讨论“为什么慢”和“怎么改”,比直接归因框架更可靠。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-21 10:52 , Processed in 0.022355 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部