当前位置: 首页 > news >正文

代码性能测试——benchmark库

在平常的代码开发中,我们一般用googletest做单元测试用例,如果需要对代码如某个函数的执行时间或效率进行测量,一般用benchmark

目录

  • 1.benchmark 安装
  • 2.benchmark 介绍
    • 2.1 示例
    • 2.2 benchmark 测试说明
    • 2.3 benchmark 计时
  • 3.示例
    • 测试kdTree()耗时
    • 测量排序算法性能

benchmark 是一个用于性能测试和基准测试的库。它主要用于测量代码执行的时间、效率等性能指标,帮助开发者评估不同实现之间的效率差异,或者测试特定代码片段在不同环境下的表现。

具体来说,benchmark 的作用包括:

  • 性能测量:能够精确测量代码的执行时间,可以帮助开发者识别性能瓶颈。
  • 比较不同实现:通过对比多个实现的执行时间,帮助开发者选择最优方案。
  • 自动化基准测试:自动执行测试,减少人工干预,可以用于自动化性能评估。
  • 准确性:通过多次运行来消除偶然的误差,提供更稳定的数据。

1.benchmark 安装

  • 下载 benchmark 库

https://github.com/google/benchmark.git

  • 编译 benchmark 库
    创建一个构建目录并使用CMake进行编译和安装:
git clone https://github.com/google/benchmark.git
git clone https://github.com/google/googletest.git benchmark/googletest # 因为编译benchmark需要googletestcd benchmark
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install # 安装到系统目录下

2.benchmark 介绍

2.1 示例

