c++性能測試工具:google benchmark入門(一)

若是你正在尋找一款c++性能測試工具,那麼這篇文章是不容錯過的。c++

市面上的benchmark工具或多或少存在一些使用上的不便,那麼是否存在一個使用簡便又功能強大的性能測試工具呢?答案是google/benchmarkgit

google/benchmark是一個由Google開發的基於googletest框架的c++ benchmark工具,它易於安裝和使用,並提供了全面的性能測試接口。github

下面我將介紹google/benchmark的安裝並用一個簡短的例子介紹它的簡單使用。api

安裝google/benchmark

google/benchmark基於c++11標準和googletest框架,因此安裝前須要先作一些準備工做。數組

首先是安裝g++和cmake。bash

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 benchmark_example.cpp -pthread -lbenchmark

benchmark須要連接libbenchmark.so,因此須要指定-lbenchmark,此外還須要thread的支持,由於libstdc++不提供thread的底層實現,咱們須要pthread。另外不建議使用-lpthread,官方表示會出現兼容問題,在我這測試也會出現連接錯誤。注意文件名必定要在-lbenchmark前面,不然編譯會失敗,具體參見:https://github.com/google/benchmark/issues/619

若是你是在Windows平臺使用google/benchmark,那麼你須要額外連接shlwapi.lib才能使benchmark正常編譯和運行。詳細信息在這裏

編譯好程序後就能夠運行測試了:

顯示的警告信息表示在當前系統環境有一些噪音(例如其餘在運行的程序)可能致使結果不太準確,並不影響咱們的測試。

在Windows上一般沒有上述警告,若是你須要在Linux平臺上去除相關警告的話,請參考此處

測試結果與預期基本相符,std::get最快,at()最慢。

以上就是google/benchmark的安裝和簡單使用,下一篇文章中我會介紹更多使用benchmark的技巧,若有錯誤歡迎指正。

相關文章
相關標籤/搜索