This topic outlines some best practices for improving your application performance to live up to user expectations for quick startup, timely response, and no frame freezing.
Following these practices, you can reduce your application's startup time, response time, and frame loss.
- Improving application startup and response time
-[Speeding Up Application Cold Start](../performance/improve-application-startup-and-response/improve-application-cold-start-speed.md)
Application startup latency is a key factor that affects user experience. To speed up the application cold start, you are advised to perform optimization in the following four phases:
1. Application process creation and initialization
2. Application and ability initialization
3. Ability lifecycle
4. Home page loading and drawing
-[Speeding Up Application Response](../performance/improve-application-startup-and-response/improve-application-response.md)
A premium interaction experience requires quick response to user input. To improve your application's response time, you are advised to prevent the main thread from being blocked by non-UI tasks and reduce the number of component to be refreshed.
The smoothness of rendering the layout to the screen affects the user perceived quality. It is recommended that you minimize nesting in your code to shorten the render time.
Whether animations in your application run smoothly is a key factor that affects user experience. You are advised to use the system-provided animation APIs to reduce frame loss.
Application startup latency is a key factor that affects user experience. When an application is started, the background does not have a process of the application, and therefore the system creates a new process and allocates it to the application. This startup mode is called cold start.
## Analyzing the Time Required for Application Cold Start
The cold start process of OpenHarmony applications can be divided into four phases: application process creation and initialization, application and ability initialization, ability lifecycle, and home page loading and drawing, as shown in the following figure.
## 1. Shortening Time Required for Application Process Creation And Initialization
In the phase of application process creation and initialization, the system creates and initializes an application process, including decoding the icon of the startup page (specified by **startWindowIcon**).
### Using startWindowIcon of Appropriate Resolution
With regard to the icon of the startup page, the recommended maximum resolution is 256 x 256 pixels. Larger resolutions may result in slow startup.
## 2. Shortening Time Required for Application and Ability Initialization
In this phase of application and ability initialization, resources are loaded, VMs are created, application and ability related objects are created and initialized, and dependent modules are loaded.
### Minimizing the Number of Imported Modules
Before the application code is executed, the application must find and load all imported modules. Each additional third-party framework or module to be loaded by the application increases the startup time. The time required depends on the number and size of loaded third-party frameworks or modules. To speed up startup, use system-provided modules when possible and load the modules as required.
## 3. Shortening Time Required for Ability Lifecycle
In this phase of ability lifecycle, the ability lifecycle callbacks are executed.
### Avoiding Time-Consuming Operations in Ability Lifecycle Callbacks
In the application startup process, the system executes the ability lifecycle callbacks. Whenever possible, avoid performing time-consuming operations in these callbacks. You are advised to perform time-consuming operations through asynchronous tasks or execute them in other threads.
In these lifecycle callbacks, perform only necessary operations. For details, see [UIAbility Lifecycle](https://gitee.com/openharmony/docs/blob/master/en/application-dev/application-models/uiability-lifecycle.md).
## 4. Shortening Time Required for Home Page Loading and Drawing
In this phase of home page loading and drawing, the home page content is loaded, the layout is measured, and components are refreshed and drawn.
### Avoid time-consuming operations in the custom component lifecycle callbacks.
When the lifecycle of a custom component changes, the corresponding callback is called.
The **aboutToAppear** function is executed after the custom component instance is created and before the page is drawn. The following code asynchronously processes the time-consuming computing task in **aboutToAppear** to avoid executing the operation in this function and blocking the page drawing.
```javascript
@Entry
@Component
structIndex{
@Stateprivatetext:string=undefined;
privatecount:number=undefined;
aboutToAppear(){
this.computeTaskAsync();// Asynchronous task
this.text="hello world";
}
build(){
Column({space:10}){
Text(this.text).fontSize(50)
}
.width('100%')
.height('100%')
.padding(10)
}
computeTask(){
this.count=0;
while(this.count<10000000){
this.count++;
}
this.text='task complete';
}
// Asynchronous processing of the computing task
privatecomputeTaskAsync(){
newPromise((resolved,rejected)=>{
setTimeout(()=>{// setTimeout is used to implement asynchronous processing.
This topic provides the following tips for improving your application's response to user input.
- Prevent the main thread from being blocked by non-UI tasks.
- Reduce the number of components to be refreshed.
## Preventing Main Thread from Being Blocked by Non-UI Tasks
When the application responds to user input, its main thread should execute only UI tasks (such as preparation of data to be displayed and update of visible components). It is recommended that non-UI, time-consuming tasks (such as long-time content loading) be executed through asynchronous tasks or allocated to other threads.
### Using Asynchronous Component Loading
The **\<Image>** component has the asynchronous loading feature enabled by default. When an application loads a batch of local images to be displayed on the page, blank placeholder icons are displayed first, and then replaced by the images when these images have finished loading in other threads. In this way, image loading does not block page display. The following code is recommended only when the image loading takes a short time.
// Several <Row> containers are omitted here. Each container contains the preceding <Image> components.
}
}
}
```
Recommendation: If it takes a short time to load an image, the benefits of asynchronous loading will be greatly undermined. In this case, change the value of the syncLoad attribute.
// Several <Row> containers are omitted here. Each container contains the preceding <Image> components.
}
}
}
```
### Using TaskPool for Asynchronous Processing
Compared with the worker thread, [TaskPool](https://gitee.com/sqsyqqy/docs/blob/master/en/application-dev/reference/apis/js-apis-taskpool.md) provides the task priority setting and automatic thread pool management mechanism. The following is an example:
The following code shows how to declare a long-running non-UI task as an asynchronous task through **Promise**. This allows the main thread to first focus on providing user feedback and completing the initial render, and then execute the asynchronous task when it is idle. After the asynchronous task is complete, related components are redrawn to refresh the page.
this.computeTaskAsync();// Invoke the asynchronous compute function.
}
// Simulate a compute-intensive task.
computeTask(){
this.count=0;
while(this.count<100000000){
this.count++;
}
this.children=this.children.reverse();
}
computeTaskAsync(){
newPromise((resolved,rejected)=>{
setTimeout(()=>{// setTimeout is used to implement asynchronous processing.
this.computeTask();
},1000)
})
}
build(){
// Component layout
}
}
```
## Reducing the Number of Components to Be Refreshed
When an application refreshes a page, the number of components to be refreshed must be reduced as much as possible. If this number is too large, the main thread will take a long time to perform measurement and layout. In addition, the **aboutToAppear()** and **aboutToDisappear()** APIs will be called multiple times during the creation and destruction of custom components, increasing the load of the main thread.
### Limiting the Refresh Scope with Containers
Negative example: If a component in a container is included in the **if** condition, changes in the **if** condition result will trigger the creation and destruction of the component. If the container layout is affected in this case, all components in the container are refreshed. As a result, the UI refresh of the main thread takes a long time.
In the following example, the **Text('New Page')** component is controlled by the state variable **isVisible**. When **isVisible** is set to **true**, the component is created. When **isVisible** is set to **false**, the component is destroyed. This means that, when the value of **isVisible** changes, all components in the **\<Stack>** container are refreshed.
Negative example: Each of the 10000 elements in **this.arr** is initialized and loaded. As a result, the execution of the main thread takes a long time.
Frame loss in the animation arena is a phenomenon where the frame rate of an animation drops when it is running or being created.
When playing an animation, the system needs to calculate the animation curve and draw the component layout within a refresh period. You are advised to use the system-provided animation APIs. With these APIs, setting the curve type, end point position, and duration is enough for meeting common animation needs, thereby reducing the load of the UI main thread.
Negative example: The application uses a custom animation, which involves animation curve calculation. This calculation process may cause high load of the UI thread and frame loss.
})// Animation configuration for the width and height attributes of the <Button> component.
}.width('100%').margin({top:5})
}
}
```
For more details, see [Property Animator](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/arkui-ts/ts-animatorproperty.md).
## Using System-Provided Explicit Animation APIs
The following uses the system-provided explicit animation APIs to implement the preceding animation features:
For more details, see [Explicit Animation](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/arkui-ts/ts-explicit-animation.md).
The view hierarchy can significantly affect application performance. For example, at the 120 Hz refresh rate, a device screen refreshes frames every 8.3 ms. If there are many levels of nested views, the frames may fail to be refreshed within 8.3 ms. As a result, frame loss and frame freezing occur, detracting from user experience. Therefore, it is recommended that you minimize nesting in your code to shorten the refresh time.
## Removing Redundant Levels of Nesting
In the following negative example, the **\<Grid>** component is used to implement a grid, but it is nested inside three levels of **\<Stack>** containers. As a result, the refresh and rendering process takes a long time to complete.
Recommendation: Reduce the redundant nesting of **\<Stack>** containers. In this way, the number of components that each grid item needs to pass is three less, shortening the refresh and rendering time.