• 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![qosfigure1.png](./figures/qosfigure1.png)
68
69线程1和线程2是某程序的两个关键线程,线程1在运行时会触发新任务线程2,等线程2执行完后会唤醒线程1继续执行。在未标记这两个线程的QoS等级之前,其优先执行顺序低于线程3和线程4;此时线程1和线程2的执行效果如上图所示:
70
711. 线程1等待被线程2唤醒,而线程2优先级低,长时间被抢占,导致线程1长时间睡眠;
72
732. 线程1优先级低,它被唤醒后等待运行时间长;
74
753. 线程1优先级低,运行过程中长时间被其它线程抢占。
76
77#### 优化后
78![qosfigure2.png](./figures/qosfigure2.png)
79
80合理标记线程1和线程2的QoS等级后,两个线程的执行优化效果如上图所示:
81
821. 线程2运行时间占比提高,线程1等待时间减少;
83
842. 线程1被线程2唤醒后,等待的时间减少;
85
863. 线程1运行实际占比提高,被抢占比例减少。
87
88### QoS对RN框架的优化
89在RN框架中合理标记关键线程的QoS等级后,如下表所示,开源benchmark测试的性能提升了约13%。
90
91| 验证场景      | 验证环境 | 总渲染时间 |
92| ----------- | ----------- | ----------- |
93| benchmark<br>1500view      | 无QoS优化       | 270.8 ms       |
94| benchmark<br>1500view   | 使用QoS优化        | 236.6 ms       |
95
96## 接口说明
97
98| 接口名                                                       | 描述                                                         | 参数                                                         | 返回值                                                         |
99| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
100| OH_QoS_SetThreadQoS(QoS_Level level) | 设置当前任务的QoS等级。 | QoS_Level level | 0或-1 |
101| OH_QoS_ResetThreadQoS() | 取消当前任务设置的QoS等级。 | 无 | 0或-1 |
102| OH_QoS_GetThreadQoS(QoS_Level *level) | 获取当前任务的QoS等级。 | QoS_Level *level | 0或-1 |
103
104### 使用限制
105* QoS接口只能设置本任务的QoS等级。
106
107## 函数介绍
108
109### OH_QoS_SetThreadQoS
110
111#### 声明
112```{.c}
113int OH_QoS_SetThreadQoS(QoS_Level level);
114```
115
116#### 参数
117QoS_Level level
118* 该参数用于描述要为任务设置的QoS等级。
119
120#### 返回值
121* 若成功则返回0,失败则返回-1。
122
123#### 描述
124为某个任务设置指定的QoS等级。设置当前任务的QoS等级。开发者可以根据当前任务的重要程度,为其标记不同等级的QoS,从而获得不同的调度供给。参考[QoS实践指导](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-thread-priority-setting)125
126#### 样例
127```
128#include <stdio.h>
129#include "qos/qos.h"
130
131int func()
132{
133    // 设置当前任务的QoS等级为QOS_USER_INITIATED
134    int ret = OH_QoS_SetThreadQoS(QoS_Level::QOS_USER_INITIATED);
135
136    if (!ret) { // ret等于0说明设置成功
137        printf("set QoS Success.");
138    } else { // ret不等于0说明设置失败
139        printf("set QoS failed.");
140    }
141
142    return 0;
143}
144```
145
146### OH_QoS_ResetThreadQoS
147
148#### 声明
149```{.c}
150int OH_QoS_ResetThreadQoS();
151```
152
153#### 参数
154* 无。
155
156#### 返回值
157* 若成功则返回0,失败则返回-1。
158
159#### 描述
160取消某个任务设置的QoS等级。取消当前任务的QoS等级。参考[QoS实践指导](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-thread-priority-setting)161
162#### 样例
163```
164#include <stdio.h>
165#include "qos/qos.h"
166
167int func()
168{
169    // 重置当前任务的QoS等级
170    int ret = OH_QoS_ResetThreadQoS();
171
172    if (!ret) { // ret等于0说明重置成功
173        printf("reset QoS Success.");
174    } else { // ret不等于0说明重置失败
175        printf("reset QoS failed.");
176    }
177
178    return 0;
179}
180```
181
182### OH_QoS_GetThreadQoS
183
184#### 声明
185```{.c}
186int OH_QoS_GetThreadQoS(QoS_Level *level);
187```
188
189#### 参数
190QoS_Level *level
191* 该参数用于存储任务已经设置的QoS等级。
192
193#### 返回值
194* 若成功则返回0,失败则返回-1。
195
196#### 描述
197获取某个任务之前最近一次设置的QoS等级;如果之前未设置任何QoS等级,则返回-1。查看当前任务的QoS等级。参考[QoS实践指导](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-thread-priority-setting)198
199#### 样例
200```
201#include <stdio.h>
202#include "qos/qos.h"
203
204int func()
205{
206    // 获取当前任务的QoS等级
207    QoS_Level level = QoS_Level::QOS_DEFAULT;
208    int ret = OH_QoS_GetThreadQoS(&level);
209
210    if (!ret) { // ret等于0说明获取成功
211        printf("get QoS level %d Success.", level);
212    } else { // ret不等于0说明获取失败
213        printf("get QoS level failed.");
214    }
215
216    return 0;
217}
218```
219
220## 开发步骤
221以下步骤描述了如何使用QoS特性提供的Native API接口,调整或查询任务的QoS等级。
222
223### 1. 添加动态链接库
224QoS特性的使用依赖相关的动态链接库:**libqos.so**;需要在目标应用或程序的编译环境中添加。
225
226**示例**
227
228使用DevEco Studio创建的模板NDK工程,会默认生成CMakeLists.txt脚本,在其中添加QoS相关动态链接库示例如下:
229
230```txt
231# the minimum version of CMake.
232cmake_minimum_required(VERSION 3.4.1)
233project(qos)
234
235set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
236
237include_directories(${NATIVERENDER_ROOT_PATH}
238                    ${NATIVERENDER_ROOT_PATH}/include)
239
240add_library(entry SHARED hello.cpp)
241
242# 直接引用libqos.so原因:位于已在链接寻址路径的NDK中,无需额外声明
243target_link_libraries(entry PUBLIC libqos.so)
244```
245
246### 2. 引用头文件
247
248在使用QoS特性的源代码中需要引用相关的头文件。
249
250```c
251#include "qos/qos.h"
252```
253
254### 3. 调用QoS接口
255
256开发者根据自身需求调用相应的QoS接口调整任务的QoS等级,或者查询任务的QoS等级。
257
258