0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

HarmonyOS应用高负载场景分帧渲染

HarmonyOS开发者 来源:HarmonyOS开发者 2025-03-25 10:28 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

概述

在应用开发中,当页面内的列表结构较为复杂且每个列表项包含的组件较多时,容易导致嵌套层级过深,进而增加组件的负载,延长绘制时间。在转场或列表滑动时,列表项可能会一次性加载大量数据,导致性能问题。此时,可以采用分帧渲染技术,将原本在一帧内加载的数据分散到多帧中逐步加载,从而减轻单帧的渲染压力。不过,分帧渲染需要开发者精确计算每帧加载的数据量,操作较为复杂,因此建议仅在性能瓶颈明显且必要时使用。

实现原理

(一)原理说明

在单帧内绘制多个特性各不相同的组件时,会同时创建大量的GraphicsPipelines,导致后续整个Flush阶段的耗时增加,从而使得单帧渲染时间过长。针对这种单帧内组件负载重、数据量大、绘制耗时长的问题,开发者可以根据实际的业务逻辑、页面布局和数据量,提前规划需要通过多少帧完成加载,通过帧回调监听来动态修改状态变量或向数据结构中补充数据,计算和设置每一帧需要处理的渲染数据,确保每一帧只处理预设的数据量。由于已经设置了帧回调监听,页面组件在加载数据时,只需通过状态变量或数据结构即可实现按帧分批加载数据。这种方式将原本需要在一帧内加载的数据分散到多帧中处理,有效减少了首帧的渲染压力,避免了首帧卡顿现象的发生。如下图所示,将一帧数据拆分到三帧示例:

7a42d3fe-0574-11f0-9310-92fbcf53809c.png

(二)具体实现

在高负载场景下使用分帧渲染的关键操作是把数据拆分到每一帧中加载,但这个过程中加载新的数据时可能会将已有数据再次绘制,因此需要搭配合理的页面布局来避免重绘。可以通过if或ForEach两种方法来实现布局,两种方法的更新机制如下:

if更新机制是根据状态判断条件,如果分支没有变化,不会对条件渲染语句进行更新。

ForEach非首次渲染会检查新生成的键值是否在上次渲染中已经存在。如果键值不存在,则会创建一个新的组件;如果键值存在,则不会创建新的组件,而是直接渲染该键值所对应的组件。

因此在分帧逐步加载数据时使用上述两种方法不会引起重绘。并且在页面布局时可以给分帧渲染的外部容器组件设置宽高,这样组件本身不会触发重新进行Measure的过程,对组件的宽高不会重新测算,避免因外部容器大小改变引起重绘,详情可参考合理使用布局。

保证页面不会重绘后,在实际开发过程中为了逐步增加页面数据,可以使用ArkTS中提供的displaySync(可变帧率)API接口,通过Vsync信号控制数据刷新的时机,来实现绘制内容帧率的控制。先通过页面UI中aboutToAppear()添加帧回调监听并开启监听,Vsync信号变化时触发帧回调执行应用逻辑,计算每帧加载的数据,改变ViewModel数据。ViewModel数据改变后驱动页面或组件执行build(),使用if或ForEach分帧迭代渲染绘制UI并控制刷新范围。最后可以在aboutToDisappear()里停止帧回调监听。

具体操作流程如下图:

7a4fcffa-0574-11f0-9310-92fbcf53809c.png

转场场景

由于业务需求,从当前页面进入一个新页面时,会有转场动画播放,并且在动画首帧中加载新页面所需要的数据。如果数据量较多,那么动画首帧的响应时延就会变长,导致后面动画帧延迟播放的情况。从一个页面到新页面转场流程图如下:

7a5c6256-0574-11f0-9310-92fbcf53809c.png

(一)解决思路

既然转场时一次性加载大量的数据会导致卡顿情况,那么采用分帧渲染将数据拆分成多份并分批次进行加载就是一种解决思路。

转场场景分帧:转场时会在动画首帧加载新页面的数据,采用分帧策略就是将首帧加载的数据拆分,将数据拆分到后面的帧加载,新页面打开后List列表只展示两个列表项,因此在首帧加载显示两条数据,其余缓存数据可以在第二帧加载。该方法的优点是减少动画首帧的响应时间,缺点是转场动画完成时延变长。

转场场景效果图如下:

7a6e2c20-0574-11f0-9310-92fbcf53809c.gif

在分帧前会在转场动画的首帧将层叠组件和列表可见区域与缓存区域的数据全部加载,而分帧后在首帧加载层叠组件和列表前两项的数据,在第二帧加载缓存区域的列表数据。分帧前后示意图如下:

