Update benchmark library (nw)

This commit is contained in:
Miodrag Milanovic 2016-03-08 11:36:56 +01:00
parent facd2b7dda
commit 62709182b2
13 changed files with 316 additions and 100 deletions

View File

@ -1,6 +1,14 @@
cmake_minimum_required (VERSION 2.8.11)
project (benchmark)
foreach(p
CMP0054 # CMake 3.1
)
if(POLICY ${p})
cmake_policy(SET ${p} NEW)
endif()
endforeach()
option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON)
option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF)
# Make sure we can import out CMake functions
@ -23,73 +31,83 @@ include(CheckCXXCompilerFlag)
include(AddCXXCompilerFlag)
include(CXXFeatureCheck)
# Try and enable C++11. Don't use C++14 because it doesn't work in some
# configurations.
add_cxx_compiler_flag(-std=c++11)
if (NOT HAVE_CXX_FLAG_STD_CXX11)
add_cxx_compiler_flag(-std=c++0x)
endif()
# Turn compiler warnings up to 11
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Turn compiler warnings up to 11
add_cxx_compiler_flag(-W4)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
else()
add_cxx_compiler_flag(-Wall)
endif()
add_cxx_compiler_flag(-Wextra)
add_cxx_compiler_flag(-Wshadow)
add_cxx_compiler_flag(-Werror RELEASE)
add_cxx_compiler_flag(-pedantic)
add_cxx_compiler_flag(-pedantic-errors)
add_cxx_compiler_flag(-Wshorten-64-to-32)
add_cxx_compiler_flag(-Wfloat-equal)
add_cxx_compiler_flag(-Wzero-as-null-pointer-constant)
add_cxx_compiler_flag(-fstrict-aliasing)
if (HAVE_CXX_FLAG_FSTRICT_ALIASING)
add_cxx_compiler_flag(-Wstrict-aliasing)
endif()
add_cxx_compiler_flag(-Wthread-safety)
if (HAVE_WTHREAD_SAFETY)
add_definitions(-DHAVE_WTHREAD_SAFETY)
cxx_feature_check(THREAD_SAFETY_ATTRIBUTES)
endif()
# Link time optimisation
if (BENCHMARK_ENABLE_LTO)
add_cxx_compiler_flag(-flto)
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
find_program(GCC_AR gcc-ar)
if (GCC_AR)
set(CMAKE_AR ${GCC_AR})
endif()
find_program(GCC_RANLIB gcc-ranlib)
if (GCC_RANLIB)
set(CMAKE_RANLIB ${GCC_RANLIB})
# Link time optimisation
if (BENCHMARK_ENABLE_LTO)
set(CMAKE_CXX_FLAGS_RELEASE "/GL")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/LTCG")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG")
endif()
else()
# Try and enable C++11. Don't use C++14 because it doesn't work in some
# configurations.
add_cxx_compiler_flag(-std=c++11)
if (NOT HAVE_CXX_FLAG_STD_CXX11)
add_cxx_compiler_flag(-std=c++0x)
endif()
# Turn compiler warnings up to 11
add_cxx_compiler_flag(-Wall)
add_cxx_compiler_flag(-Wextra)
add_cxx_compiler_flag(-Wshadow)
add_cxx_compiler_flag(-Werror RELEASE)
add_cxx_compiler_flag(-pedantic)
add_cxx_compiler_flag(-pedantic-errors)
add_cxx_compiler_flag(-Wshorten-64-to-32)
add_cxx_compiler_flag(-Wfloat-equal)
add_cxx_compiler_flag(-Wzero-as-null-pointer-constant)
add_cxx_compiler_flag(-fstrict-aliasing)
if (HAVE_CXX_FLAG_FSTRICT_ALIASING)
add_cxx_compiler_flag(-Wstrict-aliasing)
endif()
add_cxx_compiler_flag(-Wthread-safety)
if (HAVE_WTHREAD_SAFETY)
add_definitions(-DHAVE_WTHREAD_SAFETY)
cxx_feature_check(THREAD_SAFETY_ATTRIBUTES)
endif()
# Link time optimisation
if (BENCHMARK_ENABLE_LTO)
add_cxx_compiler_flag(-flto)
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
find_program(GCC_AR gcc-ar)
if (GCC_AR)
set(CMAKE_AR ${GCC_AR})
endif()
find_program(GCC_RANLIB gcc-ranlib)
if (GCC_RANLIB)
set(CMAKE_RANLIB ${GCC_RANLIB})
endif()
endif()
endif()
endif()
# Coverage build type
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
"Flags used by the C++ compiler during coverage builds."
FORCE)
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used for linking binaries during coverage builds."
FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used by the shared libraries linker during coverage builds."
FORCE)
mark_as_advanced(
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE)
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
FORCE)
add_cxx_compiler_flag(--coverage COVERAGE)
# Coverage build type
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
"Flags used by the C++ compiler during coverage builds."
FORCE)
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used for linking binaries during coverage builds."
FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used by the shared libraries linker during coverage builds."
FORCE)
mark_as_advanced(
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE)
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
FORCE)
add_cxx_compiler_flag(--coverage COVERAGE)
endif()
# C++ feature checks
cxx_feature_check(STD_REGEX)

