README_zh.md
1# C++ benchmark测试指导
2
3基准测试(benchmarking)是一种测量和评估软件性能指标的活动,可以在某个时候通过基准测试建立一个已知的性能水平(称为基准线),当系统的软硬件环境发生变化之后再进行一次基准测试以确定那些变化对性能的影响。这是基准测试最常见的用途,其他用途包括测定某种负载水平下的性能极限、管理系统或环境的变化、发现可能导致性能问题的条件等。
4
5## 用例编写
6
7```
8/*
9 * Copyright (c) 2021 XXXX Device Co., Ltd.
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 */
22
23#include <benchmark/benchmark.h>
24#include <string>
25#include <vector>
26
27using namespace std;
28
29namespace {
30 /**
31 * @tc.name: BenchmarkTestExample
32 * @tc.desc: Testcase for testing 'SimpleExample' function.
33 * @tc.type: FUNC
34 * @tc.require: Issue Number
35 */
36 size_t SimpleExample()
37 {
38 string str = "benchmark test";
39 return str.size();
40 }
41
42 static void BenchmarkTestExample(benchmark::State &state)
43 {
44 for (auto _ : state) {
45 /* @tc.steps: step1.call SimpleExample in loop */
46 SimpleExample();
47 }
48 }
49
50 /* Register the function as a benchmark */
51 BENCHMARK(BenchmarkTestExample);
52 /* Register benchmark and explicitly set the fix iterations */
53 BENCHMARK(BenchmarkTestExample)->Iterations(1000);
54
55 /**
56 * @tc.name: BenchmarkTestVectorOperator
57 * @tc.desc: Testcase for testing "AccessVectorElementByOperator"
58 * function.
59 * @tc.type: FUNC
60 * @tc.require: Issue Number
61 */
62 void AccessVectorElementByOperator()
63 {
64 constexpr int testLen = 5;
65 std::vector<int> testVec(testLen, 0);
66 for (int i = 0; i < testLen; i++) {
67 testVec[i] = i * i;
68 }
69 }
70
71 static void BenchmarkTestVectorOperator(benchmark::State &state)
72 {
73 for (auto _ : state) {
74 /* @tc.steps: step1.call AccessVectorElementByOperator in loop */
75 AccessVectorElementByOperator();
76 }
77 }
78
79 /*
80 * Register the function as a benchmark, set iterations repetitions.
81 * And set "ReportAggregatesOnly", it will display the statistics Mean,
82 * Median and Standard Deviation of Repeated Benchmarks.
83 */
84 BENCHMARK(BenchmarkTestVectorOperator)->Iterations(1000)->Repetitions(3)->
85 ReportAggregatesOnly();
86
87 /**
88 * @tc.name: BenchmarkTestVectorAt
89 * @tc.desc: Testcase for testing "AccessVectorElementByAt"
90 * function.
91 * @tc.type: FUNC
92 * @tc.require: Issue Number
93 */
94 void AccessVectorElementByAt()
95 {
96 constexpr int testLen = 5;
97 std::vector<int> testVec(testLen, 0);
98 for (int i = 0; i < testLen; i++) {
99 testVec.at(i) = i * i;
100 }
101 }
102
103 static void BenchmarkTestVectorAt(benchmark::State &state)
104 {
105 for (auto _ : state) {
106 /* @tc.steps: step1.call AccessVectorElementByAt in loop */
107 AccessVectorElementByAt();
108 }
109 }
110
111 BENCHMARK(BenchmarkTestVectorAt)->Iterations(1000)->Repetitions(3)->
112 ReportAggregatesOnly();
113
114 /**
115 * @tc.name: CalculatedAreaTestCase
116 * @tc.desc: Define a testcase that accesses a class member
117 * variable.
118 * @tc.type: FUNC
119 * @tc.require: Issue Number
120 */
121 class BenchmarkDemoTest : public benchmark::Fixture {
122 public:
123 void SetUp(const ::benchmark::State &state)
124 {
125 /* @tc.setup: width and height assigned */
126 phoneWidth_ = 1080; /* 1080 is default width */
127 phoneHeight_ = 2244; /* 2244 is default height */
128 }
129
130 void TearDown(const ::benchmark::State &state)
131 {
132 }
133
134 int phoneWidth_;
135 int phoneHeight_;
136 };
137
138 BENCHMARK_F(BenchmarkDemoTest, CalculatedAreaTestCase)(
139 benchmark::State &st)
140 {
141 long int area = 0;
142 for (auto _ : st) {
143 /* @tc.steps: step1.calculate area */
144 area = phoneWidth_ * phoneHeight_;
145 }
146 }
147
148 BENCHMARK_REGISTER_F(BenchmarkDemoTest, CalculatedAreaTestCase);
149}
150
151// Run the benchmark
152BENCHMARK_MAIN();
153```
154
155详细内容介绍:
156
1571. 添加测试用例文件头注释信息
158
159 ```
160 /*
161 * Copyright (c) 2021 XXXX Device Co., Ltd.
162 * Licensed under the Apache License, Version 2.0 (the "License");
163 * you may not use this file except in compliance with the License.
164 * You may obtain a copy of the License at
165 *
166 * http://www.apache.org/licenses/LICENSE-2.0
167 *
168 * Unless required by applicable law or agreed to in writing, software
169 * distributed under the License is distributed on an "AS IS" BASIS,
170 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
171 * See the License for the specific language governing permissions and
172 * limitations under the License.
173 */
174 ```
175
1762. 引用测试框架头文件和命名空间
177
178 ```
179 #include <benchmark/benchmark.h>
180
181 using namespace std;
182 ```
183
1843. 添加测试套引用的头文件
185
186 ```
187 #include <string>
188 #include <vector>
189 ```
190
1914. 测试用例实现
192
193 ```
194 /**
195 * @tc.name: BenchmarkTestExample
196 * @tc.desc: Testcase for testing 'SimpleExample' function.
197 * @tc.type: FUNC
198 * @tc.require: Issue Number
199 */
200 size_t SimpleExample()
201 {
202 string str = "benchmark test";
203 return str.size();
204 }
205
206 static void BenchmarkTestExample(benchmark::State &state)
207 {
208 for (auto _ : state) {
209 /* @tc.steps: step1.call SimpleExample in loop */
210 SimpleExample();
211 }
212 }
213 ```
214
2155. 向benchmark注册用例
216
217 ```
218 /* Register the function as a benchmark */
219 BENCHMARK(BenchmarkTestExample);
220 /* Register benchmark and explicitly set the fix iterations */
221 BENCHMARK(BenchmarkTestExample)->Iterations(1000);
222 ```
223
224 注册用例同时可以指定用例的执行参数,常用的参数如下表
225
226 | 参数 | 说明 |
227 | -------------------- | ------------------------ |
228 | Iterations | 测试用例迭代次数 |
229 | Repetitions | 测试用例重复执行次数 |
230 | ReportAggregatesOnly | 计算平均值、中值、标准差 |
231 | arg | 向用例函数传入参数 |
232
233 > **说明:**
234 >
235 > Iterations和Repetitions看似重复概念,实则存在差异,此处说明
236 >
237 > **Iterations**:benchmark注册的用例函数实现中均存在for循环,如demo用例BenchmarkTestExample中的for,**Iterations表示这个for循环迭代次数**
238 >
239 > **Repetitions**:表示注册的用例重复执行次数
240 >
241 > 因此若一个用例两个参数均指定,理论上用例中的函数实际执行次数为**Repetitions与Iterations的乘积**
242
243 benchmark还支持其他多种参数,具体介绍和使用参考[benchmark](https://gitee.com/openharmony/third_party_benchmark/blob/master/README.md)
244
245
246## 用例编译
247
248```
249# Copyright (c) 2021 XXXX Device Co., Ltd.
250# Licensed under the Apache License, Version 2.0 (the "License");
251# you may not use this file except in compliance with the License.
252# You may obtain a copy of the License at
253#
254# http://www.apache.org/licenses/LICENSE-2.0
255#
256# Unless required by applicable law or agreed to in writing, software
257# distributed under the License is distributed on an "AS IS" BASIS,
258# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259# See the License for the specific language governing permissions and
260# limitations under the License.
261
262import("//build/test.gni")
263
264module_output_path = "developertest/calculator"
265
266ohos_benchmarktest("BenchmarkDemoTest") {
267 module_out_path = module_output_path
268 sources = [ "benchmark_demo_test.cpp" ]
269}
270
271group("benchmarktest") {
272 testonly = true
273 deps = []
274
275 deps += [
276 # deps file
277 ":BenchmarkDemoTest",
278 ]
279}
280```
281
282详细内容如下:
283
2841. 添加文件头注释信息
285
286 ```
287 # Copyright (c) 2021 XXXX Device Co., Ltd.
288 # Licensed under the Apache License, Version 2.0 (the "License");
289 # you may not use this file except in compliance with the License.
290 # You may obtain a copy of the License at
291 #
292 # http://www.apache.org/licenses/LICENSE-2.0
293 #
294 # Unless required by applicable law or agreed to in writing, software
295 # distributed under the License is distributed on an "AS IS" BASIS,
296 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
297 # See the License for the specific language governing permissions and
298 # limitations under the License.
299 ```
300
3012. 导入编译模板文件
302
303 ```
304 import("//build/test.gni")
305 ```
306
3073. 指定文件输出路径
308
309 ```
310 module_output_path = "developertest/calculator"
311 ```
312
313> **说明:** 此处输出路径为部件/模块名。
314
3154. 指定测试套名称
316
317 ```
318 ohos_benchmarktest("BenchmarkDemoTest") {
319 module_out_path = module_output_path
320 sources = [ "benchmark_demo_test.cpp" ]
321 }
322 ```
323
3245. 对目标测试套进行分组
325
326 ```
327 group("benchmarktest") {
328 testonly = true
329 deps = []
330
331 deps += [
332 # deps file
333 ":BenchmarkDemoTest",
334 ]
335 }
336 ```
337
338 > **说明:** 进行条件分组的目的在于执行用例时可以选择性的执行某一种特定类型的用例。
339
340