7a860c46-0574-11f0-9310-92fbcf53809c.png

(二)常规情况

在组件即将出现时回调aboutToAppear()接口,将数据放入productData中,并通过瀑布流加载。编译运行后,可以通过Trace图看到,转场动画的首帧耗时21ms左右,这是因为在点击进入页面时将数据全部放入瀑布流,在235970帧中需要计算每个子组件的尺寸,导致了响应时间增长。

7a929c5e-0574-11f0-9310-92fbcf53809c.png

(三)优化方案

在aboutToAppear()接口中添加displaySync的帧回调,并将数据拆分进行加载。此时,aboutToAppear()接口中并没有一次性加载全部数据,而是将数据拆分,在帧回调中分成2次进行加载,编译运行后,通过Trace图可以看到,动画首帧的耗时是12ms。相较于优化前的代码,不再是首帧占据大量的时间,而是将耗时分摊到了后面的动画帧中。当数据量更大时,可以将数据进行更多次拆分,将不会直接出现在屏幕上的数据放到第二帧或者第三帧中进行加载,降低首帧的响应时延。

7aabc9e0-0574-11f0-9310-92fbcf53809c.png

对使用分帧前后进行分析,得到的数据如下表所示:

使用分帧 使用分帧前 使用分帧后
首帧耗时 21ms 12ms
第二帧耗时 4ms 13ms

在使用分帧后动画首帧与第二帧分别是12ms和13ms,如果依然没有达到期望的帧率,可以继续将数据拆分。

滑动场景

在日历应用中,需要在一个List里面加载每个月的全部天数,包括公历和农历日期,这样在一个ItemView复用组件中就会有很多数据加载,当列表滑动的时候,通过组件复用的aboutToReuse()接口设置新的数据,就会导致ItemView内所有组件一起刷新,可能会引起掉帧卡顿现象。

(一)解决思路

由于一次性加载大量数据、刷新大量组件会导致卡顿丢帧,那么减少一次性加载的数据量就是一种解决方法。但是由于业务需求,需要加载的数据总量和绘制的组件数量是不能减少的,那么就可以考虑采用分帧渲染。

滑动场景分帧:滑动日历列表,复用ItemView组件,更新每月天数包含阴历和阳历,一次更新所有天数,数据量大,可以使用分帧策略,将每月日期数据进行拆分,一帧只更新5天数据,在使用ForEach循环每月的天数时,因为一次只更新5天数据,ForEach会根据key值更新对应的天数,从而避免在一帧中更新所有数据。该方法优点是可以将数据拆分在多帧中加载,缺点是操作比较麻烦,需要开发者根据实际情况计算一帧中加载的数据量,维护较为复杂。

滑动场景效果图如下:

7abfcc60-0574-11f0-9310-92fbcf53809c.gif

分帧前后示意图如下:

7aeee6d0-0574-11f0-9310-92fbcf53809c.png

(二)‍常规情况

通常情况下,会在aboutToReuse()中设置新的数据,并一次性绘制所有的组件。通过组件复用,在ItemView的aboutToReuse()接口中,将一个月的数据直接设置到状态变量monthItem中,这样下面的Flex就会收到状态变量变更的消息通知,从而刷新组件中的数据。编译运行后,进入日历页面,然后滑动列表到最底端,分析下图。

7afb0186-0574-11f0-9310-92fbcf53809c.png

选中Actual Timeline(render_service)标签中的146272后,可以通过箭头看到它所关联到的位置是Actual Timeline(example.display)标签中的209136和209137,即RenderService层出现的异常情况是由应用层中前面两帧里面的操作引起的。

通过箭头2的标签可以看到,在209135中调用了aboutToReuse接口,此时系统开始了组件复用的绘制操作,在aboutToReuse接口将一个月的所有数据全部放入了当前被复用的组件中,并更新了所有用于显示日期的Text组件中的数据(箭头3,diffIndexArray.lenght:35,表示有35个不同的元素),这就导致209136需要计算35个子组件的尺寸(箭头1),从而引起146272的绘制时间延长。

在列表数据量较少时,其实并不会引起掉帧现象,因为每次延长帧的时间都很短,对帧率的影响较小,但是在列表数据较多时,就会因为延长帧过多,发生掉帧现象。

(三)优化方案

通过displaySync中的帧回调方法,将数据拆分到每一帧中进行加载和绘制,只需要在帧回调中修改自定义子组件ItemView中加载数据的方式。

