harmony 鸿蒙ArkTS Performant Programming Practices
ArkTS Performant Programming Practices
Overview
This topic provides a set of performant programming practices that you can apply in performance-critical scenarios. They are techniques and recommendations drawn from real-world development. Following these practices in your service implementation can help develop performant applications. For details about ArkTS coding standards, see ArkTS Coding Style Guide.
Declaration and Expression
Using const to Declare Unchanged Variables
You are advised to use const to declare variables that remain unchanged.
const index = 10000; // This variable does not change in the subsequent process. You are advised to declare it as a constant.
Avoiding Mixed Use of Integers and Floating-Point Numbers in Variables of the number Type
For variables of the number type, integer data and floating-point data are distinguished during optimization at runtime. As such, avoid changing the data type of the variables after they have been initialized.
let intNum = 1;
intNum = 1.1; // This variable is declared as an integer data type. Avoid assigning a floating-point number to it.
let doubleNum = 1.1;
doubleNum = 1; // This variable is declared as a floating-point data type. Avoid assigning an integer to it.
Avoiding Overflow in Arithmetic Operations
When arithmetic operations run into overflow, the engine enters a slower logic branch for processing overflow, affecting subsequent performance. Below are some suggestions to mitigate the overflow risk.
For operations such as addition, subtraction, multiplication, and exponentiation, the value should not be greater than INT32_MAX or less than INT32_MIN.
For operations such as & (and) and >>> (unsigned right shift), the value should not be greater than INT32_MAX.
Extracting Constants in Loops to Reduce Attribute Access Times
In a loop where there is frequent access to a constant that does not change, extract the constant outside of the loop to reduce the number of times the property is accessed.
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) {
// The system searches for info and start of Time multiple times, and the values found each time are the same.
total += ((Time.info[num - Time.start] & index) !== 0) ? 1 : 0;
}
return total;
}
This optimization extracts constants in Time.info[num - Time.start], which greatly reduces the number of property access times and brings better performance. The optimized code is as follows:
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]; // Extract constants from the loop.
for (let index: number = 0x8000; index > 0x8; index >>= 1) {
if ((info & index) != 0) {
total++;
}
}
return total;
}
Functions
Using Parameters to Pass External Variables
Using closures may incur additional overhead for closure creation and access. In performance-sensitive scenarios, you are advised to use parameters to pass external variables instead of using closures.
let arr = [0, 1, 2];
function foo(): number {
return arr[0] + arr[1];
}
foo();
You are advised to use parameter to pass external variables instead of using closures.
let arr = [0, 1, 2];
function foo(array: number[]): number {
return array[0] + array[1];
}
foo(arr);
Avoiding Optional Parameters
An optional function parameter may be undefined. When such a parameter is used in the function, the system needs to check whether the parameter is null, which will cause extra overhead.
function add(left?: number, right?: number): number|undefined {
if (left != undefined && right != undefined) {
return left + right;
}
return undefined;
}
Declare function parameters as mandatory parameters based on service requirements. You can use the default parameters.
function add(left: number = 0, right: number = 0): number {
return left + right;
}
Arrays
Prioritizing TypedArray for Value Arrays
Where only arithmetic operations are involved, prefer TypedArrays over Arrays.
Before optimization
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];
}
After optimization
const typedArray1 = new Int8Array([1, 2, 3]);
const typedArray2 = new Int8Array([4, 5, 6]);
let res = new Int8Array(3);
for (let i = 0; i < 3; i++) {
res[i] = typedArray1[i] + typedArray2[i];
}
Avoiding Sparse Arrays
When allocating an array whose size exceeds 1024 or a sparse array, a hash table is used to store elements. This mode, compared with using an offset to access array elements, results in slower access speeds. Therefore, during development, avoid changing arrays into sparse arrays.
// Allocate an array of 100,000 bytes, for which a hash table is used to store elements.
let count = 100000;
let result: number[] = new Array(count);
// The array will become a sparse array when the value is changed to 9999 after the array is created.
let result: number[] = new Array();
result[9999] = 0;
Avoiding Arrays of Union Types
When appropriate, use arrays that contain elements of the same type. That is, avoid using arrays of union types. Avoid mixed use of integer data and floating-point data in number arrays.
let arrNum: number[] = [1, 1.1, 2]; // Both integer data and floating-point data are used in a value array.
let arrUnion: (number|string)[] = [1, 'hello']; // Union array.
Place the data of the same type in the same array based on service requirements.
let arrInt: number[] = [1, 2, 3];
let arrDouble: number[] = [0.1, 0.2, 0.3];
let arrString: string[] = ['hello', 'world'];
Exceptions
Avoiding Frequent Exceptions
Creating exceptions involves constructing the stack frame for the exception, which may performance overhead. In light of this, avoid frequently throwing exceptions in performance-sensitive scenarios, for example, in for loop statements.
Before optimization
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
}
After optimization
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
}
你可能感兴趣的鸿蒙文章
harmony 鸿蒙Creating an Application Clone
harmony 鸿蒙app.json5 Configuration File
harmony 鸿蒙Structure of the app Tag
harmony 鸿蒙Overview of Application Configuration Files in FA Model
harmony 鸿蒙Overview of Application Configuration Files in Stage Model
harmony 鸿蒙Application Installation, Uninstall, and Update
harmony 鸿蒙Application Package Overview
- 所属分类: 后端技术
- 本文标签:
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