鸿蒙中代码的性能优化

代码性能优化,很多时候藏在细节里。提升运行效率的几个关键:变量声明、属性访问、数值计算与数据结构、模块导出优化,以及通过路径展开提升冷启动性能。
一、变量声明
1. 尽量使用 const 声明常量
对于初期明确不会改变的变量,尽量使用 const 声明常量。
常量范围:包括基础类型和引用类型。
好处:
-
通过
const声明,可以确保地址不会变化 -
减少因误操作导致的赋值错误,从而避免逻辑改变
-
在编辑时及时发现错误
2. number 类型区分 int 和 double
对于 number 类型,编译器在优化时会区分 int 和 double 类型。
写法建议:
-
初始化 number 类型的变量时指定 number 的类型
-
如果预期是整数类型就初始化为
0 -
如果是小数类型就初始化为
0.0 -
避免将一个 number 类型初始化为
undefined或者null
3. 减少使用 ESObject
ESObject 主要用于 ArkTS 和 TS/JS 跨语言调用的类型标注。
在非跨语言场景中使用 ESObject 会引入不必要的跨语言调用,造成额外性能开销。
建议:
在非跨语言调用的场景下,减少使用 ESObject,引入明确的类型进行注释。
二、属性访问
1. 减少变量的属性查找
在要求性能的场景下,建议通过将全局变量存储为局部变量的方式来减少变量的属性查找。
原理:访问局部变量比访问全局变量更快。
说明:重复访问同一变量会造成不必要的消耗,尤其是在循环中,对性能的影响更大。
2. 给类属性添加访问修饰符
在 ArkTS 中,类结构的属性支持 private、protected 和 public 可访问修饰符。
默认情况:属性的可访问修饰符为 public。
建议:
给类属性添加访问修饰符,选取适当的可访问修饰符可以提升代码的安全性、可读性。
三、数值计算与数据结构
1. 纯数值计算推荐 TypedArray
如果是纯数值计算的场合,推荐数值计算使用 TypedArray 数据结构。
说明:
TypedArray 类型化数组是一种类似数组的对象,提供在内存缓冲区中访问原始二进制数据的机制。
适用场景:
-
图像数据处理
-
加解密计算
原因:TypedArray 基于 ArrayBuffer 实现,在性能方面有显著提升。
2. 选取合适的数据结构
通过选取合适的数据结构提高运行效率。
示例:
| 数据结构 | 适用场景 |
|---|---|
| Record | 作为临时容器处理属性存取逻辑 |
| HashMap | 实现快速读写键值 |
HashMap 说明:
HashMap 是 ArkTS 提供的高性能容器类,底层使用红黑树实现,支持高效的数据读写操作。
四、模块导出与延迟加载
1. 减少同文件大量 export * 导出方式
原理:
由于依赖模块解析采用深度优先遍历,会从入口文件的第一个导入语句开始逐层查找,直到最后一个没有导入语句的模块。连接好该模块的导出变量后,再回到上一级模块重复此步骤。
建议:
减少同文件大量 export * 导出方式,降低依赖模块解析、文件执行阶段耗时增长。
2. 延迟加载(lazy import)
当工具类中存在较多暴露函数或变量时,推荐:
-
按需引用使用到的变量
-
使用延迟加载(lazy import)
好处:可以减少该阶段中 .ets 文件执行耗时,即减少文件中所有 export 变量的初始化过程。
五、通过路径展开提升运行效率
传统 HAR 包导入时,即使只需要 HAR 包中单个变量,也会触发整个依赖链所有模块的加载和执行,造成性能浪费。
解决方案:expandImportPath
ArkTS 编译器提供 expandImportPath 配置项。
原理:通过修改配置项,编译器会将间接包名导入转换为精准的文件路径导入,跳过中间模块。
好处:该优化可消除冗余的模块解析和初始化,减少冷启动阶段不必要的资源消耗。
注意
由于 import 路径展开会跳过中间模块的执行,若业务依赖模块的执行顺序,修改后可能会导致业务异常。
示例:未使用路径展开
问题代码:
// entry/src/main/ets/pages/Index.ets
// Before optimization: Namespace Import
import { hilog } from '@kit.PerformanceAnalysisKit';
import * as library from 'library';
hilog.info(0x0000, 'testTag', 'library.typeNum is %{public}d', library.typeNum);
说明:
即使只需要使用 typeNum 变量,但当使用 import * 全量导入 HAR 包时,所有关联模块(如 Animals.ets 等)仍会被加载执行,这会带来不必要的性能开销。
library 模块结构:
// library/src/main/ets/Animals.ets
import { hilog } from '@kit.PerformanceAnalysisKit';
export * from './Birds';
export * from './Fish';
export * from './Mammals';
export * from './TypeNum';
hilog.info(0x0000, 'testTag', 'library Animals.ets execute.');
即使用 import * as library,也会触发 Animals.ets、Birds.ets、Fish.ets、Mammals.ets、TypeNum.ets 全部执行。
代码示例:使用路径展开
优化方式:
-
配置
expandImportPath启用路径展开功能 -
将导入方式改为:
import { typeNum } from 'library';
效果:
使源码中的 import 语句在编译时指向被引用符号的实际定义文件。从 Trace 上看,此时只执行 TypeNum.ets,同时通过修改前后的 Trace 对比也可以看出冷启动性能得到提升。
关键点:
-
const是"零成本"优化:不改变的变量全部用const,既防误改又便于编译器优化,没有理由不用。 -
number 初始化:整数用
0,小数用0.0,别用undefined或null。编译器会区分 int 和 double,初始化时给对类型能避免运行时类型转换。 -
ESObject 是"跨语言专用" :只在 ArkTS 调 TS/JS 时用,非跨语言场景用了会引入额外跨语言调用开销,能用明确类型就别用 ESObject。
-
局部变量比全局变量快:把全局变量存为局部变量,减少属性查找。循环中尤其重要,重复查找的累积开销很大。
-
TypedArray 是数值计算的利器:图像处理、加解密计算用 TypedArray,基于 ArrayBuffer,性能显著优于普通数组。
-
HashMap 底层是红黑树:需要快速读写键值时用 HashMap,比普通对象更高效。
-
export *有解析成本:依赖解析是深度优先遍历,export *越多,解析和执行越慢。按需导出、按需引用更高效。 -
lazy import 减少初始化:工具类函数多时,用 lazy import 按需加载,减少 .ets 文件中所有 export 变量的初始化过程。
-
expandImportPath 是冷启动优化:
-
问题:
import *会触发整个依赖链加载执行 -
解决:配置
expandImportPath,把间接包名导入转为精准文件路径导入,跳过中间模块 -
效果:只执行实际用到的文件,冷启动性能提升
-
-
路径展开风险:跳过中间模块执行可能影响依赖模块执行顺序的业务逻辑。有副作用的模块(如初始化配置、注册事件)要注意,改之前先确认依赖关系。
更多推荐




所有评论(0)