Harmony os——ArkTS 高性能编程实践 – 速查笔记

ArkTS 高性能编程实践 -- 速查笔记

场景:性能敏感代码 (比如频繁调用、深层循环、动画/渲染逻辑等)

目标:在写业务代码的同时,顺手带上高性能写法习惯。


一、声明与表达式

1.1 使用 const 声明不变的变量

  • 原则 :只读、不再修改的变量用 const,方便引擎做优化。
ts 复制代码
// ✅ 推荐
const index = 10000;

// ❌ 不推荐:逻辑上不会变却用 let
let index = 10000;

1.2 number 避免整型 / 浮点型混用

ArkTS 运行时会区分 "整型 number" 和 "浮点 number",混着用会让优化失效。

复制代码
// ❌ 不推荐:int ➜ double
let intNum = 1;
intNum = 1.1;   // 声明时是整数,后面变成小数

// ❌ 不推荐:double ➜ int
let doubleNum = 1.1;
doubleNum = 1;  // 声明时是小数,后面赋值为整数

// ✅ 推荐:类型风格保持一致
let scoreInt: number = 0;     // 一直用整数
let scoreDouble: number = 0.0; // 一直用小数

1.3 数值计算避免溢出

原因:溢出后会走"慢路径",性能变差。

  • + - * ** 运算:尽量保证在 INT32_MIN ~ INT32_MAX 范围内
    • INT32_MAX = 2147483647
    • INT32_MIN = -2147483648
  • &>>> 等位运算:同样避免超过 INT32_MAX

简单理解:

  • 做位运算 / 累加计数时不要让值无限增长,及时裁剪(比如 & 0xffff 或重置)。

1.4 循环中提取常量,减少属性访问

问题代码:每次循环都访问 class 静态属性 + 计算

复制代码
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) {
    total += ((Time.info[num - Time.start] & index) !== 0) ? 1 : 0;
  }
  return total;
}

优化:把循环不变的值缓存到局部常量

复制代码
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;
}

"循环里用到但不会改变的东西 → 提前拿出来当局部 const"。


二、函数

2.1 尽量用参数传递,而不是闭包捕获外部变量

问题:闭包 = 引擎额外维护环境,性能有成本。

复制代码
// ❌ 闭包捕获外部变量
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);

心法:性能敏感代码里,"从外面拿变量" 尽量走参数,而不是让函数偷偷闭包引用。


2.2 避免可选参数,使用"必选 + 默认值"

问题:可选参数意味着可能是 undefined,每次使用都要做判断。

复制代码
// ❌ 有可选参数,内部还要 if 判空
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;
}

场景:

  • 一般工具函数 尽量设计成参数必传,需要"不传"时用默认值表达。

三、数组

3.1 纯数值运算 ➜ 用 TypedArray

普通数组:

复制代码
// ❌ 普通 number 数组
const arr1 = new Array<number>(1, 2, 3);
const arr2 = new Array<number>(4, 5, 6);
let res = new Array<number>(3);

for (let i = 0; i < 3; i++) {
  res[i] = arr1[i] + arr2[i];
}

TypedArray:

复制代码
// ✅ 推荐:TypedArray
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];
}

适用场景:矩阵运算、音频数据、图像 buffer、频繁数值计算等。


3.2 避免"稀疏数组"(sparse array)

稀疏数组 & 大数组(>1024)可能会被运行时转成 hash 表存储,访问会更慢。

复制代码
// ❌ 大小 100000 的数组:可能走 hash 存储
let count = 100000;
let result: number[] = new Array(count);

// ❌ 稀疏数组:直接给很远的索引赋值
let result2: number[] = new Array();
result2[9999] = 0;

建议:

  • 尽量使用 push 逐步填充

  • 或者用 new Array(count).fill(0) 初始化成"密集数组"

    // ✅ 密集数组
    let result: number[] = new Array(count).fill(0);


3.3 避免联合类型数组 & 数值类型混用

复制代码
// ❌ 数值数组里混合整型 + 浮点型
let arrNum: number[] = [1, 1.1, 2];

// ❌ 元素是 (number | string) 联合类型
let arrUnion: (number | string)[] = [1, 'hello'];

推荐: 不同类型的值分开存:

复制代码
// ✅ 分类型存储
let arrInt: number[] = [1, 2, 3];
let arrDouble: number[] = [0.1, 0.2, 0.3];
let arrString: string[] = ['hello', 'world'];

心法:

  • 数组 = 一种类型,而不是"什么都往里面丢一个"。

四、异常(Error)使用

4.1 性能敏感路径中避免频繁抛异常

抛异常时需要构造栈信息,是非常重 的操作。

特别是在 for 循环、热点函数中,不要用异常做控制流。

问题代码:

复制代码
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.info(e.message);
  }
  return sum;
}

优化思路:

  • 返回特殊值 (NaN / -1 / null) 表示异常,而不是直接 throw

  • 循环内部做快速判断,避免频繁进入 catch

    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 (num <= 0) { // ✅ 提前拦截非法情况
    console.info('Invalid numbers.');
    break; // 可视情况 break / continue
    }
    sum += div(t, num);
    }
    return sum;
    }

经验法则:

  • 异常只用在"真正异常的情况",而不是普通业务条件判断。
  • 热路径里宁可多几次 if,也少一次 throw

五、实战时可以直接套用的"小 Checklist"

写 ArkTS 性能敏感代码时,可以过一遍这几个问题:

  1. 常量是不是都用 const
    • 会不会修改?不会就用 const
  2. number 有没有从 int 变 double 或反过来?
    • 是否统一风格?
    • 是否可能越界 int32?
  3. 循环里有没有可以提到外面的不变量?
    • 静态属性、数组索引结果、复杂表达式等。
  4. 函数是不是在闭包里偷偷引用外部变量?
    • 能否通过参数传进去?
  5. 函数参数用的是可选参数吗?
    • 能否改成"必选+默认值"?
  6. 数组是不是稀疏的 / 超大 / 元素类型杂?
    • 能否用 TypedArray 或分类型数组?
  7. for/热点代码里有频繁 throw / try...catch 吗?
    • 能否用返回码 / NaN / null 代表错误?
相关推荐
Alice-YUE1 小时前
【js高频八股】防抖与节流
开发语言·前端·javascript·笔记·学习·ecmascript
小陈phd2 小时前
TensorRT 入门完全指南(一)——从核心定义到生态工具全解析
人工智能·笔记
是上好佳佳佳呀2 小时前
【前端(十一)】JavaScript 语法基础笔记(多语言对比)
前端·javascript·笔记
xmdy58662 小时前
Flutter+开源鸿蒙实战|智安盾电商溯源平台Day1 项目搭建与整体方案拆解
flutter·开源·harmonyos
handler012 小时前
Linux 内核剖析:进程优先级、上下文切换与 O(1) 调度算法
linux·运维·c语言·开发语言·c++·笔记·算法
其实防守也摸鱼3 小时前
CTF密码学综合教学指南--第四章
网络·笔记·安全·网络安全·密码学·ctf
nashane3 小时前
HarmonyOS 6学习:应用签名文件丢失处理与更新完全指南
学习·华为·harmonyos·harmonyos 5
笔触狂放4 小时前
【项目】基于ArkTS的老年人智能应用开发(1)
harmonyos·arkts·鸿蒙
05候补工程师5 小时前
【ROS 2 具身智能】Gazebo 仿真避坑指南:从“幽灵机器人”到传感器数据流打通
人工智能·经验分享·笔记·ubuntu·机器人
chushiyunen5 小时前
pandas使用笔记、数据清洗、json_normalize
笔记·pandas