#include <benchmark/benchmark.h>static void BM_SomeFunction(benchmark::State& state) {
// 在此处执行设置  
for (auto _ : state) {// 此代码获得计时SomeFunction();benchmark::DoNotOptimize();}}// 将该函数作为benchmark
BENCHMARK(BM_SomeFunction);
// 运行benchmark测试
BENCHMARK_MAIN();
  • benchmark::State& state:是 Google Benchmark 提供的一个状态对象,用于控制测试的执行。state 管理测试循环,保证代码在性能测试过程中多次执行,以获得稳定的性能结果。
  • for (auto _ : state):是一个范围循环,benchmark::State 对象提供了类似范围的迭代支持。该循环将根据 Google Benchmark 自动确定的迭代次数运行测试代码,直到Google Benchmark认为已经收集到足够的数据为止。这种结构确保每次运行都具有相同的执行环境,帮助减少外部噪声带来的影响。
  • benchmark::DoNotOptimize():是 Google Benchmark 提供的一个工具函数,用来防止编译器对测试代码进行优化。以确保测试中的代码不会被跳过或优化掉。这样可以确保测试结果更接近真实性能。
  • BENCHMARK(BM_SomeFunction):这行代码注册了定义的 BM_SomeFunction 的benchmark测试,让 Google Benchmark 能够在主函数中自动调用。
  • BENCHMARK_MAIN():是 Google Benchmark 的主函数入口,它会自动运行所有注册的benchmark测试。

2.2 benchmark 测试说明

for (auto _ : state) 循环中插入想要测试的代码,Benchmark 会多次执行该代码,并统计每次运行的时间,最终输出平均执行时间、CPU时间等。

默认情况下,Benchmark会自动测量每次迭代的时间。但有时可能需要排除一些准备工作的时间,可以使用state.PauseTiming()state.ResumeTiming()来暂停和恢复计时:

for (auto _ : state) {state.PauseTiming();// 不需要计入时间的函数SomeFunctionNoTimekeeping();state.ResumeTiming();SomeFunction();
}

2.3 benchmark 计时

Benchmark 库使用标准库中的 std::chrono 提供的高精度时钟(通常是 std::chrono::high_resolution_clock)来进行计时。这是C++中的高精度时钟,通常提供纳秒级别的精度,在运行代码之前和之后记录时钟时间,计算代码执行所耗费的时间。

Benchmark 的 State 类会控制迭代次数,并在性能测试开始和结束时调用时钟进行时间测量。

benchmark::State 会自动控制测试运行的起始时间、迭代次数和循环。在测试完成后,Benchmark 会汇总这些数据,输出迭代次数、平均执行时间等性能指标。

3.示例

测试kdTree()耗时

#include <pcl/console/time.h>
#include <pcl/point_cloud.h> //点类型定义头文件
#include <pcl/kdtree/kdtree_flann.h> //kdtree类定义头文件int kdTreeTest()
{srand(time(NULL)); //用系统时间初始化随机种子//创建一个PointCloud<pcl::PointXYZ>pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);// 随机点云生成cloud->width  = 1000; //此处点云数量cloud->height = 1;    //表示点云为无序点云cloud->points.resize(cloud->width * cloud->height);for (size_t i = 0; i < cloud->points.size(); ++i) //循环填充点云数据{cloud->points[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f); // // 产生数值为0-1024的浮点数cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);}//创建KdTreeFLANN对象,并把创建的点云设置为输入,创建一个searchPoint变量作为查询点pcl::KdTreeFLANN<pcl::PointXYZ> kdtree; // pcl::KdTreeFLANN<PointT, Dist>::setInputCloud (const PointCloudConstPtr// &cloud, const IndicesConstPtr &indices)//设置搜索空间kdtree.setInputCloud(cloud);//设置查询点并赋随机值pcl::PointXYZ searchPoint;searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f);searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f);searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);// K 临近搜索//创建一个整数(设置为10)和两个向量来存储搜索到的K近邻,两个向量中,一个存储搜索到查询点近邻的索引,另一个存储对应近邻的距离平方int K = 10;std::vector<int> pointIdxNKNSearch(K);         //存储查询点近邻索引std::vector<float> pointNKNSquaredDistance(K); //存储近邻点对应距离平方//打印相关信息std::cout << "K nearest neighbor search at (" << searchPoint.x << " " << searchPoint.y << " " << searchPoint.z<< ") with K=" << K << std::endl;if (kdtree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0) //执行K近邻搜索{//打印所有近邻坐标for (size_t i = 0; i < pointIdxNKNSearch.size(); ++i)std::cout << "    " << cloud->points[pointIdxNKNSearch[i]].x << " " << cloud->points[pointIdxNKNSearch[i]].y<< " " << cloud->points[pointIdxNKNSearch[i]].z<< " (squared distance: " << pointNKNSquaredDistance[i] << ")" << std::endl;}/**********************************************************************************下面的代码展示查找到给定的searchPoint的某一半径(随机产生)内所有近邻,重新定义两个向量pointIdxRadiusSearch  pointRadiusSquaredDistance来存储关于近邻的信息********************************************************************************/// 半径 R内近邻搜索方法std::vector<int> pointIdxRadiusSearch;         //存储近邻索引std::vector<float> pointRadiusSquaredDistance; //存储近邻对应距离的平方float radius = 256.0f * rand() / (RAND_MAX + 1.0f); //随机的生成某一半径//打印输出std::cout << "Neighbors within radius search at (" << searchPoint.x << " " << searchPoint.y << " " << searchPoint.z<< ") with radius=" << radius << std::endl;// 假设我们的kdtree返回了大于0个近邻。那么它将打印出在我们"searchPoint"附近的10个最近的邻居并把它们存到先前创立的向量中。if (kdtree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) >0) //执行半径R内近邻搜索方法{for (size_t i = 0; i < pointIdxRadiusSearch.size(); ++i)std::cout << "    " << cloud->points[pointIdxRadiusSearch[i]].x << " "<< cloud->points[pointIdxRadiusSearch[i]].y << " " << cloud->points[pointIdxRadiusSearch[i]].z<< " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;}return 0;
}#include <benchmark/benchmark.h>
#include <gtest/gtest.h>static void BM_Kdtree(benchmark::State &state)
{// 运行基准测试for (auto _ : state) {kdTreeTest();}
}
// 注册基准测试
BENCHMARK(BM_Kdtree);BENCHMARK_MAIN();

输出:
在这里插入图片描述

测量排序算法性能

#include <benchmark/benchmark.h>
#include <vector>
#include <algorithm>// 选择排序算法
void selectionSort(std::vector<int>& arr) {for (size_t i = 0; i < arr.size(); ++i) {size_t minIdx = i;for (size_t j = i + 1; j < arr.size(); ++j) {if (arr[j] < arr[minIdx]) {minIdx = j;}}std::swap(arr[i], arr[minIdx]);}
}// 快速排序算法
void quickSort(std::vector<int>& arr, int low, int high) {if (low < high) {int pivot = arr[high];int i = low - 1;for (int j = low; j < high; ++j) {if (arr[j] < pivot) {++i;std::swap(arr[i], arr[j]);}}std::swap(arr[i + 1], arr[high]);int pi = i + 1;quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}
}// 基准测试函数,使用 Google Benchmark 库
static void BM_SelectionSort(benchmark::State& state) {std::vector<int> arr = {5, 2, 9, 1, 5, 6};for (auto _ : state) {selectionSort(arr);}
}// 快速排序基准测试
static void BM_QuickSort(benchmark::State& state) {std::vector<int> arr = {5, 2, 9, 1, 5, 6};for (auto _ : state) {quickSort(arr, 0, arr.size() - 1);}
}// 注册基准测试
BENCHMARK(BM_SelectionSort);
BENCHMARK(BM_QuickSort);// 定义测试入口
BENCHMARK_MAIN();

输出:

2025-08-24T22:37:58+08:00
Running ./three_dim_test
Run on (20 X 4600 MHz CPU s)
CPU Caches:L1 Data 48 KiB (x10)L1 Instruction 32 KiB (x10)L2 Unified 1280 KiB (x10)L3 Unified 24576 KiB (x1)
Load Average: 0.88, 0.85, 0.80
-----------------------------------------------------------
Benchmark                 Time             CPU   Iterations
-----------------------------------------------------------
BM_SelectionSort        160 ns          160 ns      4371089
BM_QuickSort            217 ns          218 ns      3213221
http://www.xdnf.cn/news/1358173.html

相关文章:

  • 基于Spring Boot与Redis的电商场景面试问答解析
  • Python训练营打卡 DAY 46 通道注意力(SE注意力)
  • 【数据结构】排序算法全解析
  • Linux服务实验
  • [论文阅读] 软件工程 | GPS算法:用“路径摘要”当向导,软件模型检测从此告别“瞎找bug”
  • Kaggle项目:一次 Uber 出行数据分析的完整思路
  • 【机器学习】 11 Mixture models and the EM algorithm
  • 如何捕获组件的异常情况
  • Node.js依赖管理与install及run命令详解
  • Redis实战-缓存的解决方案(一)
  • Flink直接缓冲存储器异常解析与解决方案
  • comfyUI背后的一些技术——CLIP
  • 暗影哨兵:安全运维的隐秘防线
  • 高并发AI服务部署方案:vLLM、TGI、FastChat性能压测报告
  • 使用 Fargate 在 AWS ECS 上运行 Spring Boot 应用程序
  • QML Charts组件之坐标轴示例
  • maven私服架构
  • Tesla智能座舱域控制器(MCU)的系统化梳理
  • ChainVault:重塑亚洲黄金交易基建,引领RWA金融新浪潮
  • Vue 3多语言应用开发实战:vue-i18n深度解析与最佳实践
  • 项目学习总结(4)
  • 【(含模板)滑动窗口 - LeetCode】3. 无重复字符的最长子串
  • 基于深度学习的餐盘清洁状态分类
  • 基于stm32汽车雨刮器控制系统设计
  • 普元低代码开发平台:开启企业高效创新新征程
  • SQL Server从入门到项目实践(超值版)读书笔记 24
  • 【C++】 9. vector
  • 线段树相关算法题(2)
  • 3D打印机管理后台与RabbitMQ集成的业务场景
  • Windows Server存储副本智能同步优化方案