View File

@ -243,7 +243,7 @@ The `context` attribute contains information about the run in general, including
information about the CPU and the date.
The `benchmarks` attribute contains a list of ever benchmark run. Example json
output looks like:
```
``` json
{
"context": {
"date": "2015/03/17-18:40:25",
@ -290,6 +290,20 @@ name,iterations,real_time,cpu_time,bytes_per_second,items_per_second,label
"BM_SetInsert/1024/10",106365,17238.4,8421.53,4.74973e+06,1.18743e+06,
```
Debug vs Release
----------------
By default, benchmark builds as a debug library. You will see a warning in the output when this is the case. To build it as a release library instead, use:
```
cmake -DCMAKE_BUILD_TYPE=Release
```
To enable link-time optimisation, use
```
cmake -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_LTO=true
```
Linking against the library
---------------------------
When using gcc, it is necessary to link against pthread to avoid runtime exceptions. This is due to how gcc implements std::thread. See [issue #67](https://github.com/google/benchmark/issues/67) for more details.

View File

@ -12,9 +12,16 @@ platform:
environment:
matrix:
- compiler: msvc-12-seh
- compiler: msvc-14-seh
- compiler: gcc-4.9.2-posix
# - compiler: gcc-4.8.4-posix
# - compiler: msvc-12-seh
artifacts:
- path: '_build/CMakeFiles/*.log'
name: logs
- path: '_build/Testing/**/*.xml'
name: test_results
install:
# derive some extra information
@ -35,18 +42,83 @@ before_build:
- if "%compiler_name%"=="gcc" (set "build=mingw32-make -j4")
- if "%compiler_name%"=="gcc" (set "test=mingw32-make CTEST_OUTPUT_ON_FAILURE=1 test")
# msvc specific commands
# TODO :)
- if "%compiler_name%"=="msvc" if "%compiler_version%"=="12" if "%platform%"=="x86" (set "generator=Visual Studio 12 2013")
- if "%compiler_name%"=="msvc" if "%compiler_version%"=="12" if "%platform%"=="x64" (set "generator=Visual Studio 12 2013 Win64")
- if "%compiler_name%"=="msvc" if "%compiler_version%"=="14" if "%platform%"=="x86" (set "generator=Visual Studio 14 2015")
- if "%compiler_name%"=="msvc" if "%compiler_version%"=="14" if "%platform%"=="x64" (set "generator=Visual Studio 14 2015 Win64")
- if "%compiler_name%"=="msvc" (set "build=cmake --build . --config %variant%")
- if "%compiler_name%"=="msvc" (set "test=ctest -c Release -D CTEST_OUTPUT_ON_FAILURE:STRING=1")
# add the compiler path if needed
- if not "%compiler_path%"=="" (set "PATH=%PATH%;%compiler_path%")
# git bash conflicts with MinGW makefiles
- if "%generator%"=="MinGW Makefiles" (set "PATH=%PATH:C:\Program Files (x86)\Git\bin=%")
- if "%generator%"=="MinGW Makefiles" (set "PATH=%PATH:C:\Program Files\Git\usr\bin;=%")
build_script:
- cmake -G "%generator%" "-DCMAKE_BUILD_TYPE=%variant%" "-DBUILD_SHARED_LIBS=%shared%"
- cmd /c "%build%"
- ps: |
md _build -Force
cd _build
& cmake -G "$env:generator" "-DCMAKE_BUILD_TYPE=$env:variant" "-DBUILD_SHARED_LIBS=$env:shared" ..
if ($LastExitCode -ne 0) {
throw "Exec: $ErrorMessage"
}
iex "& $env:build"
if ($LastExitCode -ne 0) {
throw "Exec: $ErrorMessage"
}
test_script:
- cmd /c "%test%"
- ps: |
iex "& $env:test"
if ($LastExitCode -ne 0) {
throw "Exec: $ErrorMessage"
}
function Add-CTest-Result($testResult)
{
$tests = ([xml](get-content $testResult)).Site.Testing
$testsCount = 0
$anyFailures = $FALSE
foreach ($test in $tests.test) {
$testsCount++
$testName = $test.Name
$testpath = $test.Path
$timeNode = $test.SelectSingleNode('Results/NamedMeasurement[@name="Execution Time"]/Value')
if ($test.status -eq "failure") {
$time = ([double]$timeNode.InnerText * 1000)
Add-AppveyorTest $testName -Outcome Failed -FileName $testpath -Duration $time -ErrorMessage $($test.results.measurement.value)
Add-AppveyorMessage `"$testName failed`" -Category Error
$anyFailures = $TRUE
}
elseif ($test.status -eq "skipped") {
Add-AppveyorTest $testName -Outcome Ignored -Filename $testpath
}
else {
$time = ([double]$timeNode.InnerText * 1000)
Add-AppveyorTest $testName -Outcome Passed -FileName $testpath -Duration $time -StdOut $($test.results.measurement.value)
}
}
return $testsCount, $anyFailures
}
$testsCount = 0
$anyFailures = $FALSE
# Run tests and upload results to AppVeyor one by one
Get-ChildItem ".\Testing\*.xml" -Recurse | foreach {
$testfile = $_.fullname
$count, $testsResult = Add-CTest-Result $testfile
Write-Host "Found $testfile with $count tests"
$testsCount = $testsCount + $count
$anyFailures = $anyFailures -or $testsResult
}
Write-Host "There are $testsCount tests found"
if ($anyFailures -eq $TRUE){
Write-Host "Failing build as there are broken tests"
$host.SetShouldExit(1)
}
matrix:
fast_finish: true

