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