首先,需要在ItemView中第一次使用时创建displaySync对象,设置期望帧率,添加帧回调的监听,然后进行启动。

然后,在监听中添加更新数据的代码。这里将每个月的数据更新拆分开来,第一步用来更新月份数据和计算总的执行步骤,最后一步将计数数据清空, 方便下一次数据的写入,其余需要执行步骤的多少根据每次加载数据量会有所改变。

最后,在aboutToReuse接口中将数据放入数组中,用于帧回调中开始执行数据更新。

分析下面trace图,在211618中,开始调用aboutToReuse接口,由于只是将数据放入一个temp数组中,并没有更新复用组件中的数据,所以这一帧并没有发生延长现象。

在211619中开始逐步更新复用组件中的数据,在第一帧中更新月份和周的数据,但是由于前一帧(211618)中并没有更新当前复用组件中的数据,所以在211619中并不需要绘制组件,所以此帧耗时依旧很短。

结合代码可以看到,在211620中放入了5天的日期数据,由于前一帧(211619)只是设置了2条数据,并且只有1条会更新,所以这一帧的绘制时间也不会超时。

7b1368d4-0574-11f0-9310-92fbcf53809c.png

和前一帧(211620)一样,此帧(211621)中更新了5天的日期数据,并且会重新测量上一帧中更新数据的5个Text组件尺寸(箭头1),而其余的组件由于数据并没有变动,所以测量被略过了(箭头2)。

后面的帧是类似的,每次只会放入5天的数据,并且更新上一帧中设置的数据所关联的Text组件。由于每次更新的组件数量较少,每帧基本上都能在规定的时间内(1秒120帧,即8ms一帧)绘制完成,所以延长帧就会较少。这样不论列表中数据多还是少,都不会引起掉帧现象的发生。

7b22d58a-0574-11f0-9310-92fbcf53809c.png

对使用分帧前后进行分析,得到的数据如下表所示:

使用分帧 使用分帧前 使用分帧后
渲染帧率 113fps 120fps
丢帧率 5.8% 0%

在使用displaySync时不建议将ExpectedFrameRateRange中的expected、min、max都设置为120,否则会干扰系统的可变帧率机制运行,产生不必要的负载,进而影响到整机的性能和功耗,详情请参考场景策略建议。

总结

通过上述示例代码和优化过程可以看出,在列表中使用组件复用时,如果一次性加载所有数据,可能会导致掉帧问题。虽然在数据量较少时,单帧绘制时间的延长不会明显影响性能,但随着数据量增加,这种单帧耗时的增加会变得显著,进而引发掉帧。因此,开发者可以根据实际业务需求,合理采用分帧策略对数据进行拆分,将原本集中在一帧内处理的任务分散到多帧中执行。这种方式可以有效减少单帧的渲染压力,降低延长帧的发生概率,从而避免因掉帧导致的性能问题。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 渲染
    +关注

    关注

    0

    文章

    76

    浏览量

    11201
  • 高负载
    +关注

    关注

    0

    文章

    5

    浏览量

    6045
  • 应用开发
    +关注

    关注

    0

    文章

    63

    浏览量

    9773

原文标题:HarmonyOS应用高负载场景分帧渲染

