• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# QoS 开发指导
2
3## 场景介绍
4
5自多道程序及多任务操作系统问世以来,CPU、内存等有限的系统资源成为系统中所有任务的竞争对象。合理安排各个任务对系统的响应速度以及资源消耗都有非常重大的意义。相比操作系统,开发者更加清楚应用中各个任务的重要程度;根据重要程度对应用的任务进行分类,能帮助系统更好地进行任务的调度。通过本指导,开发者可以了解在OpenHarmony系统中,如何利用QoS特性及相关的接口调节任务在系统中的运行时间分配。
6
7本文用于指导开发者基于QoS特性实现应用任务优先调度属性自定义。
8
9## 基本概念
10
11### QoS
12
13QoS(quality-of-service),即服务质量,在OpenHarmony中QoS特性主要指任务的优先调度属性。开发者可以利用QoS对要执行的工作进行分类,以指示其与用户交互的关联程度;系统则可以根据任务设置的QoS安排各任务的运行时间和运行次序。例如,当系统中有多个任务需要同时执行时,一些与用户交互关联程度不高的后台下载任务可以推迟到更晚的时间执行,且每次执行时分配更少的时间;而用户感知明显的动效绘制等任务则需要立即执行,并分配更多的执行时间。
14
15### QoS等级定义
16目前,OpenHarmony系统一共划分了如下6个QoS等级,从上到下与用户交互的关联程度依次递增,适用于多种不同的应用场景及负载特征情况。
17
18| QoS等级                                                       | 使用场景                                                         | 负载特征                                                         |
19| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
20| QOS_BACKGROUND | 后台且用户不可见任务,例如数据同步、备份。 | 任务完成需要几分钟甚至几小时。 |
21| QOS_UTILITY | 不需要立即看到响应效果的任务,例如下载或导入数据。 | 任务完成需要几秒到几分钟。 |
22| QOS_DEFAULT | 默认。 | 任务完成需要几秒钟。 |
23| QOS_USER_INITIATED | 用户触发并且可见进展的任务,例如打开文档。 | 任务在几秒钟之内完成。 |
24| QOS_DEADLINE_REQUEST | 越快越好的关键任务,如页面加载。 | 任务几乎是瞬间完成的。 |
25| QOS_USER_INTERACTIVE	 | 用户交互任务(UI线程、刷新界面、动效)。 | 任务是即时的。 |
26
27QoS等级定义为枚举类型QoS_Level,如上表所示;枚举值定义如下。
28### QoS_Level声明
29```{.c}
30typedef enum QoS_Level {
31    /**
32     * 适用于数据同步等用户不可见的后台任务。
33     */
34    QOS_BACKGROUND,
35    /**
36     * 适用于下载等不需要立即看到响应效果的任务。
37     */
38    QOS_UTILITY,
39    /**
40     * 默认的QoS等级。
41     */
42    QOS_DEFAULT,
43    /**
44     * 适用于打开文档等用户触发并且可以看到进展的任务。
45     */
46    QOS_USER_INITIATED,
47    /**
48     * 适用于页面加载等越快越好的任务。
49     */
50    QOS_DEADLINE_REQUEST,
51    /**
52     * 适用于动效绘制等用户交互任务。
53     */
54    QOS_USER_INTERACTIVE,
55} QoS_Level;
56
57```
58
59## 功能效果
60QoS等级更高的任务相对等级更低的可能被分配更多的CPU时间。
61
62下面将展示合理使用QoS对程序执行的优化效果。
63
64### QoS对线程执行的优化
65
66**优化前**
67
68![qosfigure1.png](./figures/qosfigure1.png)
69
70线程1和线程2是某程序的两个关键线程,线程1在运行时会触发新任务线程2,等线程2执行完后会唤醒线程1继续执行。在未标记这两个线程的QoS等级之前,其优先执行顺序低于线程3和线程4;此时线程1和线程2的执行效果如上图所示:
71
721. 线程1等待被线程2唤醒,而线程2优先级低,长时间被抢占,导致线程1长时间睡眠;
73
742. 线程1优先级低,它被唤醒后等待运行时间长;
75
763. 线程1优先级低,运行过程中长时间被其它线程抢占。
77
78**优化后**
79
80![qosfigure2.png](./figures/qosfigure2.png)
81
82合理标记线程1和线程2的QoS等级后,两个线程的执行优化效果如上图所示:
83
841. 线程2运行时间占比提高,线程1等待时间减少;
85
862. 线程1被线程2唤醒后,等待的时间减少;
87
883. 线程1运行实际占比提高,被抢占比例减少。
89
90### QoS对RN框架的优化
91在RN框架中合理标记关键线程的QoS等级后,如下表所示,开源benchmark测试的性能提升了约13%。
92
93| 验证场景      | 验证环境 | 总渲染时间 |
94| ----------- | ----------- | ----------- |
95| benchmark<br>1500view      | 无QoS优化       | 270.8 ms       |
96| benchmark<br>1500view   | 使用QoS优化        | 236.6 ms       |
97
98## 接口说明
99
100| 接口名                                                       | 描述                                                         | 参数                                                         | 返回值                                                         |
101| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
102| OH_QoS_SetThreadQoS(QoS_Level level) | 设置当前任务的QoS等级。 | QoS_Level level | 0或-1 |
103| OH_QoS_ResetThreadQoS() | 取消当前任务设置的QoS等级。 | 无 | 0或-1 |
104| OH_QoS_GetThreadQoS(QoS_Level *level) | 获取当前任务的QoS等级。 | QoS_Level *level | 0或-1 |
105
106### 使用限制
107* QoS接口只能设置本任务的QoS等级。
108
109## 函数介绍
110
111### OH_QoS_SetThreadQoS
112
113**声明**
114```{.c}
115int OH_QoS_SetThreadQoS(QoS_Level level);
116```
117
118**参数**
119
120QoS_Level level
121* 该参数用于描述要为任务设置的QoS等级。
122
123**返回值**
124* 若成功则返回0,失败则返回-1。
125
126**描述**
127
128为某个任务设置指定的QoS等级。设置当前任务的QoS等级。开发者可以根据当前任务的重要程度,为其标记不同等级的QoS,从而获得不同的调度供给。参考[QoS实践指导](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-thread-priority-setting)129
130**样例**
131```
132#include <stdio.h>
133#include "qos/qos.h"
134
135int func()
136{
137    // 设置当前任务的QoS等级为QOS_USER_INITIATED
138    int ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_USER_INITIATED);
139
140    if (!ret) { // ret等于0说明设置成功
141        printf("set QoS Success.");
142    } else { // ret不等于0说明设置失败
143        printf("set QoS failed.");
144    }
145
146    return 0;
147}
148```
149
150### OH_QoS_ResetThreadQoS
151
152**声明**
153```{.c}
154int OH_QoS_ResetThreadQoS();
155```
156
157**参数**
158* 无。
159
160**返回值**
161* 若成功则返回0,失败则返回-1。
162
163**描述**
164
165取消某个任务设置的QoS等级。取消当前任务的QoS等级。参考[QoS实践指导](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-thread-priority-setting)166
167**样例**
168```
169#include <stdio.h>
170#include "qos/qos.h"
171
172int func()
173{
174    // 重置当前任务的QoS等级
175    int ret = OH_QoS_ResetThreadQoS();
176
177    if (!ret) { // ret等于0说明重置成功
178        printf("reset QoS Success.");
179    } else { // ret不等于0说明重置失败
180        printf("reset QoS failed.");
181    }
182
183    return 0;
184}
185```
186
187### OH_QoS_GetThreadQoS
188
189**声明**
190```{.c}
191int OH_QoS_GetThreadQoS(QoS_Level *level);
192```
193
194**参数**
195
196QoS_Level *level
197* 该参数用于存储任务已经设置的QoS等级。
198
199**返回值**
200* 若成功则返回0,失败则返回-1。
201
202**描述**
203
204获取某个任务之前最近一次设置的QoS等级;如果之前未设置任何QoS等级,则返回-1。查看当前任务的QoS等级。参考[QoS实践指导](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-thread-priority-setting)205
206**样例**
207```
208#include <stdio.h>
209#include "qos/qos.h"
210
211int func()
212{
213    // 获取当前任务的QoS等级
214    QoS_Level level = QoS_Level::QOS_DEFAULT;
215    int ret = OH_QoS_GetThreadQoS(&level);
216
217    if (!ret) { // ret等于0说明获取成功
218        printf("get QoS level %d Success.", level);
219    } else { // ret不等于0说明获取失败
220        printf("get QoS level failed.");
221    }
222
223    return 0;
224}
225```
226
227## 开发步骤
228以下步骤描述了如何使用QoS特性提供的Native API接口,调整或查询任务的QoS等级。
229
230### 1. 添加动态链接库
231QoS特性的使用依赖相关的动态链接库:**libqos.so**;需要在目标应用或程序的编译环境中添加。
232
233**示例**
234
235使用DevEco Studio创建的模板NDK工程,会默认生成CMakeLists.txt脚本,在其中添加QoS相关动态链接库示例如下:
236
237```txt
238# the minimum version of CMake.
239cmake_minimum_required(VERSION 3.4.1)
240project(qos)
241
242set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
243
244include_directories(${NATIVERENDER_ROOT_PATH}
245                    ${NATIVERENDER_ROOT_PATH}/include)
246
247add_library(entry SHARED hello.cpp)
248
249# 直接引用libqos.so原因:位于已在链接寻址路径的NDK中,无需额外声明
250target_link_libraries(entry PUBLIC libqos.so)
251```
252
253### 2. 引用头文件
254
255在使用QoS特性的源代码中需要引用相关的头文件。
256
257```c
258#include "qos/qos.h"
259```
260
261### 3. 调用QoS接口
262
263开发者根据自身需求调用相应的QoS接口调整任务的QoS等级,或者查询任务的QoS等级。
264
265