如果你正在尋找一款c++性能測試工具绊谭,那么這篇文章是不容錯過的。
市面上的benchmark工具或多或少存在一些使用上的不便汪拥,那么是否存在一個使用簡便又功能強(qiáng)大的性能測試工具呢达传?答案是google/benchmark。
google/benchmark是一個由Google開發(fā)的基于googletest框架的c++ benchmark工具迫筑,它易于安裝和使用宪赶,并提供了全面的性能測試接口。
下面我將介紹google/benchmark的安裝并用一個簡短的例子介紹它的簡單使用脯燃。
安裝google/benchmark
google/benchmark基于c++11標(biāo)準(zhǔn)和googletest框架搂妻,所以安裝前需要先做一些準(zhǔn)備工作。
首先是安裝g++和cmake辕棚。
Debian/Ubuntu:
sudo apt install g++ cmake
Arch Linux/Manjaro Linux:
sudo pacman -s g++ cmake
確保你的g++版本在5.0以上欲主,否則可能不能很好地支持c++11的某些特性邓厕。
然后是googletest框架,你可以選擇單獨(dú)安裝岛蚤,不過這里我選擇將其作為benchmark源碼樹的依賴而不單獨(dú)安裝它邑狸,因?yàn)閎enchmark在編譯安裝時需要googletest但是在使用時并不需要,為了篇幅我們選擇后者涤妒。
小編是一個有著6年工作經(jīng)驗(yàn)的工程師单雾,關(guān)于C++,編程她紫,自己有做材料的整合硅堆,一個完整的C++編程學(xué)習(xí)路線,學(xué)習(xí)資料和工具贿讹,能夠進(jìn)我的群7253渐逃,-91790收取,免費(fèi)送給大家民褂,希望你也能憑著自己的努力茄菊,成為下一個優(yōu)秀的程序員
準(zhǔn)備工作完成后選擇一個合適的目錄,然后運(yùn)行下面的命令:
git clone https://github.com/google/benchmark.git
git clone https://github.com/google/googletest.git benchmark/googletest
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=RELEASE ../benchmark
make -j4
# 如果想全局安裝就接著運(yùn)行下面的命令
sudo make install
頭文件會被安裝至/usr/local/include赊堪,庫文件會安裝至/usr/local/lib面殖。
現(xiàn)在安裝完成了,我們來看看benchmark如何使用哭廉。
google/benchmark的簡單使用
我們的例子將會對比三種訪問std::array容器內(nèi)元素方法的性能脊僚,進(jìn)而演示benchmark的使用方法。
先看代碼:
#include <benchmark/benchmark.h>
#include <array>
constexpr int len = 6;
// constexpr function具有inline屬性遵绰,你應(yīng)該把它放在頭文件中
constexpr auto my_pow(const int i)
{
return i * i;
}
// 使用operator[]讀取元素辽幌,依次存入1-6的平方
static void bench_array_operator(benchmark::State& state)
{
std::array<int, len> arr;
constexpr int i = 1;
for (auto _: state) {
arr[0] = my_pow(i);
arr[1] = my_pow(i+1);
arr[2] = my_pow(i+2);
arr[3] = my_pow(i+3);
arr[4] = my_pow(i+4);
arr[5] = my_pow(i+5);
}
}
BENCHMARK(bench_array_operator);
// 使用at()讀取元素,依次存入1-6的平方
static void bench_array_at(benchmark::State& state)
{
std::array<int, len> arr;
constexpr int i = 1;
for (auto _: state) {
arr.at(0) = my_pow(i);
arr.at(1) = my_pow(i+1);
arr.at(2) = my_pow(i+2);
arr.at(3) = my_pow(i+3);
arr.at(4) = my_pow(i+4);
arr.at(5) = my_pow(i+5);
}
}
BENCHMARK(bench_array_at);
// std::get<>(array)是一個constexpr function椿访,它會返回容器內(nèi)元素的引用乌企,并在編譯期檢查數(shù)組的索引是否正確
static void bench_array_get(benchmark::State& state)
{
std::array<int, len> arr;
constexpr int i = 1;
for (auto _: state) {
std::get<0>(arr) = my_pow(i);
std::get<1>(arr) = my_pow(i+1);
std::get<2>(arr) = my_pow(i+2);
std::get<3>(arr) = my_pow(i+3);
std::get<4>(arr) = my_pow(i+4);
std::get<5>(arr) = my_pow(i+5);
}
}
BENCHMARK(bench_array_get);
BENCHMARK_MAIN();
我們可以看到每一個benchmark測試用例都是一個類型為std::function<void(benchmark::State&)>的函數(shù),其中benchmark::State&負(fù)責(zé)測試的運(yùn)行及額外參數(shù)的傳遞赎离。
隨后我們使用for (auto _: state) {}來運(yùn)行需要測試的內(nèi)容逛犹,state會選擇合適的次數(shù)來運(yùn)行循環(huán),時間的計(jì)算從循環(huán)內(nèi)的語句開始梁剔,所以我們可以選擇像例子中一樣在for循環(huán)之外初始化測試環(huán)境虽画,然后在循環(huán)體內(nèi)編寫需要測試的代碼。
測試用例編寫完成后我們需要使用BENCHMARK(<function_name>);將我們的測試用例注冊進(jìn)benchmark荣病,這樣程序運(yùn)行時才會執(zhí)行我們的測試码撰。
最后是用BENCHMARK_MAIN();替代直接編寫的main函數(shù),它會處理命令行參數(shù)并運(yùn)行所有注冊過的測試用例生成測試結(jié)果个盆。
示例中大量使用了constexpt脖岛,這是為了能在編譯期計(jì)算出需要的數(shù)值避免對測試產(chǎn)生太多噪音朵栖。
然后我們編譯測試程序:
g++ -Wall -std=c++14 -pthread -lbenchmark benchmark_example.cpp
benchmark需要鏈接libbenchmark.so,所以需要指定-lbenchmark柴梆,此外還需要thread的支持陨溅,因?yàn)閘ibstdc++不提供thread的底層實(shí)現(xiàn),我們需要pthread绍在。另外不建議使用-lpthread门扇,官方表示會出現(xiàn)兼容問題,在我這測試也會出現(xiàn)鏈接錯誤偿渡。
編譯好程序后就可以運(yùn)行測試了:
顯示的警告信息表示在當(dāng)前系統(tǒng)環(huán)境有一些噪音(例如其他在運(yùn)行的程序)可能導(dǎo)致結(jié)果不太準(zhǔn)確臼寄,并不影響我們的測試。
測試結(jié)果與預(yù)期基本相符溜宽,std::get最快吉拳,at()最慢。
以上就是google/benchmark的安裝和簡單使用适揉,