文章出处:【微信号:HarmonyOS_Dev,微信公众号:HarmonyOS开发者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何评价光栅化渲染中光线在场景中的折返?

    对于那些想要获得现实感的艺术家或开发人员而言,一款可以模拟光在场景中发生相互作用(即光反射、光吸收、光折射等)的渲染器(具有创建视觉效果的功能)十重要。这就需要在处理每个像素时,对场景
    发表于 05-22 10:17 2637次阅读

    HarmonyOS实战开发-合理选择条件渲染和显隐控制

    开发者可以通过条件渲染或显隐控制两种方式来实现组件在显示和隐藏间的切换。本文从两者原理机制的区别出发,对二者适用场景分别进行说明,实现相应适用场景的示例并给出性能对比数据。 原理机制 条件渲染
    发表于 05-10 15:16

    HarmonyOS卡片开发-JS/JAVA场景能力简析

    场景Java卡片JS卡片支持的版本实时刷新(类似时钟)Java使用ComponentProvider做实时刷新代价比较大JS可以做到端侧刷新,但是需要定制化组件HarmonyOS 2.0及以上
    发表于 10-19 09:23

    HDC2021技术论坛:酷炫3D效果在瘦设备上也能实现?

    存和功耗上表现都非常出色。三、应用示例HarmonyOS 3D渲染引擎当前主要面向普通的应用开发者,典型应用场景是在以2D为主的应用中嵌入少量的3D元素。目前3D渲染引擎已经内置到
    发表于 12-21 10:40

    图形测试分析毫无头绪?HarmonyOS图形栈测试技术帮你解决

    关键就是由渲染特性HDR、Bloom等粒子特效组成,再加上CPU负载就形成一个关键,这些关键连续起来就是3D
    发表于 01-10 10:56

    打造HarmonyOS智能全场景,7大BUFF为您助力!

    的全场景系统架构和一体的的软硬件互通的1+8+N全场景体验。本课程已上线6个课时,每个课时为12钟左右~本课程能帮助开发者更好地理解HarmonyOSConnect UX设计标准与规
    发表于 01-17 10:38

    HarmonyOS/OpenHarmony应用开发-ArkTS语言渲染控制概述

    渲染控制语句包括控制组件是否显示的条件渲染语句,基于数组数据快速生成组件的循环渲染语句以及针对大数据量场景的数据懒加载语句。 后面我们会持续对这这三种方式进行详细阐述。
    发表于 08-09 09:54

    HarmonyOS/OpenHarmony应用开发-ArkTS语言渲染控制if/else条件渲染

    适用的else分支,则不构建任何内容。 条件可以包括Typescript表达式。对于构造函数中的表达式,此类表达式不得更改应用程序状态。三、使用场景1.使用if进行条件渲染 @Entry
    发表于 08-21 14:29

    渲染中的缓存和深度缓存

    渲染涉及大量的缓存,这里缓存只是一个简单的存有像素数据的矩形内存块,最重要缓存是缓存和深度缓存。
    的头像 发表于 05-14 11:44 7373次阅读
    <b class='flag-5'>渲染</b>中的<b class='flag-5'>帧</b>缓存和深度缓存

    华为开发者HarmonyOS零基础入门:15钟玩转harmonyOS服务卡片

    华为开发者HarmonyOS零基础入门:15钟玩转harmonyOS服务卡片,服务卡片颜值、拥有服务直达功能。
    的头像 发表于 10-23 11:40 2514次阅读
    华为开发者<b class='flag-5'>HarmonyOS</b>零基础入门:15<b class='flag-5'>分</b>钟玩转<b class='flag-5'>harmonyOS</b>服务卡片

    HarmonyOS测试技术与实战-UI和渲染分离

    HDC 2021华为开发者大会 HarmonyOS测试技术与实战-UI和渲染分离
    的头像 发表于 10-23 15:23 1572次阅读
    <b class='flag-5'>HarmonyOS</b>测试技术与实战-UI和<b class='flag-5'>渲染</b>分离

    华为开发者论坛HarmonyOS学生公开课-HarmonyOS应用的可流转演示

    2021华为开发者论坛HarmonyOS学生公开课-HarmonyOS应用的可流转演示
    的头像 发表于 10-24 09:41 1867次阅读
    华为开发者<b class='flag-5'>分</b>论坛<b class='flag-5'>HarmonyOS</b>学生公开课-<b class='flag-5'>HarmonyOS</b>应用的可流转演示

    华为开发者论坛HarmonyOS学生公开课-10钟成为HarmonyOS开发者

    2021华为开发者论坛HarmonyOS学生公开课-10钟成为HarmonyOS开发者
    的头像 发表于 10-24 11:03 2230次阅读
    华为开发者<b class='flag-5'>分</b>论坛<b class='flag-5'>HarmonyOS</b>学生公开课-10<b class='flag-5'>分</b>钟成为<b class='flag-5'>HarmonyOS</b>开发者

    华为开发者论坛HarmonyOS学生公开课-如何学习HarmonyOS应用开发?

    2021华为开发者论坛HarmonyOS学生公开课-如何学习HarmonyOS应用开发?
    的头像 发表于 10-24 11:09 2481次阅读
    华为开发者<b class='flag-5'>分</b>论坛<b class='flag-5'>HarmonyOS</b>学生公开课-如何学习<b class='flag-5'>HarmonyOS</b>应用开发?

    HarmonyOS 3D渲染引擎介绍

    随着3D技术的应用普及,越来越多的场景都能看到3D的身影,比如充电动效、3D壁纸、游戏等等,给用户带来了更有趣、更丰富的体验。要满足用户的3D体验需求,离不开3D渲染引擎。本期,我们就和大家聊一聊HarmonyOS的3D
    的头像 发表于 12-23 09:49 5045次阅读
    <b class='flag-5'>HarmonyOS</b> 3D<b class='flag-5'>渲染</b>引擎介绍