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