c++性能測試工具:google benchmark入門(一)
如果你正在尋找一款c++性能測試工具,那麽這篇文章是不容錯過的。
市面上的benchmark工具或多或少存在一些使用上的不便,那麽是否存在一個使用簡便又功能強大的性能測試工具呢?答案是google/benchmark。
google/benchmark是一個由Google開發的基於googletest框架的c++ benchmark工具,它易於安裝和使用,並提供了全面的性能測試接口。
下面我將介紹google/benchmark的安裝並用一個簡短的例子介紹它的簡單使用。
安裝google/benchmark
google/benchmark基於c++11標準和googletest框架,所以安裝前需要先做一些準備工作。
首先是安裝g++和cmake。
Debian/Ubuntu:
sudo apt install g++ cmake
Arch Linux/Manjaro Linux:
sudo pacman -s g++ cmake
確保你的g++版本在5.0以上,否則可能不能很好地支持c++11的某些特性。
然後是googletest框架,你可以選擇單獨安裝,不過這裏我選擇將其作為benchmark源碼樹的依賴而不單獨安裝它,因為benchmark在編譯安裝時需要googletest但是在使用時並不需要,為了篇幅我們選擇後者。
準備工作完成後選擇一個合適的目錄,然後運行下面的命令:
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 # 如果想全局安裝就接著運行下面的命令 sudo make install
頭文件會被安裝至/usr/local/include
,庫文件會安裝至/usr/local/lib
。
現在安裝完成了,我們來看看benchmark如何使用。
google/benchmark的簡單使用
我們的例子將會對比三種訪問std::array
容器內元素方法的性能,進而演示benchmark的使用方法。
先看代碼:
#include <benchmark/benchmark.h> #include <array> constexpr int len = 6; // constexpr function具有inline屬性,你應該把它放在頭文件中 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,它會返回容器內元素的引用,並在編譯期檢查數組的索引是否正確 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&)>
的函數,其中benchmark::State&
負責測試的運行及額外參數的傳遞。
隨後我們使用for (auto _: state) {}
來運行需要測試的內容,state會選擇合適的次數來運行循環,時間的計算從循環內的語句開始,所以我們可以選擇像例子中一樣在for循環之外初始化測試環境,然後在循環體內編寫需要測試的代碼。
測試用例編寫完成後我們需要使用BENCHMARK(<function_name>);
將我們的測試用例註冊進benchmark,這樣程序運行時才會執行我們的測試。
最後是用BENCHMARK_MAIN();
替代直接編寫的main函數,它會處理命令行參數並運行所有註冊過的測試用例生成測試結果。
示例中大量使用了constexpt,這是為了能在編譯期計算出需要的數值避免對測試產生太多噪音。
然後我們編譯測試程序:
g++ -Wall -std=c++14 -pthread -lbenchmark benchmark_example.cpp
benchmark需要鏈接libbenchmark.so
,所以需要指定-lbenchmark
,此外還需要thread的支持,因為libstdc++不提供thread的底層實現,我們需要pthread。另外不建議使用-lpthread
,官方表示會出現兼容問題,在我這測試也會出現鏈接錯誤。
編譯好程序後就可以運行測試了:
顯示的警告信息表示在當前系統環境有一些噪音(例如其他在運行的程序)可能導致結果不太準確,並不影響我們的測試。
測試結果與預期基本相符,std::get
最快,at()
最慢。
以上就是google/benchmark的安裝和簡單使用,下一篇文章中我會介紹更多使用benchmark的技巧,如有錯誤歡迎指正。
c++性能測試工具:google benchmark入門(一)