View File

@ -221,7 +221,7 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
// benchmark to use.
class State {
public:
State(size_t max_iters, bool has_x, int x, bool has_y, int y, int thread_i);
State(size_t max_iters, bool has_x, int x, bool has_y, int y, int thread_i, int n_threads);
// Returns true iff the benchmark should continue through another iteration.
// NOTE: A benchmark may not return from the test until KeepRunning() has
@ -358,7 +358,10 @@ private:
size_t items_processed_;
public:
// Index of the executing thread. Values from [0, threads).
const int thread_index;
// Number of threads concurrently executing the benchmark.
const int threads;
const size_t max_iterations;
private:
@ -486,13 +489,13 @@ public:
Fixture() : internal::Benchmark("") {}
virtual void Run(State& st) {
this->SetUp();
this->SetUp(st);
this->BenchmarkCase(st);
this->TearDown();
this->TearDown(st);
}
virtual void SetUp() {}
virtual void TearDown() {}
virtual void SetUp(const State&) {}
virtual void TearDown(const State&) {}
protected:
virtual void BenchmarkCase(State&) = 0;

View File

@ -599,7 +599,7 @@ namespace {
void RunInThread(const benchmark::internal::Benchmark::Instance* b,
size_t iters, int thread_id,
ThreadStats* total) EXCLUDES(GetBenchmarkLock()) {
State st(iters, b->has_arg1, b->arg1, b->has_arg2, b->arg2, thread_id);
State st(iters, b->has_arg1, b->arg1, b->has_arg2, b->arg2, thread_id, b->threads);
b->benchmark->Run(st);
CHECK(st.iterations() == st.max_iterations) <<
"Benchmark returned before State::KeepRunning() returned false!";
@ -736,15 +736,17 @@ void RunBenchmark(const benchmark::internal::Benchmark::Instance& b,
} // namespace
State::State(size_t max_iters, bool has_x, int x, bool has_y, int y,
int thread_i)
int thread_i, int n_threads)
: started_(false), total_iterations_(0),
has_range_x_(has_x), range_x_(x),
has_range_y_(has_y), range_y_(y),
bytes_processed_(0), items_processed_(0),
thread_index(thread_i),
threads(n_threads),
max_iterations(max_iters)
{
CHECK(max_iterations != 0) << "At least one iteration must be run";
CHECK_LT(thread_index, threads) << "thread_index must be less than threads";
}
void State::PauseTiming() {

View File

@ -37,7 +37,7 @@ bool ConsoleReporter::ReportContext(const Context& context) {
if (context.cpu_scaling_enabled) {
std::cerr << "***WARNING*** CPU scaling is enabled, the benchmark "
"real time measurements may be noisy and will incure extra "
"real time measurements may be noisy and will incur extra "
"overhead.\n";
}

View File

@ -34,7 +34,7 @@ bool CSVReporter::ReportContext(const Context& context) {
if (context.cpu_scaling_enabled) {
std::cerr << "***WARNING*** CPU scaling is enabled, the benchmark "
"real time measurements may be noisy and will incure extra "
"real time measurements may be noisy and will incur extra "
"overhead.\n";
}

View File

@ -99,6 +99,14 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() {
_asm rdtsc
#elif defined(COMPILER_MSVC)
return __rdtsc();
#elif defined(__aarch64__)
// System timer of ARMv8 runs at a different frequency than the CPU's.
// The frequency is fixed, typically in the range 1-50MHz. It can be
// read at CNTFRQ special register. We assume the OS has set up
// the virtual timer properly.
int64_t virtual_timer_value;
asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
return virtual_timer_value;
#elif defined(__ARM_ARCH)
#if (__ARM_ARCH >= 6) // V6 is the earliest arch that has a standard cyclecount
uint32_t pmccntr;

View File

@ -174,12 +174,16 @@ void InitializeSystemInfo() {
if (freqstr[1] != '\0' && *err == '\0' && bogo_clock > 0)
saw_bogo = true;
}
} else if (strncasecmp(line, "processor", sizeof("processor") - 1) == 0) {
} else if (strncmp(line, "processor", sizeof("processor") - 1) == 0) {
// The above comparison is case-sensitive because ARM kernels often
// include a "Processor" line that tells you about the CPU, distinct
// from the usual "processor" lines that give you CPU ids. No current
// Linux architecture is using "Processor" for CPU ids.
num_cpus++; // count up every time we see an "processor :" entry
const char* freqstr = strchr(line, ':');
if (freqstr) {
const long cpu_id = strtol(freqstr + 1, &err, 10);
if (freqstr[1] != '\0' && *err == '\0' && max_cpu_id < cpu_id)
const char* id_str = strchr(line, ':');
if (id_str) {
const long cpu_id = strtol(id_str + 1, &err, 10);
if (id_str[1] != '\0' && *err == '\0' && max_cpu_id < cpu_id)
max_cpu_id = cpu_id;
}
}
@ -201,7 +205,7 @@ void InitializeSystemInfo() {
} else {
if ((max_cpu_id + 1) != num_cpus) {
fprintf(stderr,
"CPU ID assignments in /proc/cpuinfo seems messed up."
"CPU ID assignments in /proc/cpuinfo seem messed up."
" This is usually caused by a bad BIOS.\n");
}
cpuinfo_num_cpus = num_cpus;

View File

@ -39,6 +39,9 @@ add_test(basic_benchmark basic_test --benchmark_min_time=0.01)
compile_benchmark_test(fixture_test)
add_test(fixture_test fixture_test --benchmark_min_time=0.01)
compile_benchmark_test(map_test)
add_test(map_test map_test --benchmark_min_time=0.01)
compile_benchmark_test(cxx03_test)
set_target_properties(cxx03_test
PROPERTIES COMPILE_FLAGS "${CXX03_FLAGS}")

View File

@ -150,5 +150,29 @@ static void BM_LongTest(benchmark::State& state) {
}
BENCHMARK(BM_LongTest)->Range(1<<16,1<<28);
static void BM_ParallelMemset(benchmark::State& state) {
int size = state.range_x() / sizeof(int);
int thread_size = size / state.threads;
int from = thread_size * state.thread_index;
int to = from + thread_size;
if (state.thread_index == 0) {
test_vector = new std::vector<int>(size);
}
while (state.KeepRunning()) {
for (int i = from; i < to; i++) {
// No need to lock test_vector_mu as ranges
// do not overlap between threads.
benchmark::DoNotOptimize(test_vector->at(i) = 1);
}
}
if (state.thread_index == 0) {
delete test_vector;
}
}
BENCHMARK(BM_ParallelMemset)->Arg(10 << 20)->ThreadRange(1, 4);
BENCHMARK_MAIN()

View File

@ -2,41 +2,51 @@
#include "benchmark/benchmark.h"
#include <cassert>
#include <memory>
class MyFixture : public ::benchmark::Fixture
{
public:
void SetUp() {
data = new int(42);
class MyFixture : public ::benchmark::Fixture {
public:
void SetUp(const ::benchmark::State& state) {
if (state.thread_index == 0) {
assert(data.get() == nullptr);
data.reset(new int(42));
}
}
void TearDown() {
assert(data != nullptr);
delete data;
data = nullptr;
void TearDown(const ::benchmark::State& state) {
if (state.thread_index == 0) {
assert(data.get() != nullptr);
data.reset();
}
}
~MyFixture() {
assert(data == nullptr);
}
~MyFixture() {
assert(data == nullptr);
}
int* data;
std::unique_ptr<int> data;
};
BENCHMARK_F(MyFixture, Foo)(benchmark::State& st) {
assert(data != nullptr);
assert(*data == 42);
while (st.KeepRunning()) {
}
assert(data.get() != nullptr);
assert(*data == 42);
while (st.KeepRunning()) {
}
}
BENCHMARK_DEFINE_F(MyFixture, Bar)(benchmark::State& st) {
if (st.thread_index == 0) {
assert(data.get() != nullptr);
assert(*data == 42);
}
while (st.KeepRunning()) {
assert(data.get() != nullptr);
assert(*data == 42);
}
st.SetItemsProcessed(st.range_x());
}
BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42);
BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42)->ThreadPerCpu();
BENCHMARK_MAIN()

58
3rdparty/benchmark/test/map_test.cc vendored Normal file
View File

@ -0,0 +1,58 @@
#include "benchmark/benchmark.h"
#include <cstdlib>
#include <map>
namespace {
std::map<int, int> ConstructRandomMap(int size) {
std::map<int, int> m;
for (int i = 0; i < size; ++i) {
m.insert(std::make_pair(rand() % size, rand() % size));
}
return m;
}
} // namespace
// Basic version.
static void BM_MapLookup(benchmark::State& state) {
const int size = state.range_x();
while (state.KeepRunning()) {
state.PauseTiming();
std::map<int, int> m = ConstructRandomMap(size);
state.ResumeTiming();
for (int i = 0; i < size; ++i) {
benchmark::DoNotOptimize(m.find(rand() % size));
}
}
state.SetItemsProcessed(state.iterations() * size);
}
BENCHMARK(BM_MapLookup)->Range(1 << 3, 1 << 12);
// Using fixtures.
class MapFixture : public ::benchmark::Fixture {
public:
void SetUp(const ::benchmark::State& st) {
m = ConstructRandomMap(st.range_x());
}
void TearDown(const ::benchmark::State&) {
m.clear();
}
std::map<int, int> m;
};
BENCHMARK_DEFINE_F(MapFixture, Lookup)(benchmark::State& state) {
const int size = state.range_x();
while (state.KeepRunning()) {
for (int i = 0; i < size; ++i) {
benchmark::DoNotOptimize(m.find(rand() % size));
}
}
state.SetItemsProcessed(state.iterations() * size);
}
BENCHMARK_REGISTER_F(MapFixture, Lookup)->Range(1<<3, 1<<12);
BENCHMARK_MAIN()