ArkTS高性能编程最佳实践

钱满满 发布于 阅读:4

ArkTS作为鸿蒙应用开发主力语言,高性能编程直接影响用户体验(流畅度、响应速度)与设备资源利用(内存、CPU)。

优化后应用启动速度提升,UI渲染帧率提升,内存占用减少。

  1. const声明不变变量
    不变的变量推荐使用const声明。

    const index = 10000; // 该 变 量 在 后 续 过 程 中 未 发 生 改 变 , 建 议 声 明 成 常 量
  2. 避免数值类型混用
    引擎类型动态切换会导致性能损耗。

    let intNum = 1;
    intNum = 1.1; // 该 变 量 在 声 明 时 为 整 型 数 据 , 建 议 后 续 不 要 赋 值 浮 点 型数 据
    let doubleNum = 1.1;
    doubleNum = 1; // 该 变 量 在 声 明 时 为 浮 点 型 数 据 , 建 议 后 续 不要 赋 值 整 型 数据
  3. 循环常量提取
    原理:减少循环体内重复访问对象属性、数组元素或调用方法的开销,将不变的引用提取到循环外部。
    优化前(性能较差)

    class Time {
    static start: number = 0;
    static info: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    }
    function getNum(num: number): number {
    let total: number = 348;
    for (let index: number = 0x8000; index > 0x8; index >>= 1) {
    / / 多 次 对 T ime 的 in f o 及 s t a r t 进 行 查 找 , 并 且 每 次 查找 出 来 的 值 是相 同 的
    total += ((Time.info[num - Time.start] & index) !== 0) ? 1 : 0;
    }
    return total;
    }

    可以将Time.info[num - Time.start]提取为常量,这样可以显著减少属性访问次数,提升性能。

    class Time {
    static start: number = 0;
    static info: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    }
    function getNum(num: number): number {
    let total: number = 348;
    const info = Time.info[num - Time.start]; / / 从 循 环 中 提 取 不 变 量
    for (let index: number = 0x8000; index > 0x8; index >>= 1) {
    if ((info & index) != 0) {
        total++;
    }
    }
    return total;
    }
  4. 闭包性能瓶颈
    作用域链延长,内存占用增加,易导致泄漏。在性能敏感场景中,建议使用参数传递函数外的变量替代。
    使用闭包会造成额外的开销。在性能敏感场景中,建议使用参数传递函数外的变量替代。

    let arr = [0, 1, 2]
    function foo(): number {
    return arr[0] + arr[1]
    }
    foo()

    建议使用参数传递函数外部的变量,以替代使用闭包。

    let arr = [0, 1, 2];
    function foo(array: number[]): number {
    return array[0] + array[1];
    }
    foo(arr);
  5. 可选参数性能影响
    引擎需要处理 undefined 值,这会增加额外的分支判断和类型检查开销,降低函数执行效率。
    优化前(使用可选参数)

    function add(left?: number, right?:
    number): number | undefined {
    if (left != undefined && right !=
    undefined) {
    return left + right;
    }
    return undefined;
    }

    优化后(必选参数)

    function add(left: number = 0, right:
    number = 0): number {
    return left + right;
    }

    根据业务需求,将函数参数声明为必选参数。考虑使用默认参数。

  6. TypedArray核心价值
    针对采用二进制缓冲区(ArrayBuffer)进行存储,元素类型固定(如int8Array、Uint16Array、Float32Array等)。这使得它非常适合进行数值计算和大数据处理,因为它可以直接操作内存,避免了JavaScript动态类型带来的开销。

    const typedArray1 = Int8Array.from([1, 2, 3]);
    const typedArray2 = Int8Array.from([4, 5, 6]);
    let res = new Int8Array(3);
    for (let i = 0; i < 3; i++) {
    res[i] = typedArray1[i] + typedArray2[i];
    }
  7. 稀疏数组问题
    内存浪费(空元素会浪费空间),且遍历效率低下(使用 forEach 时耗时比密集数组更高)。
    数组元素类型不统一(如 (number | string)[])会导致类型检查开销增大,并且JavaScript引擎难以进行有效的优化。

  8. 异常处理性能代价
    中断正常的执行流程,进行堆栈展开和异常对象构造,是一项昂贵的操作。在高频调用或循环中频繁抛出和捕获异常,会显著导致主线程阻塞,降低应用响应速度。
    提前条件判断: 在可能出错的操作前进行检查,避免异常发生。错误码代替异常: 建议使用错误码(如-1, null)来表示失败,而非抛出异常。
    优化前

    function div(a: number, b: number):
    number {
    if (a <= 0 || b <= 0) {
        throw new Error('Invalid numbers.');
    }
        return a / b;
    }
    function sum(num: number): number {
        let sum = 0
        try {
            for (let t = 1; t < 100; t++) {
                sum += div(t, num);
            }
        } catch (e) {
        console.log(e.message);
        }
    return sum;
    }

    优化后

    function div(a: number, b: number): number {
    if (a <= 0 || b <= 0) {
        return NaN;
    }
    return a / b;
    }
    function sum(num: number): number {
    let sum = 0
    for (let t = 1; t < 100; t++) {
        if (t <= 0 || num <= 0) {
            console.log('Invalid numbers.')
        }
        sum += div(t, num);
    }
    return sum;
    }
  9. 长列表优化效果对比
    在实际应用开发中,长列表渲染(如商品列表、消息列表)是常见的性能瓶颈。当列表项数量庞大或内容复杂时,容易出现卡顿、掉帧甚至应用崩溃。

    @State data: ArticleListData | null = null;
    List({ space: Constants.SPACE_16 }) {
    if (this.data !== null) {
        LazyForEach(this.data, (item: LearningResource) => {
            ListItem() {
            // 完 成 列 表 项 渲 染
                ....
            }
            .reuseId('article')
        },
    (item: LearningResource) => item.id)
    }
    }

    优化策略:
    • 列表:只渲染可视区域内的列表项。
    • 数据懒加载:滚动到底部时再加载更多数据。
    • 组件复用:避免频繁创建和销毁列表项组件。
    • 减少重绘:优化列表项布局,避免复杂计算。


扫描二维码,在手机上阅读

需要登录才能发表回复

请登录或注册以继续。