【最新鸿蒙开发 | api12】——应用性能优化实践

一、概览

image-20240905204203804

二、ArkTS高性能编程

  • ArkTS高性能编程规则

    更有利于方舟编译运行时,进行编译优化,生产更高性能的机器码,保障程序运行得更快

    • 出于代码的稳定性和性能考虑,一些TypeScript的特性被限制了。比如需要不支持属性的动态变更、变量或参数需要有明确的类型声明和返回值生命等

    • 不支特使用any和unknown 请使用明确类型,或者使用联合类型、泛型或者object替代any,必须使用any的场景可以使用ESobject代替,但是可能存在性能问题,谨慎使用。

  • 使用AOT模式对应用进行编译优化

    方舟编译运行通过采用PGO(配置文件引导型优化)方式,提前生成高性能机器码,从而提升程序运行速度

    AOT模式即提前编译,能够在Host端将字节码提前编译成Target端可运行的机器码,这样字节码可以获得充分编译优化,放到Target端运行时可以获得加速

    官方文档开启AOT模式icon-default.png?t=O83Ahttps://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-hvigor-aot-V5
  • image-20240905205134311

三、提升应用启动和响应速度

  • 冷启动过程简介

    应用启动时,后台无该应用的进程,需要创建新的进程,这种启动方式叫做冷启动。

    过程大概分为四个阶段:应用进程创建和初始化、App和Ability的初始化、Ability生命周期、加载绘制首页

    • 第一阶段:应用需要在它的进程孵化仓里面去孵化出一个新的进程,进行必须的一些资源和初始化

      优化:设置合适分辨率的startWindowIcon(启动图标)

    • 第二阶段:Application是应用独有的一个上下文,包含了所有应用侧相关的一些生命周期,ability是应用启动了Application之后进行创建的一个具体的组件,ability也会在初始化过程中创建必须的上下文和资源

      优化:减少首页Abiltiy或者Page中import的模块

      image-20240905210841361

    • 第三阶段:Abiltiy的生命周期

      优化:使用异步加载

    • 第四阶段:加载绘制首页

      优化:延迟加载

    image-20240905205725048

  • 使用异步加载

    使用异步加载可以在后台线程中处理耗时操作,从而提升响应速度

    image-20240905210816070

  • 延迟加载

    将不必要的资源延迟加载可以减少应用的启动时间。使用List、Grid、Swiper等容器组件时,配合系统提供的LazyForEach数据懒加载能力,可以有效减少应用启动时间和内存占用

    image-20240905210858876

  • 使用缓存

    选择合适的缓存策略可以提高应用程序的性能和响应速度,从而提升应用响应速度,使用LazyForEach时,可以搭配使用cachedCount方法,自定义控制列表的缓存数量,默认加载1条缓存数量

四、减少丢帧卡帧

  • 避免在主线程上执行耗时操作

    UI主线程是HarmonyOS应用中最重要的线程之一,在主线程上执行耗时操作会堵塞UI渲染,从而导致UI主线程的负载过高。因此,可以将耗时操作放在TaskPool或Worker等后台线程中执行

  • Worker和TaskPool对比
    实现TASKPOOLWORKER
    内存模型线程间隔离,内存不共享。线程间隔离,内存不共享。
    参数传递机制采用标准的结构化克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。支持ArrayBuffer转移和SharedArrayBuffer共享。采用标准的结构化克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。支持ArrayBuffer转移和SharedArrayBuffer共享。
    参数传递直接传递,无需封装,默认进行transfer。消息对象唯一参数,需要自己封装。
    方法调用直接将方法传入调用。在Worker线程中进行消息解析并调用对应方法。
    返回值异步调用后默认返回。主动发送消息,需在onmessage解析赋值。
    生命周期TaskPool自行管理生命周期,无需关心任务负载高低。开发者自行管理Worker的数量及生命周期。
    任务池个数上限自动管理,无需配置。同个进程下,最多支持同时开启64个Worker线程,实际数量由进程内存决定。
    任务执行时长上限3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时),长时任务无执行时长上限。无限制。
    设置任务的优先级支持配置任务优先级。不支持。
    执行任务的取消支持取消已经发起的任务。不支持。
    线程复用支持。不支持。
    任务延时执行支持。不支持。
    设置任务依赖关系支持。不支持。
    串行队列支持。不支持。
    任务组支持。不支持。
  • 适用场景对比:由于TaskPool的工作线程会绑定系统的调度优先级,并且支持负载均衡(自动扩缩容),而Worker需要开发者自行创建,存在创建耗时以及不支持设置调度优先级,故在性能方面使用TaskPool会优于Worker,因此大多数场景推荐使用TaskPool。

  • 常见的一些开发场景及适用具体说明如下:

    • 运行时间超过3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时)的任务。例如后台进行1小时的预测算法训练等CPU密集型任务,需要使用Worker。

    • 有关联的一系列同步任务。例如在一些需要创建、使用句柄的场景中,句柄创建每次都是不同的,该句柄需永久保存,保证使用该句柄进行操作,需要使用Worker。

    • 需要设置优先级的任务。例如图库直方图绘制场景,后台计算的直方图数据会用于前台界面的显示,影响用户体验,需要高优先级处理,需要使用TaskPool。

    • 需要频繁取消的任务。例如图库大图浏览场景,为提升体验,会同时缓存当前图片左右侧各2张图片,往一侧滑动跳到下一张图片时,要取消另一侧的一个缓存任务,需要使用TaskPool。

    • 大量或者调度点较分散的任务。例如大型应用的多个模块包含多个耗时任务,不方便使用Worker去做负载管理,推荐采用TaskPool。

  • image-20240905212043908

  • 减少渲染进程的冗余开销

    使用资源图代替绘制、合理使用renderGroup、尺寸位置设置尽量使用整数,可以减少渲染所需要的时间,从而减少丢帧卡顿

    image-20240905212113613

    image-20240917171430739

    • animateTo需要判断初始状态和结束状态两个状态,需要进行两次更新

    • transition只需要去判断初始状态或者时结束状态的最总结果,只需要一次判断,因此性能更好

  • 合理使用RenderGroup

    对于没有状态变量绑定的一些组件去做属性动画时,可以加上renderGroup属性,加速动画效果。前提是组件的内容不会发生变化,否则缓存信息会失效。
  • image-20240905212431589

  • 减少视图嵌套层级

    应用开发中的用户界面(UI)布局是用户与应用程序交互的关键部分。不合理的布局越多,视图的创建、布局、渲染等流程所需的时间就越长。因此,减少嵌套层次或者使用高性能布局节点,可以减少丢帧卡顿。

    image-20240905212826450

  • 组件复用配合LazyForEach(可以去看我之前的瀑布流案例)

    使用ArkUI开发范式提供的组件复用机制,通过重复利用已经创建过并缓存的组件对象,降低组件短时间内频繁创建和销毁的开销,提升组件的加载效率,降低UI线程负载,从而减少丢帧卡顿

    image-20240905212936390

  • 精确控制状态变量的关联组件数

    @State等状态变量关联组件越多,状态数据变更时刷新的组件越多,UI线程负载越重,因此移除冗余的组件关联可以减少丢帧卡顿

    image-20240905213018569

  • 在对象上谨慎使用状态变量关联

    使用@Prop会进行数据的拷贝,而@ObjectLink只是将引用指向原数据

    image-20240905213117031

更多可参考华为开发者学堂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值