13f085823Sopenharmony_ci# C++ benchmark测试指导 23f085823Sopenharmony_ci 33f085823Sopenharmony_ci基准测试(benchmarking)是一种测量和评估软件性能指标的活动,可以在某个时候通过基准测试建立一个已知的性能水平(称为基准线),当系统的软硬件环境发生变化之后再进行一次基准测试以确定那些变化对性能的影响。这是基准测试最常见的用途,其他用途包括测定某种负载水平下的性能极限、管理系统或环境的变化、发现可能导致性能问题的条件等。 43f085823Sopenharmony_ci 53f085823Sopenharmony_ci## 用例编写 63f085823Sopenharmony_ci 73f085823Sopenharmony_ci``` 83f085823Sopenharmony_ci/* 93f085823Sopenharmony_ci * Copyright (c) 2021 XXXX Device Co., Ltd. 103f085823Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 113f085823Sopenharmony_ci * you may not use this file except in compliance with the License. 123f085823Sopenharmony_ci * You may obtain a copy of the License at 133f085823Sopenharmony_ci * 143f085823Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 153f085823Sopenharmony_ci * 163f085823Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 173f085823Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 183f085823Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 193f085823Sopenharmony_ci * See the License for the specific language governing permissions and 203f085823Sopenharmony_ci * limitations under the License. 213f085823Sopenharmony_ci */ 223f085823Sopenharmony_ci 233f085823Sopenharmony_ci#include <benchmark/benchmark.h> 243f085823Sopenharmony_ci#include <string> 253f085823Sopenharmony_ci#include <vector> 263f085823Sopenharmony_ci 273f085823Sopenharmony_ciusing namespace std; 283f085823Sopenharmony_ci 293f085823Sopenharmony_cinamespace { 303f085823Sopenharmony_ci /** 313f085823Sopenharmony_ci * @tc.name: BenchmarkTestExample 323f085823Sopenharmony_ci * @tc.desc: Testcase for testing 'SimpleExample' function. 333f085823Sopenharmony_ci * @tc.type: PERF 343f085823Sopenharmony_ci * @tc.require: Issue Number 353f085823Sopenharmony_ci */ 363f085823Sopenharmony_ci size_t SimpleExample() 373f085823Sopenharmony_ci { 383f085823Sopenharmony_ci string str = "benchmark test"; 393f085823Sopenharmony_ci return str.size(); 403f085823Sopenharmony_ci } 413f085823Sopenharmony_ci 423f085823Sopenharmony_ci static void BenchmarkTestExample(benchmark::State &state) 433f085823Sopenharmony_ci { 443f085823Sopenharmony_ci for (auto _ : state) { 453f085823Sopenharmony_ci /* @tc.steps: step1.call SimpleExample in loop */ 463f085823Sopenharmony_ci SimpleExample(); 473f085823Sopenharmony_ci } 483f085823Sopenharmony_ci } 493f085823Sopenharmony_ci 503f085823Sopenharmony_ci /* Register the function as a benchmark */ 513f085823Sopenharmony_ci BENCHMARK(BenchmarkTestExample); 523f085823Sopenharmony_ci /* Register benchmark and explicitly set the fix iterations */ 533f085823Sopenharmony_ci BENCHMARK(BenchmarkTestExample)->Iterations(1000); 543f085823Sopenharmony_ci 553f085823Sopenharmony_ci /** 563f085823Sopenharmony_ci * @tc.name: BenchmarkTestVectorOperator 573f085823Sopenharmony_ci * @tc.desc: Testcase for testing "AccessVectorElementByOperator" 583f085823Sopenharmony_ci * function. 593f085823Sopenharmony_ci * @tc.type: PERF 603f085823Sopenharmony_ci * @tc.require: Issue Number 613f085823Sopenharmony_ci */ 623f085823Sopenharmony_ci void AccessVectorElementByOperator() 633f085823Sopenharmony_ci { 643f085823Sopenharmony_ci constexpr int testLen = 5; 653f085823Sopenharmony_ci std::vector<int> testVec(testLen, 0); 663f085823Sopenharmony_ci for (int i = 0; i < testLen; i++) { 673f085823Sopenharmony_ci testVec[i] = i * i; 683f085823Sopenharmony_ci } 693f085823Sopenharmony_ci } 703f085823Sopenharmony_ci 713f085823Sopenharmony_ci static void BenchmarkTestVectorOperator(benchmark::State &state) 723f085823Sopenharmony_ci { 733f085823Sopenharmony_ci for (auto _ : state) { 743f085823Sopenharmony_ci /* @tc.steps: step1.call AccessVectorElementByOperator in loop */ 753f085823Sopenharmony_ci AccessVectorElementByOperator(); 763f085823Sopenharmony_ci } 773f085823Sopenharmony_ci } 783f085823Sopenharmony_ci 793f085823Sopenharmony_ci /* 803f085823Sopenharmony_ci * Register the function as a benchmark, set iterations repetitions. 813f085823Sopenharmony_ci * And set "ReportAggregatesOnly", it will display the statistics Mean, 823f085823Sopenharmony_ci * Median and Standard Deviation of Repeated Benchmarks. 833f085823Sopenharmony_ci */ 843f085823Sopenharmony_ci BENCHMARK(BenchmarkTestVectorOperator)->Iterations(1000)->Repetitions(3)-> 853f085823Sopenharmony_ci ReportAggregatesOnly(); 863f085823Sopenharmony_ci 873f085823Sopenharmony_ci /** 883f085823Sopenharmony_ci * @tc.name: BenchmarkTestVectorAt 893f085823Sopenharmony_ci * @tc.desc: Testcase for testing "AccessVectorElementByAt" 903f085823Sopenharmony_ci * function. 913f085823Sopenharmony_ci * @tc.type: PERF 923f085823Sopenharmony_ci * @tc.require: Issue Number 933f085823Sopenharmony_ci */ 943f085823Sopenharmony_ci void AccessVectorElementByAt() 953f085823Sopenharmony_ci { 963f085823Sopenharmony_ci constexpr int testLen = 5; 973f085823Sopenharmony_ci std::vector<int> testVec(testLen, 0); 983f085823Sopenharmony_ci for (int i = 0; i < testLen; i++) { 993f085823Sopenharmony_ci testVec.at(i) = i * i; 1003f085823Sopenharmony_ci } 1013f085823Sopenharmony_ci } 1023f085823Sopenharmony_ci 1033f085823Sopenharmony_ci static void BenchmarkTestVectorAt(benchmark::State &state) 1043f085823Sopenharmony_ci { 1053f085823Sopenharmony_ci for (auto _ : state) { 1063f085823Sopenharmony_ci /* @tc.steps: step1.call AccessVectorElementByAt in loop */ 1073f085823Sopenharmony_ci AccessVectorElementByAt(); 1083f085823Sopenharmony_ci } 1093f085823Sopenharmony_ci } 1103f085823Sopenharmony_ci 1113f085823Sopenharmony_ci BENCHMARK(BenchmarkTestVectorAt)->Iterations(1000)->Repetitions(3)-> 1123f085823Sopenharmony_ci ReportAggregatesOnly(); 1133f085823Sopenharmony_ci 1143f085823Sopenharmony_ci /** 1153f085823Sopenharmony_ci * @tc.name: CalculatedAreaTestCase 1163f085823Sopenharmony_ci * @tc.desc: Define a testcase that accesses a class member 1173f085823Sopenharmony_ci * variable. 1183f085823Sopenharmony_ci * @tc.type: PERF 1193f085823Sopenharmony_ci * @tc.require: Issue Number 1203f085823Sopenharmony_ci */ 1213f085823Sopenharmony_ci class BenchmarkDemoTest : public benchmark::Fixture { 1223f085823Sopenharmony_ci public: 1233f085823Sopenharmony_ci void SetUp(const ::benchmark::State &state) 1243f085823Sopenharmony_ci { 1253f085823Sopenharmony_ci /* @tc.setup: width and height assigned */ 1263f085823Sopenharmony_ci phoneWidth_ = 1080; /* 1080 is default width */ 1273f085823Sopenharmony_ci phoneHeight_ = 2244; /* 2244 is default height */ 1283f085823Sopenharmony_ci } 1293f085823Sopenharmony_ci 1303f085823Sopenharmony_ci void TearDown(const ::benchmark::State &state) 1313f085823Sopenharmony_ci { 1323f085823Sopenharmony_ci } 1333f085823Sopenharmony_ci 1343f085823Sopenharmony_ci int phoneWidth_; 1353f085823Sopenharmony_ci int phoneHeight_; 1363f085823Sopenharmony_ci }; 1373f085823Sopenharmony_ci 1383f085823Sopenharmony_ci BENCHMARK_F(BenchmarkDemoTest, CalculatedAreaTestCase)( 1393f085823Sopenharmony_ci benchmark::State &st) 1403f085823Sopenharmony_ci { 1413f085823Sopenharmony_ci long int area = 0; 1423f085823Sopenharmony_ci for (auto _ : st) { 1433f085823Sopenharmony_ci /* @tc.steps: step1.calculate area */ 1443f085823Sopenharmony_ci area = phoneWidth_ * phoneHeight_; 1453f085823Sopenharmony_ci } 1463f085823Sopenharmony_ci } 1473f085823Sopenharmony_ci 1483f085823Sopenharmony_ci BENCHMARK_REGISTER_F(BenchmarkDemoTest, CalculatedAreaTestCase); 1493f085823Sopenharmony_ci} 1503f085823Sopenharmony_ci 1513f085823Sopenharmony_ci// Run the benchmark 1523f085823Sopenharmony_ciBENCHMARK_MAIN(); 1533f085823Sopenharmony_ci``` 1543f085823Sopenharmony_ci 1553f085823Sopenharmony_ci详细内容介绍: 1563f085823Sopenharmony_ci 1573f085823Sopenharmony_ci1. 添加测试用例文件头注释信息 1583f085823Sopenharmony_ci 1593f085823Sopenharmony_ci ``` 1603f085823Sopenharmony_ci /* 1613f085823Sopenharmony_ci * Copyright (c) 2021 XXXX Device Co., Ltd. 1623f085823Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 1633f085823Sopenharmony_ci * you may not use this file except in compliance with the License. 1643f085823Sopenharmony_ci * You may obtain a copy of the License at 1653f085823Sopenharmony_ci * 1663f085823Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 1673f085823Sopenharmony_ci * 1683f085823Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1693f085823Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1703f085823Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1713f085823Sopenharmony_ci * See the License for the specific language governing permissions and 1723f085823Sopenharmony_ci * limitations under the License. 1733f085823Sopenharmony_ci */ 1743f085823Sopenharmony_ci ``` 1753f085823Sopenharmony_ci 1763f085823Sopenharmony_ci2. 引用测试框架头文件和命名空间 1773f085823Sopenharmony_ci 1783f085823Sopenharmony_ci ``` 1793f085823Sopenharmony_ci #include <benchmark/benchmark.h> 1803f085823Sopenharmony_ci 1813f085823Sopenharmony_ci using namespace std; 1823f085823Sopenharmony_ci ``` 1833f085823Sopenharmony_ci 1843f085823Sopenharmony_ci3. 添加测试套引用的头文件 1853f085823Sopenharmony_ci 1863f085823Sopenharmony_ci ``` 1873f085823Sopenharmony_ci #include <string> 1883f085823Sopenharmony_ci #include <vector> 1893f085823Sopenharmony_ci ``` 1903f085823Sopenharmony_ci 1913f085823Sopenharmony_ci4. 测试用例实现 1923f085823Sopenharmony_ci 1933f085823Sopenharmony_ci ``` 1943f085823Sopenharmony_ci /** 1953f085823Sopenharmony_ci * @tc.name: BenchmarkTestExample 1963f085823Sopenharmony_ci * @tc.desc: Testcase for testing 'SimpleExample' function. 1973f085823Sopenharmony_ci * @tc.type: PERF 1983f085823Sopenharmony_ci * @tc.require: Issue Number 1993f085823Sopenharmony_ci */ 2003f085823Sopenharmony_ci size_t SimpleExample() 2013f085823Sopenharmony_ci { 2023f085823Sopenharmony_ci string str = "benchmark test"; 2033f085823Sopenharmony_ci return str.size(); 2043f085823Sopenharmony_ci } 2053f085823Sopenharmony_ci 2063f085823Sopenharmony_ci static void BenchmarkTestExample(benchmark::State &state) 2073f085823Sopenharmony_ci { 2083f085823Sopenharmony_ci for (auto _ : state) { 2093f085823Sopenharmony_ci /* @tc.steps: step1.call SimpleExample in loop */ 2103f085823Sopenharmony_ci SimpleExample(); 2113f085823Sopenharmony_ci } 2123f085823Sopenharmony_ci } 2133f085823Sopenharmony_ci ``` 2143f085823Sopenharmony_ci > **注意:** 2153f085823Sopenharmony_ci > 测试用例名称不要过长,否则会造成测试报告无法生成。 2163f085823Sopenharmony_ci 2173f085823Sopenharmony_ci5. 向benchmark注册用例 2183f085823Sopenharmony_ci 2193f085823Sopenharmony_ci ``` 2203f085823Sopenharmony_ci /* Register the function as a benchmark */ 2213f085823Sopenharmony_ci BENCHMARK(BenchmarkTestExample); 2223f085823Sopenharmony_ci /* Register benchmark and explicitly set the fix iterations */ 2233f085823Sopenharmony_ci BENCHMARK(BenchmarkTestExample)->Iterations(1000); 2243f085823Sopenharmony_ci ``` 2253f085823Sopenharmony_ci 2263f085823Sopenharmony_ci 注册用例同时可以指定用例的执行参数,常用的参数如下表 2273f085823Sopenharmony_ci 2283f085823Sopenharmony_ci | 参数 | 说明 | 2293f085823Sopenharmony_ci | -------------------- | ------------------------ | 2303f085823Sopenharmony_ci | Iterations | 测试用例迭代次数 | 2313f085823Sopenharmony_ci | Repetitions | 测试用例重复执行次数 | 2323f085823Sopenharmony_ci | ReportAggregatesOnly | 计算平均值、中值、标准差 | 2333f085823Sopenharmony_ci | arg | 向用例函数传入参数 | 2343f085823Sopenharmony_ci 2353f085823Sopenharmony_ci > **说明:** 2363f085823Sopenharmony_ci > 2373f085823Sopenharmony_ci > Iterations和Repetitions看似重复概念,实则存在差异,此处说明 2383f085823Sopenharmony_ci > 2393f085823Sopenharmony_ci > **Iterations**:benchmark注册的用例函数实现中均存在for循环,如demo用例BenchmarkTestExample中的for,**Iterations表示这个for循环迭代次数** 2403f085823Sopenharmony_ci > 2413f085823Sopenharmony_ci > **Repetitions**:表示注册的用例重复执行次数 2423f085823Sopenharmony_ci > 2433f085823Sopenharmony_ci > 因此若一个用例两个参数均指定,理论上用例中的函数实际执行次数为**Repetitions与Iterations的乘积** 2443f085823Sopenharmony_ci 2453f085823Sopenharmony_ci benchmark还支持其他多种参数,具体介绍和使用参考[benchmark](https://gitee.com/openharmony/third_party_benchmark) 2463f085823Sopenharmony_ci 2473f085823Sopenharmony_ci 2483f085823Sopenharmony_ci## 用例编译 2493f085823Sopenharmony_ci 2503f085823Sopenharmony_ci``` 2513f085823Sopenharmony_ci# Copyright (c) 2021 XXXX Device Co., Ltd. 2523f085823Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 2533f085823Sopenharmony_ci# you may not use this file except in compliance with the License. 2543f085823Sopenharmony_ci# You may obtain a copy of the License at 2553f085823Sopenharmony_ci# 2563f085823Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 2573f085823Sopenharmony_ci# 2583f085823Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 2593f085823Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 2603f085823Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2613f085823Sopenharmony_ci# See the License for the specific language governing permissions and 2623f085823Sopenharmony_ci# limitations under the License. 2633f085823Sopenharmony_ci 2643f085823Sopenharmony_ciimport("//build/test.gni") 2653f085823Sopenharmony_ci 2663f085823Sopenharmony_cimodule_output_path = "developer_test/calculator" 2673f085823Sopenharmony_ci 2683f085823Sopenharmony_ciohos_benchmarktest("BenchmarkDemoTest") { 2693f085823Sopenharmony_ci module_out_path = module_output_path 2703f085823Sopenharmony_ci sources = [ "benchmark_demo_test.cpp" ] 2713f085823Sopenharmony_ci} 2723f085823Sopenharmony_ci 2733f085823Sopenharmony_cigroup("benchmarktest") { 2743f085823Sopenharmony_ci testonly = true 2753f085823Sopenharmony_ci deps = [] 2763f085823Sopenharmony_ci 2773f085823Sopenharmony_ci deps += [ 2783f085823Sopenharmony_ci # deps file 2793f085823Sopenharmony_ci ":BenchmarkDemoTest", 2803f085823Sopenharmony_ci ] 2813f085823Sopenharmony_ci} 2823f085823Sopenharmony_ci``` 2833f085823Sopenharmony_ci 2843f085823Sopenharmony_ci详细内容如下: 2853f085823Sopenharmony_ci 2863f085823Sopenharmony_ci1. 添加文件头注释信息 2873f085823Sopenharmony_ci 2883f085823Sopenharmony_ci ``` 2893f085823Sopenharmony_ci # Copyright (c) 2021 XXXX Device Co., Ltd. 2903f085823Sopenharmony_ci # Licensed under the Apache License, Version 2.0 (the "License"); 2913f085823Sopenharmony_ci # you may not use this file except in compliance with the License. 2923f085823Sopenharmony_ci # You may obtain a copy of the License at 2933f085823Sopenharmony_ci # 2943f085823Sopenharmony_ci # http://www.apache.org/licenses/LICENSE-2.0 2953f085823Sopenharmony_ci # 2963f085823Sopenharmony_ci # Unless required by applicable law or agreed to in writing, software 2973f085823Sopenharmony_ci # distributed under the License is distributed on an "AS IS" BASIS, 2983f085823Sopenharmony_ci # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2993f085823Sopenharmony_ci # See the License for the specific language governing permissions and 3003f085823Sopenharmony_ci # limitations under the License. 3013f085823Sopenharmony_ci ``` 3023f085823Sopenharmony_ci 3033f085823Sopenharmony_ci2. 导入编译模板文件 3043f085823Sopenharmony_ci 3053f085823Sopenharmony_ci ``` 3063f085823Sopenharmony_ci import("//build/test.gni") 3073f085823Sopenharmony_ci ``` 3083f085823Sopenharmony_ci 3093f085823Sopenharmony_ci3. 指定文件输出路径 3103f085823Sopenharmony_ci 3113f085823Sopenharmony_ci ``` 3123f085823Sopenharmony_ci module_output_path = "developer_test/calculator" 3133f085823Sopenharmony_ci ``` 3143f085823Sopenharmony_ci 3153f085823Sopenharmony_ci> **说明:** 此处输出路径为部件/模块名。 3163f085823Sopenharmony_ci 3173f085823Sopenharmony_ci4. 指定测试套名称 3183f085823Sopenharmony_ci 3193f085823Sopenharmony_ci ``` 3203f085823Sopenharmony_ci ohos_benchmarktest("BenchmarkDemoTest") { 3213f085823Sopenharmony_ci module_out_path = module_output_path 3223f085823Sopenharmony_ci sources = [ "benchmark_demo_test.cpp" ] 3233f085823Sopenharmony_ci } 3243f085823Sopenharmony_ci ``` 3253f085823Sopenharmony_ci 3263f085823Sopenharmony_ci5. 对目标测试套进行分组 3273f085823Sopenharmony_ci 3283f085823Sopenharmony_ci ``` 3293f085823Sopenharmony_ci group("benchmarktest") { 3303f085823Sopenharmony_ci testonly = true 3313f085823Sopenharmony_ci deps = [] 3323f085823Sopenharmony_ci 3333f085823Sopenharmony_ci deps += [ 3343f085823Sopenharmony_ci # deps file 3353f085823Sopenharmony_ci ":BenchmarkDemoTest", 3363f085823Sopenharmony_ci ] 3373f085823Sopenharmony_ci } 3383f085823Sopenharmony_ci ``` 3393f085823Sopenharmony_ci 3403f085823Sopenharmony_ci > **说明:** 进行条件分组的目的在于执行用例时可以选择性的执行某一种特定类型的用例。 3413f085823Sopenharmony_ci 342