Compare commits
No commits in common. "7960ad6cf6b759c64775d93c7ba7d133ba197c09" and "d9573008011832e6022b362f60dd6a5f103b2593" have entirely different histories.
7960ad6cf6
...
d957300801
95
premake5.lua
95
premake5.lua
@ -44,50 +44,6 @@ project "gtest"
|
||||
filter "system:macosx"
|
||||
pic "on"
|
||||
|
||||
project "benchmark"
|
||||
location "build"
|
||||
kind "StaticLib"
|
||||
language "C++"
|
||||
cppdialect "C++20"
|
||||
staticruntime "on"
|
||||
|
||||
targetdir ("bin/" .. outputdir .. "/output")
|
||||
objdir ("bin/" .. outputdir .. "/intermediate")
|
||||
|
||||
files {
|
||||
"thirdparty/benchmark/src/**.cc",
|
||||
}
|
||||
|
||||
removefiles {
|
||||
"thirdparty/benchmark/src/benchmark_main.cc",
|
||||
}
|
||||
|
||||
includedirs {
|
||||
"thirdparty/benchmark/include",
|
||||
"thirdparty/benchmark/src",
|
||||
}
|
||||
|
||||
defines { "BENCHMARK_STATIC_DEFINE", "HAVE_STD_REGEX" }
|
||||
|
||||
filter "configurations:debug"
|
||||
runtime "Debug"
|
||||
symbols "on"
|
||||
optimize "off"
|
||||
|
||||
filter "configurations:release"
|
||||
runtime "Release"
|
||||
symbols "on"
|
||||
optimize "Speed"
|
||||
|
||||
filter "system:windows"
|
||||
systemversion "latest"
|
||||
|
||||
filter "system:linux"
|
||||
pic "on"
|
||||
|
||||
filter "system:macosx"
|
||||
pic "on"
|
||||
|
||||
project "gtest_main"
|
||||
location "build"
|
||||
kind "StaticLib"
|
||||
@ -206,54 +162,3 @@ project "tenvex_tests"
|
||||
filter "toolset:gcc or toolset:clang"
|
||||
buildoptions { "-msse4.1" }
|
||||
filter {}
|
||||
|
||||
project "tenvex_bench"
|
||||
location "build"
|
||||
kind "ConsoleApp"
|
||||
language "C++"
|
||||
cppdialect "C++20"
|
||||
staticruntime "on"
|
||||
|
||||
targetdir ("bin/" .. outputdir .. "/output")
|
||||
objdir ("bin/" .. outputdir .. "/intermediate")
|
||||
|
||||
files {
|
||||
"src/benchmarks/**.cpp",
|
||||
}
|
||||
|
||||
includedirs {
|
||||
"src/tenvex",
|
||||
"thirdparty/benchmark/include",
|
||||
}
|
||||
|
||||
links { "benchmark" }
|
||||
|
||||
defines { "BENCHMARK_STATIC_DEFINE" }
|
||||
|
||||
filter "configurations:debug"
|
||||
runtime "Debug"
|
||||
symbols "on"
|
||||
optimize "off"
|
||||
defines { "TENVEX_DEBUG" }
|
||||
|
||||
filter "configurations:release"
|
||||
runtime "Release"
|
||||
symbols "on"
|
||||
optimize "Speed"
|
||||
defines { "TENVEX_RELEASE" }
|
||||
|
||||
filter "system:windows"
|
||||
systemversion "latest"
|
||||
links { "Shlwapi" }
|
||||
|
||||
filter "system:linux"
|
||||
pic "on"
|
||||
links { "pthread" }
|
||||
|
||||
filter "system:macosx"
|
||||
pic "on"
|
||||
|
||||
filter "toolset:gcc or toolset:clang"
|
||||
buildoptions { "-msse4.1" }
|
||||
|
||||
filter {}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
@ -1,135 +0,0 @@
|
||||
#include "tenvex.h"
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <vector>
|
||||
#include <random>
|
||||
#include <smmintrin.h>
|
||||
|
||||
using namespace tnvx;
|
||||
|
||||
// Runtime data so nothing folds to a compile-time constant.
|
||||
static std::vector<vec4> make_vecs(int n, unsigned seed)
|
||||
{
|
||||
std::mt19937 rng(seed);
|
||||
std::uniform_real_distribution<float> d(-1.0f, 1.0f);
|
||||
std::vector<vec4> v;
|
||||
v.reserve(n);
|
||||
for (int i = 0; i < n; ++i)
|
||||
v.push_back(vec4 { d(rng), d(rng), d(rng), 0.0f });
|
||||
return v;
|
||||
}
|
||||
|
||||
// =====================================================================
|
||||
// LATENCY: each iteration depends on the previous result (serial chain).
|
||||
// This is the metric for scattered everyday math: the result is needed
|
||||
// before moving on.
|
||||
// =====================================================================
|
||||
static void BM_Dot3_Latency(benchmark::State& state)
|
||||
{
|
||||
vec4 a { 1.0f, 2.0f, 3.0f, 0.0f };
|
||||
vec4 b { 0.5f, 0.5f, 0.5f, 0.0f };
|
||||
float acc = 0.0f;
|
||||
for (auto _ : state)
|
||||
{
|
||||
vec4 bb = b + vec4 { acc, 0.0f, 0.0f, 0.0f }; // depends on previous result
|
||||
float d = dot3(a, bb);
|
||||
acc = d * 1e-7f; // feedback = dependency chain
|
||||
benchmark::DoNotOptimize(acc);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Dot3_Latency);
|
||||
|
||||
static void BM_Norm3_Latency(benchmark::State& state)
|
||||
{
|
||||
vec4 v { 1.0f, 2.0f, 3.0f, 1.0f };
|
||||
for (auto _ : state)
|
||||
{
|
||||
v = norm3(v) + vec4 { 1e-3f, 2e-3f, 3e-3f, 0.0f }; // chain through v
|
||||
benchmark::DoNotOptimize(v);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Norm3_Latency);
|
||||
|
||||
// =====================================================================
|
||||
// THROUGHPUT: independent inputs, no cross-iteration dependency, so the
|
||||
// CPU can pipeline. Contrast to latency.
|
||||
// =====================================================================
|
||||
static void BM_Dot3_Throughput(benchmark::State& state)
|
||||
{
|
||||
const auto a = make_vecs(1024, 1);
|
||||
const auto b = make_vecs(1024, 2);
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
float d = dot3(a[i], b[i]);
|
||||
benchmark::DoNotOptimize(d);
|
||||
i = (i + 1) & 1023;
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Dot3_Throughput);
|
||||
|
||||
// =====================================================================
|
||||
// Compound expression: tenvex vs hand-written intrinsics.
|
||||
// If the numbers are roughly equal, the abstraction is zero-cost.
|
||||
// =====================================================================
|
||||
static void BM_Compound_tenvex(benchmark::State& state)
|
||||
{
|
||||
const auto va = make_vecs(1024, 1);
|
||||
const auto vb = make_vecs(1024, 2);
|
||||
const auto vc = make_vecs(1024, 3);
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
vec4 r = norm3(va[i] + vb[i] * 2.0f) * dot3(vb[i], vc[i]) + vc[i] * 3.0f;
|
||||
benchmark::DoNotOptimize(r);
|
||||
i = (i + 1) & 1023;
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Compound_tenvex);
|
||||
|
||||
static __m128 dp3_raw(__m128 a, __m128 b) { return _mm_dp_ps(a, b, 0x7F); }
|
||||
|
||||
static __m128 norm3_raw(__m128 v)
|
||||
{
|
||||
__m128 len = _mm_sqrt_ps(dp3_raw(v, v));
|
||||
return _mm_blend_ps(_mm_div_ps(v, len), v, 0b1000);
|
||||
}
|
||||
|
||||
static void BM_Compound_intrinsics(benchmark::State& state)
|
||||
{
|
||||
const auto va = make_vecs(1024, 1);
|
||||
const auto vb = make_vecs(1024, 2);
|
||||
const auto vc = make_vecs(1024, 3);
|
||||
std::size_t i = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
__m128 a = va[i].eval(), b = vb[i].eval(), c = vc[i].eval();
|
||||
__m128 t = norm3_raw(_mm_add_ps(a, _mm_mul_ps(b, _mm_set1_ps(2.0f))));
|
||||
__m128 d = dp3_raw(b, c);
|
||||
__m128 r = _mm_add_ps(_mm_mul_ps(t, d), _mm_mul_ps(c, _mm_set1_ps(3.0f)));
|
||||
benchmark::DoNotOptimize(r);
|
||||
i = (i + 1) & 1023;
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Compound_intrinsics);
|
||||
|
||||
// =====================================================================
|
||||
// Gameplay-style query: do two units face roughly the same way?
|
||||
// Latency-bound - the answer is needed before branching on it.
|
||||
// =====================================================================
|
||||
static void BM_FacingSameWay(benchmark::State& state)
|
||||
{
|
||||
vec4 fa = norm3(vec4 { 1.0f, 0.0f, 0.2f, 0.0f });
|
||||
vec4 fb = vec4 { 0.9f, 0.1f, 0.1f, 0.0f };
|
||||
float jitter = 0.0f;
|
||||
for (auto _ : state)
|
||||
{
|
||||
vec4 f = norm3(fb + vec4 { jitter, 0.0f, 0.0f, 0.0f });
|
||||
float c = dot3(fa, f);
|
||||
bool same = c > 0.95f;
|
||||
jitter = c * 1e-6f;
|
||||
benchmark::DoNotOptimize(same);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_FacingSameWay);
|
||||
1
thirdparty/benchmark/.bazelversion
vendored
1
thirdparty/benchmark/.bazelversion
vendored
@ -1 +0,0 @@
|
||||
8.2.1
|
||||
5
thirdparty/benchmark/.clang-format
vendored
5
thirdparty/benchmark/.clang-format
vendored
@ -1,5 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
PointerAlignment: Left
|
||||
...
|
||||
37
thirdparty/benchmark/.clang-tidy
vendored
37
thirdparty/benchmark/.clang-tidy
vendored
@ -1,37 +0,0 @@
|
||||
---
|
||||
Checks: >
|
||||
abseil-*,
|
||||
bugprone-*,
|
||||
clang-analyzer-*,
|
||||
cppcoreguidelines-*,
|
||||
google-*,
|
||||
misc-*,
|
||||
performance-*,
|
||||
readability-*,
|
||||
-clang-analyzer-deadcode*,
|
||||
-clang-analyzer-optin*,
|
||||
-readability-identifier-length
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
FormatStyle: none
|
||||
CheckOptions:
|
||||
llvm-else-after-return.WarnOnConditionVariables: 'false'
|
||||
modernize-loop-convert.MinConfidence: reasonable
|
||||
modernize-replace-auto-ptr.IncludeStyle: llvm
|
||||
cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false'
|
||||
google-readability-namespace-comments.ShortNamespaceLines: '10'
|
||||
cert-err33-c.CheckedFunctions: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;'
|
||||
cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false'
|
||||
cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU'
|
||||
google-readability-braces-around-statements.ShortStatementLines: '1'
|
||||
cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true'
|
||||
google-readability-namespace-comments.SpacesBeforeComments: '2'
|
||||
modernize-loop-convert.MaxCopySize: '16'
|
||||
modernize-pass-by-value.IncludeStyle: llvm
|
||||
modernize-use-nullptr.NullMacros: 'NULL'
|
||||
llvm-qualified-auto.AddConstToQualified: 'false'
|
||||
modernize-loop-convert.NamingStyle: CamelCase
|
||||
llvm-else-after-return.WarnOnUnfixable: 'false'
|
||||
google-readability-function-size.StatementThreshold: '800'
|
||||
...
|
||||
|
||||
1
thirdparty/benchmark/.clang-tidy.ignore
vendored
1
thirdparty/benchmark/.clang-tidy.ignore
vendored
@ -1 +0,0 @@
|
||||
.*third_party/.*
|
||||
@ -1,32 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**System**
|
||||
Which OS, compiler, and compiler version are you using:
|
||||
- OS:
|
||||
- Compiler and version:
|
||||
|
||||
**To reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. sync to commit ...
|
||||
2. cmake/bazel...
|
||||
3. make ...
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[FR]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
11
thirdparty/benchmark/.github/dependabot.yml
vendored
11
thirdparty/benchmark/.github/dependabot.yml
vendored
@ -1,11 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /tools
|
||||
schedule:
|
||||
interval: daily
|
||||
12
thirdparty/benchmark/.github/install_bazel.sh
vendored
12
thirdparty/benchmark/.github/install_bazel.sh
vendored
@ -1,12 +0,0 @@
|
||||
if ! bazel version; then
|
||||
arch=$(uname -m)
|
||||
if [ "$arch" == "aarch64" ]; then
|
||||
arch="arm64"
|
||||
fi
|
||||
echo "Downloading $arch Bazel binary from GitHub releases."
|
||||
curl -L -o $HOME/bin/bazel --create-dirs "https://github.com/bazelbuild/bazel/releases/download/8.2.0/bazel-8.2.0-linux-$arch"
|
||||
chmod +x $HOME/bin/bazel
|
||||
else
|
||||
# Bazel is installed for the correct architecture
|
||||
exit 0
|
||||
fi
|
||||
35
thirdparty/benchmark/.github/libcxx-setup.sh
vendored
35
thirdparty/benchmark/.github/libcxx-setup.sh
vendored
@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# Checkout LLVM sources
|
||||
git clone --filter=blob:none --depth=1 --branch llvmorg-19.1.6 --no-checkout https://github.com/llvm/llvm-project.git llvm-project
|
||||
cd llvm-project
|
||||
git sparse-checkout set --cone
|
||||
git checkout llvmorg-19.1.6
|
||||
git sparse-checkout set cmake llvm/cmake runtimes libcxx libcxxabi
|
||||
cd ..
|
||||
|
||||
## Setup libc++ options
|
||||
if [ -z "$BUILD_32_BITS" ]; then
|
||||
export BUILD_32_BITS=OFF && echo disabling 32 bit build
|
||||
fi
|
||||
|
||||
## Build and install libc++ (Use unstable ABI for better sanitizer coverage)
|
||||
mkdir llvm-build && cd llvm-build
|
||||
cmake -GNinja \
|
||||
-DCMAKE_C_COMPILER=${CC} \
|
||||
-DCMAKE_CXX_COMPILER=${CXX} \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DLIBCXX_ABI_UNSTABLE=OFF \
|
||||
-DLLVM_USE_SANITIZER=${LIBCXX_SANITIZER} \
|
||||
-DLLVM_BUILD_32_BITS=${BUILD_32_BITS} \
|
||||
-DLIBCXXABI_USE_LLVM_UNWINDER=OFF \
|
||||
-DLLVM_INCLUDE_TESTS=OFF \
|
||||
-DLIBCXX_INCLUDE_TESTS=OFF \
|
||||
-DLIBCXX_INCLUDE_BENCHMARKS=OFF \
|
||||
-DLLVM_ENABLE_RUNTIMES='libcxx;libcxxabi' \
|
||||
../llvm-project/runtimes/
|
||||
cmake --build . -- cxx cxxabi
|
||||
cd ..
|
||||
40
thirdparty/benchmark/.github/workflows/bazel.yml
vendored
40
thirdparty/benchmark/.github/workflows/bazel.yml
vendored
@ -1,40 +0,0 @@
|
||||
name: bazel
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build_and_test_default:
|
||||
name: bazel.${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: mount bazel cache
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
env:
|
||||
cache-name: bazel-cache
|
||||
with:
|
||||
path: "~/.cache/bazel"
|
||||
key: ${{ env.cache-name }}-${{ matrix.os }}-${{ github.ref }}
|
||||
restore-keys: |
|
||||
${{ env.cache-name }}-${{ matrix.os }}-main
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
bazel build //:benchmark //:benchmark_main //test/...
|
||||
|
||||
- name: test
|
||||
run: |
|
||||
bazel test --test_output=all //test/...
|
||||
@ -1,49 +0,0 @@
|
||||
name: build-and-test-min-cmake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: ${{ matrix.os }}.min-cmake
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- uses: lukka/get-cmake@591817e96fcad43505fb4eae36172462abb3a42e # latest
|
||||
with:
|
||||
cmakeVersion: 3.13.0
|
||||
|
||||
- name: create build environment
|
||||
run: cmake -E make_directory ${{ runner.workspace }}/_build
|
||||
|
||||
- name: setup cmake initial cache
|
||||
run: touch compiler-cache.cmake
|
||||
|
||||
- name: configure cmake
|
||||
env:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: >
|
||||
cmake -C ${{ github.workspace }}/compiler-cache.cmake
|
||||
$GITHUB_WORKSPACE
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DCMAKE_CXX_VISIBILITY_PRESET=hidden
|
||||
-DCMAKE_VISIBILITY_INLINES_HIDDEN=ON
|
||||
|
||||
- name: build
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: cmake --build .
|
||||
@ -1,57 +0,0 @@
|
||||
name: build-and-test-perfcounters
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
job:
|
||||
# TODO(dominic): Extend this to include compiler and set through env: CC/CXX.
|
||||
name: ${{ matrix.os }}.${{ matrix.build_type }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
build_type: ['Release', 'Debug']
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: install libpfm
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt -y install libpfm4-dev
|
||||
|
||||
- name: create build environment
|
||||
run: cmake -E make_directory ${{ runner.workspace }}/_build
|
||||
|
||||
- name: configure cmake
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: >
|
||||
cmake $GITHUB_WORKSPACE
|
||||
-DBENCHMARK_ENABLE_LIBPFM=1
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
|
||||
- name: build
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: cmake --build . --config ${{ matrix.build_type }}
|
||||
|
||||
# Skip testing, for now. It seems perf_event_open does not succeed on the
|
||||
# hosting machine, very likely a permissions issue.
|
||||
# TODO(mtrofin): Enable test.
|
||||
# - name: test
|
||||
# shell: bash
|
||||
# working-directory: ${{ runner.workspace }}/_build
|
||||
# run: ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure
|
||||
|
||||
@ -1,151 +0,0 @@
|
||||
name: build-and-test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
# TODO: add 32-bit builds (g++ and clang++) for ubuntu
|
||||
# (requires g++-multilib and libc6:i386)
|
||||
# TODO: add coverage build (requires lcov)
|
||||
# TODO: add clang + libc++ builds for ubuntu
|
||||
job:
|
||||
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.lib }}.${{ matrix.compiler }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04, ubuntu-22.04, ubuntu-24.04-arm, macos-latest]
|
||||
build_type: ['Release', 'Debug']
|
||||
compiler: ['g++', 'clang++']
|
||||
lib: ['shared', 'static']
|
||||
|
||||
steps:
|
||||
- name: Install dependencies (macos)
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install ninja
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: build
|
||||
uses: threeal/cmake-action@725d1314ccf9ea922805d7e3f9d9bcbca892b406 # v2.1.0
|
||||
with:
|
||||
build-dir: ${{ runner.workspace }}/_build
|
||||
cxx-compiler: ${{ matrix.compiler }}
|
||||
options: |
|
||||
BENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
BUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
|
||||
CMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
CMAKE_CXX_COMPILER=${{ matrix.compiler }}
|
||||
CMAKE_CXX_VISIBILITY_PRESET=hidden
|
||||
CMAKE_VISIBILITY_INLINES_HIDDEN=ON
|
||||
|
||||
- name: test
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: ctest -C ${{ matrix.build_type }} -VV
|
||||
|
||||
msvc:
|
||||
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.lib }}.${{ matrix.msvc }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: powershell
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
msvc:
|
||||
- VS-17-2025
|
||||
- VS-17-2022
|
||||
build_type:
|
||||
- Debug
|
||||
- Release
|
||||
lib:
|
||||
- shared
|
||||
- static
|
||||
include:
|
||||
- msvc: VS-17-2025
|
||||
os: windows-2025
|
||||
generator: 'Visual Studio 17 2022'
|
||||
- msvc: VS-17-2022
|
||||
os: windows-2022
|
||||
generator: 'Visual Studio 17 2022'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- uses: lukka/get-cmake@591817e96fcad43505fb4eae36172462abb3a42e # latest
|
||||
|
||||
- name: configure cmake
|
||||
run: >
|
||||
cmake -S . -B ${{ runner.workspace }}/_build/
|
||||
-G "${{ matrix.generator }}"
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
|
||||
|
||||
- name: build
|
||||
run: cmake --build ${{ runner.workspace }}/_build/ --config ${{ matrix.build_type }}
|
||||
|
||||
- name: test
|
||||
run: ctest --test-dir ${{ runner.workspace }}/_build/ -C ${{ matrix.build_type }} -VV
|
||||
|
||||
msys2:
|
||||
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.lib }}.${{ matrix.msys2.msystem }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ windows-latest ]
|
||||
msys2:
|
||||
- { msystem: MINGW64, arch: x86_64, family: GNU, compiler: g++ }
|
||||
- { msystem: CLANG64, arch: x86_64, family: LLVM, compiler: clang++ }
|
||||
- { msystem: UCRT64, arch: x86_64, family: GNU, compiler: g++ }
|
||||
build_type:
|
||||
- Debug
|
||||
- Release
|
||||
lib:
|
||||
- shared
|
||||
- static
|
||||
|
||||
steps:
|
||||
- name: setup msys2
|
||||
uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d # v2.31.0
|
||||
with:
|
||||
cache: false
|
||||
msystem: ${{ matrix.msys2.msystem }}
|
||||
update: true
|
||||
install: >-
|
||||
git
|
||||
base-devel
|
||||
pacboy: >-
|
||||
gcc:p
|
||||
clang:p
|
||||
cmake:p
|
||||
ninja:p
|
||||
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
# NOTE: we can't use cmake actions here as we need to do everything in msys2 shell.
|
||||
- name: configure cmake
|
||||
env:
|
||||
CXX: ${{ matrix.msys2.compiler }}
|
||||
run: >
|
||||
cmake -S . -B _build/
|
||||
-GNinja
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
|
||||
|
||||
- name: build
|
||||
run: cmake --build _build/ --config ${{ matrix.build_type }}
|
||||
|
||||
- name: test
|
||||
working-directory: _build
|
||||
run: ctest -C ${{ matrix.build_type }} -VV
|
||||
@ -1,22 +0,0 @@
|
||||
name: clang-format-lint
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: check-clang-format
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: DoozyX/clang-format-lint-action@bcb4eb2cb0d707ee4f3e5cc3b456eb075f12cf73 # v0.20
|
||||
with:
|
||||
source: './include/benchmark ./src ./test ./bindings'
|
||||
clangFormatVersion: 18
|
||||
@ -1,44 +0,0 @@
|
||||
name: clang-tidy
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: run-clang-tidy
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: install clang-tidy
|
||||
run: sudo apt update && sudo apt -y install clang-tidy
|
||||
|
||||
- name: create build environment
|
||||
run: cmake -E make_directory ${{ github.workspace }}/_build
|
||||
|
||||
- name: configure cmake
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/_build
|
||||
run: >
|
||||
cmake $GITHUB_WORKSPACE
|
||||
-DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF
|
||||
-DBENCHMARK_ENABLE_LIBPFM=OFF
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DCMAKE_C_COMPILER=clang
|
||||
-DCMAKE_CXX_COMPILER=clang++
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
-DGTEST_COMPILE_COMMANDS=OFF
|
||||
|
||||
- name: run
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/_build
|
||||
run: run-clang-tidy -config-file=$GITHUB_WORKSPACE/.clang-tidy
|
||||
@ -1,34 +0,0 @@
|
||||
name: doxygen
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
name: Build HTML documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fetching sources
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Installing build dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install doxygen gcc git
|
||||
|
||||
- name: Creating build directory
|
||||
run: mkdir build
|
||||
|
||||
- name: Building HTML documentation with Doxygen
|
||||
run: |
|
||||
cmake -S . -B build -DBENCHMARK_ENABLE_TESTING:BOOL=OFF -DBENCHMARK_ENABLE_DOXYGEN:BOOL=ON -DBENCHMARK_INSTALL_DOCS:BOOL=ON
|
||||
cmake --build build --target benchmark_doxygen
|
||||
27
thirdparty/benchmark/.github/workflows/ossf.yml
vendored
27
thirdparty/benchmark/.github/workflows/ossf.yml
vendored
@ -1,27 +0,0 @@
|
||||
name: OSSF Scorecard Weekly
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # Runs every Sunday at midnight UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
ossf-scorecard:
|
||||
# To write a badge
|
||||
permissions:
|
||||
id-token: write
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Run analysis
|
||||
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||
with:
|
||||
publish_results: true
|
||||
results_file: ossf_scorecard.json
|
||||
results_format: json
|
||||
@ -1,22 +0,0 @@
|
||||
name: python + Bazel pre-commit checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
python-version: 3.12
|
||||
- name: Run pre-commit checks
|
||||
run: uv run --only-group=dev pre-commit run --all-files --verbose --show-diff-on-failure
|
||||
@ -1,97 +0,0 @@
|
||||
name: sanitizer
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
UBSAN_OPTIONS: "print_stacktrace=1"
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: ${{ matrix.sanitizer }}.${{ matrix.build_type }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: ['Debug', 'RelWithDebInfo']
|
||||
sanitizer: ['asan', 'ubsan', 'tsan', 'msan']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: configure msan env
|
||||
if: matrix.sanitizer == 'msan'
|
||||
run: |
|
||||
echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=memory -fsanitize-memory-track-origins" >> $GITHUB_ENV
|
||||
echo "LIBCXX_SANITIZER=MemoryWithOrigins" >> $GITHUB_ENV
|
||||
|
||||
- name: configure ubsan env
|
||||
if: matrix.sanitizer == 'ubsan'
|
||||
run: |
|
||||
echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=all" >> $GITHUB_ENV
|
||||
echo "LIBCXX_SANITIZER=Undefined" >> $GITHUB_ENV
|
||||
|
||||
- name: configure asan env
|
||||
if: matrix.sanitizer == 'asan'
|
||||
run: |
|
||||
echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=address -fno-sanitize-recover=all" >> $GITHUB_ENV
|
||||
echo "LIBCXX_SANITIZER=Address" >> $GITHUB_ENV
|
||||
|
||||
- name: configure tsan env
|
||||
if: matrix.sanitizer == 'tsan'
|
||||
run: |
|
||||
echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all" >> $GITHUB_ENV
|
||||
echo "LIBCXX_SANITIZER=Thread" >> $GITHUB_ENV
|
||||
|
||||
- name: fine-tune asan options
|
||||
# in asan we get an error from std::regex. ignore it.
|
||||
if: matrix.sanitizer == 'asan'
|
||||
run: |
|
||||
echo "ASAN_OPTIONS=alloc_dealloc_mismatch=0" >> $GITHUB_ENV
|
||||
|
||||
- name: setup clang
|
||||
uses: egor-tensin/setup-clang@23bc15cd4207e45f1566447deb48f4ff3ef932cb # v2.3
|
||||
with:
|
||||
version: latest
|
||||
platform: x64
|
||||
|
||||
- name: configure clang
|
||||
run: |
|
||||
echo "CC=cc" >> $GITHUB_ENV
|
||||
echo "CXX=c++" >> $GITHUB_ENV
|
||||
|
||||
- name: build libc++ (non-asan)
|
||||
if: matrix.sanitizer != 'asan'
|
||||
run: |
|
||||
"${GITHUB_WORKSPACE}/.github/libcxx-setup.sh"
|
||||
echo "EXTRA_CXX_FLAGS=-stdlib=libc++ -L${GITHUB_WORKSPACE}/llvm-build/lib -lc++abi -I${GITHUB_WORKSPACE}/llvm-build/include/c++/v1 -Isystem${GITHUB_WORKSPACE}/llvm-build/include/c++/v1 -Wl,-rpath,${GITHUB_WORKSPACE}/llvm-build/lib" >> $GITHUB_ENV
|
||||
|
||||
- name: create build environment
|
||||
run: cmake -E make_directory ${{ runner.workspace }}/_build
|
||||
|
||||
- name: configure cmake
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: >
|
||||
VERBOSE=1
|
||||
cmake -GNinja $GITHUB_WORKSPACE
|
||||
-DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF
|
||||
-DBENCHMARK_ENABLE_LIBPFM=OFF
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DCMAKE_C_COMPILER=${{ env.CC }}
|
||||
-DCMAKE_CXX_COMPILER=${{ env.CXX }}
|
||||
-DCMAKE_C_FLAGS="${{ env.EXTRA_FLAGS }}"
|
||||
-DCMAKE_CXX_FLAGS="${{ env.EXTRA_FLAGS }} ${{ env.EXTRA_CXX_FLAGS }}"
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
|
||||
- name: build
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: cmake --build . --config ${{ matrix.build_type }}
|
||||
|
||||
- name: test
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: ctest -C ${{ matrix.build_type }} -VV
|
||||
@ -1,36 +0,0 @@
|
||||
name: test-bindings
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
python_bindings:
|
||||
name: Test GBM Python ${{ matrix.python-version }} bindings on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||
python-version: [ "3.10", "3.11", "3.12", "3.13" ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install GBM Python bindings on ${{ matrix.os }}
|
||||
run: python -m pip install .
|
||||
- name: Run example on ${{ matrix.os }} under Python ${{ matrix.python-version }}
|
||||
run: python bindings/python/google_benchmark/example.py
|
||||
@ -1,84 +0,0 @@
|
||||
name: Build and upload Python wheels
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
build_sdist:
|
||||
name: Build source distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install Python 3.12
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- run: python -m pip install build
|
||||
- name: Build sdist
|
||||
run: python -m build --sdist
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: dist-sdist
|
||||
path: dist/*.tar.gz
|
||||
|
||||
build_wheels:
|
||||
name: Build Google Benchmark wheels on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, ubuntu-24.04-arm, macos-15-intel, macos-latest, windows-latest]
|
||||
steps:
|
||||
- name: Check out Google Benchmark
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
name: Install Python 3.12
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
|
||||
- name: Build wheels on ${{ matrix.os }} using cibuildwheel
|
||||
uses: pypa/cibuildwheel@8d2b08b68458a16aeb24b64e68a09ab1c8e82084 # v3.4.1
|
||||
env:
|
||||
CIBW_BUILD: "cp310-* cp311-* cp312-*"
|
||||
CIBW_BUILD_FRONTEND: "build[uv]"
|
||||
CIBW_SKIP: "*-musllinux_*"
|
||||
CIBW_ARCHS: auto64
|
||||
CIBW_BEFORE_ALL_LINUX: bash .github/install_bazel.sh
|
||||
# Grab the rootless Bazel installation inside the container.
|
||||
CIBW_ENVIRONMENT_LINUX: PATH=$PATH:$HOME/bin
|
||||
CIBW_TEST_COMMAND: python {project}/bindings/python/google_benchmark/example.py
|
||||
# unused by Bazel, but needed explicitly by delocate on MacOS.
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.os == 'macos-15-intel' && 10.14 || 11.0 }}
|
||||
|
||||
- name: Upload Google Benchmark ${{ matrix.os }} wheels
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: dist-${{ matrix.os }}
|
||||
path: wheelhouse/*.whl
|
||||
|
||||
pypi_upload:
|
||||
name: Publish google-benchmark wheels to PyPI
|
||||
needs: [build_sdist, build_wheels]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
pattern: dist-*
|
||||
merge-multiple: true
|
||||
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
|
||||
69
thirdparty/benchmark/.gitignore
vendored
69
thirdparty/benchmark/.gitignore
vendored
@ -1,69 +0,0 @@
|
||||
*.a
|
||||
*.so
|
||||
*.so.?*
|
||||
*.dll
|
||||
*.exe
|
||||
*.dylib
|
||||
*.cmake
|
||||
!/cmake/**/*.cmake
|
||||
!/test/AssemblyTests.cmake
|
||||
*~
|
||||
*.swp
|
||||
*.pyc
|
||||
__pycache__
|
||||
.DS_Store
|
||||
|
||||
# lcov
|
||||
*.lcov
|
||||
/lcov
|
||||
|
||||
# cmake files.
|
||||
/Testing
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
|
||||
# makefiles.
|
||||
Makefile
|
||||
|
||||
# in-source build.
|
||||
bin/
|
||||
lib/
|
||||
/test/*_test
|
||||
|
||||
# exuberant ctags.
|
||||
tags
|
||||
|
||||
# YouCompleteMe configuration.
|
||||
.ycm_extra_conf.pyc
|
||||
|
||||
# ninja generated files.
|
||||
.ninja_deps
|
||||
.ninja_log
|
||||
build.ninja
|
||||
install_manifest.txt
|
||||
rules.ninja
|
||||
|
||||
# bazel output symlinks.
|
||||
bazel-*
|
||||
MODULE.bazel.lock
|
||||
|
||||
# out-of-source build top-level folders.
|
||||
build/
|
||||
_build/
|
||||
build*/
|
||||
|
||||
# in-source dependencies
|
||||
/googletest/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
CMakeSettings.json
|
||||
|
||||
# Visual Studio Code cache/options directory
|
||||
.vscode/
|
||||
|
||||
# Python build stuff
|
||||
dist/
|
||||
*.egg-info*
|
||||
uv.lock
|
||||
18
thirdparty/benchmark/.pre-commit-config.yaml
vendored
18
thirdparty/benchmark/.pre-commit-config.yaml
vendored
@ -1,18 +0,0 @@
|
||||
repos:
|
||||
- repo: https://github.com/keith/pre-commit-buildifier
|
||||
rev: 8.2.1
|
||||
hooks:
|
||||
- id: buildifier
|
||||
- id: buildifier-lint
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.18.2
|
||||
hooks:
|
||||
- id: mypy
|
||||
types_or: [ python, pyi ]
|
||||
args: [ "--ignore-missing-imports", "--scripts-are-modules" ]
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.14.0
|
||||
hooks:
|
||||
- id: ruff-check
|
||||
args: [ --fix, --exit-non-zero-on-fix ]
|
||||
- id: ruff-format
|
||||
120
thirdparty/benchmark/.ycm_extra_conf.py
vendored
120
thirdparty/benchmark/.ycm_extra_conf.py
vendored
@ -1,120 +0,0 @@
|
||||
import os
|
||||
|
||||
import ycm_core
|
||||
|
||||
# These are the compilation flags that will be used in case there's no
|
||||
# compilation database set (by default, one is not set).
|
||||
# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.
|
||||
flags = [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-pedantic-errors",
|
||||
"-std=c++0x",
|
||||
"-fno-strict-aliasing",
|
||||
"-O3",
|
||||
"-DNDEBUG",
|
||||
# ...and the same thing goes for the magic -x option which specifies the
|
||||
# language that the files to be compiled are written in. This is mostly
|
||||
# relevant for c++ headers.
|
||||
# For a C project, you would set this to 'c' instead of 'c++'.
|
||||
"-x",
|
||||
"c++",
|
||||
"-I",
|
||||
"include",
|
||||
"-isystem",
|
||||
"/usr/include",
|
||||
"-isystem",
|
||||
"/usr/local/include",
|
||||
]
|
||||
|
||||
|
||||
# Set this to the absolute path to the folder (NOT the file!) containing the
|
||||
# compile_commands.json file to use that instead of 'flags'. See here for
|
||||
# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
|
||||
#
|
||||
# Most projects will NOT need to set this to anything; you can just change the
|
||||
# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
|
||||
compilation_database_folder = ""
|
||||
|
||||
if os.path.exists(compilation_database_folder):
|
||||
database = ycm_core.CompilationDatabase(compilation_database_folder)
|
||||
else:
|
||||
database = None
|
||||
|
||||
SOURCE_EXTENSIONS = [".cc"]
|
||||
|
||||
|
||||
def DirectoryOfThisScript():
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
|
||||
if not working_directory:
|
||||
return list(flags)
|
||||
new_flags = []
|
||||
make_next_absolute = False
|
||||
path_flags = ["-isystem", "-I", "-iquote", "--sysroot="]
|
||||
for flag in flags:
|
||||
new_flag = flag
|
||||
|
||||
if make_next_absolute:
|
||||
make_next_absolute = False
|
||||
if not flag.startswith("/"):
|
||||
new_flag = os.path.join(working_directory, flag)
|
||||
|
||||
for path_flag in path_flags:
|
||||
if flag == path_flag:
|
||||
make_next_absolute = True
|
||||
break
|
||||
|
||||
if flag.startswith(path_flag):
|
||||
path = flag[len(path_flag) :]
|
||||
new_flag = path_flag + os.path.join(working_directory, path)
|
||||
break
|
||||
|
||||
if new_flag:
|
||||
new_flags.append(new_flag)
|
||||
return new_flags
|
||||
|
||||
|
||||
def IsHeaderFile(filename):
|
||||
extension = os.path.splitext(filename)[1]
|
||||
return extension in [".h", ".hxx", ".hpp", ".hh"]
|
||||
|
||||
|
||||
def GetCompilationInfoForFile(filename):
|
||||
# The compilation_commands.json file generated by CMake does not have
|
||||
# entries for header files. So we do our best by asking the db for flags for
|
||||
# a corresponding source file, if any. If one exists, the flags for that
|
||||
# file should be good enough.
|
||||
if IsHeaderFile(filename):
|
||||
basename = os.path.splitext(filename)[0]
|
||||
for extension in SOURCE_EXTENSIONS:
|
||||
replacement_file = basename + extension
|
||||
if os.path.exists(replacement_file):
|
||||
compilation_info = database.GetCompilationInfoForFile(
|
||||
replacement_file
|
||||
)
|
||||
if compilation_info.compiler_flags_:
|
||||
return compilation_info
|
||||
return None
|
||||
return database.GetCompilationInfoForFile(filename)
|
||||
|
||||
|
||||
def FlagsForFile(filename, **kwargs):
|
||||
if database:
|
||||
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
|
||||
# python list, but a "list-like" StringVec object
|
||||
compilation_info = GetCompilationInfoForFile(filename)
|
||||
if not compilation_info:
|
||||
return None
|
||||
|
||||
final_flags = MakeRelativePathsInFlagsAbsolute(
|
||||
compilation_info.compiler_flags_,
|
||||
compilation_info.compiler_working_dir_,
|
||||
)
|
||||
else:
|
||||
relative_to = DirectoryOfThisScript()
|
||||
final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to)
|
||||
|
||||
return {"flags": final_flags, "do_cache": True}
|
||||
44
thirdparty/benchmark/AGENTS.md
vendored
44
thirdparty/benchmark/AGENTS.md
vendored
@ -1,44 +0,0 @@
|
||||
# AI usage
|
||||
|
||||
> [!NOTE]
|
||||
> The modern (as of 2026-06) AI is a misnomer,
|
||||
> - it is not conscious / not a consciousness,
|
||||
> - it is not sentient,
|
||||
> - it is not intelligent,
|
||||
> - it does not think,
|
||||
> - it does not understand the code,
|
||||
> - it is merely a next-token guesser,
|
||||
>
|
||||
> ... therefore it is merely an (hyper-) advanced IDE.
|
||||
|
||||
> [!NOTE]
|
||||
> A contribution is any externally-observable interaction with a project.
|
||||
|
||||
> [!CAUTION]
|
||||
> Failure to follow the following rules *may* result in repercussions,
|
||||
> possibly without a prior warning.
|
||||
|
||||
Rules:
|
||||
1. It is acceptable to use AI when producing contributions.
|
||||
> [!WARNING]
|
||||
> Any and all AI usage **MUST** be fully and explicitly disclosed
|
||||
> in **every** contribution.
|
||||
2. All contributions shall be done by conscious, sentient beings.
|
||||
Fully autonomous contributions by bots are prohibited[^1].
|
||||
> [!WARNING]
|
||||
> Dear contributor, the AI is *your* *tool*, and its output is for *your*
|
||||
> *consumption*. It is **your** responsibility to consume said output,
|
||||
> interpret it, and then produce the contribution itself.
|
||||
> **DO NOT** just query it and post the output,
|
||||
> *especially* so for all non-code contributions!
|
||||
3. The contributor (conscious, sentient being) solely bears
|
||||
the whole responsibility for the contribution,
|
||||
they must understand the problem, and the solution,
|
||||
and be able to constructively argue about it.
|
||||
"well, AI said so, therefore it is" is not an acceptable approach.
|
||||
|
||||
[^1]: Unless explicitly allowed by maintainers on case-by-case basis
|
||||
*before* the contribution is submitted,
|
||||
in which case the bot owner (conscious, sentient being)
|
||||
is recognized as the de facto contributor.
|
||||
E.g. https://github.com/apps/dependabot is allowed.
|
||||
81
thirdparty/benchmark/AUTHORS
vendored
81
thirdparty/benchmark/AUTHORS
vendored
@ -1,81 +0,0 @@
|
||||
# This is the official list of benchmark authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
#
|
||||
# Names should be added to this file as:
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
#
|
||||
# Please keep the list sorted.
|
||||
|
||||
Albert Pretorius <pretoalb@gmail.com>
|
||||
Alex Steele <steeleal123@gmail.com>
|
||||
Andriy Berestovskyy <berestovskyy@gmail.com>
|
||||
Arne Beer <arne@twobeer.de>
|
||||
Benjamin King <kingbenja5@gmail.com>
|
||||
Carto
|
||||
Cezary Skrzyński <czars1988@gmail.com>
|
||||
Christian Wassermann <christian_wassermann@web.de>
|
||||
Christopher Seymour <chris.j.seymour@hotmail.com>
|
||||
Colin Braley <braley.colin@gmail.com>
|
||||
Daniel Harvey <danielharvey458@gmail.com>
|
||||
David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
|
||||
Deniz Evrenci <denizevrenci@gmail.com>
|
||||
Dirac Research
|
||||
Dominik Czarnota <dominik.b.czarnota@gmail.com>
|
||||
Dominik Korman <kormandominik@gmail.com>
|
||||
Donald Aingworth <donalds_junk_mail@yahoo.com>
|
||||
Eric Backus <eric_backus@alum.mit.edu>
|
||||
Eric Fiselier <eric@efcs.ca>
|
||||
Eugene Zhuk <eugene.zhuk@gmail.com>
|
||||
Evgeny Safronov <division494@gmail.com>
|
||||
Fabien Pichot <pichot.fabien@gmail.com>
|
||||
Federico Ficarelli <federico.ficarelli@gmail.com>
|
||||
Felix Homann <linuxaudio@showlabor.de>
|
||||
Felmon Fekadu <felmonon@gmail.com>
|
||||
Gergely Meszaros <maetveis@gmail.com>
|
||||
Gergő Szitár <szitar.gergo@gmail.com>
|
||||
Google Inc.
|
||||
Haihan Jiang <haihanj99@gmail.com>
|
||||
Henrique Bucher <hbucher@gmail.com>
|
||||
International Business Machines Corporation
|
||||
Ismael Jimenez Martinez <ismael.jimenez.martinez@gmail.com>
|
||||
Jern-Kuan Leong <jernkuan@gmail.com>
|
||||
JianXiong Zhou <zhoujianxiong2@gmail.com>
|
||||
Joao Paulo Magalhaes <joaoppmagalhaes@gmail.com>
|
||||
Jordan Williams <jwillikers@protonmail.com>
|
||||
Jussi Knuuttila <jussi.knuuttila@gmail.com>
|
||||
Kaito Udagawa <umireon@gmail.com>
|
||||
Kishan Kumar <kumar.kishan@outlook.com>
|
||||
Kostiantyn Lazukin <konstantin.lazukin@gmail.com>
|
||||
Lei Xu <eddyxu@gmail.com>
|
||||
Marcel Jacobse <mjacobse@uni-bremen.de>
|
||||
Matt Clarkson <mattyclarkson@gmail.com>
|
||||
Maxim Vafin <maxvafin@gmail.com>
|
||||
Mike Apodaca <gatorfax@gmail.com>
|
||||
Min-Yih Hsu <yihshyng223@gmail.com>
|
||||
MongoDB Inc.
|
||||
Nick Hutchinson <nshutchinson@gmail.com>
|
||||
Norman Heino <norman.heino@gmail.com>
|
||||
Oleksandr Sochka <sasha.sochka@gmail.com>
|
||||
Olga Fadeeva <olga.kiselik@gmail.com>
|
||||
Ori Livneh <ori.livneh@gmail.com>
|
||||
Paul Redmond <paul.redmond@gmail.com>
|
||||
Prithvi Rao <ee22b024@smail.iitm.ac.in>
|
||||
qorexdev <sanenkosana600@gmail.com>
|
||||
Radoslav Yovchev <radoslav.tm@gmail.com>
|
||||
Raghu Raja <raghu@enfabrica.net>
|
||||
Rainer Orth <ro@cebitec.uni-bielefeld.de>
|
||||
Roman Lebedev <lebedev.ri@gmail.com>
|
||||
Sayan Bhattacharjee <aero.sayan@gmail.com>
|
||||
Shapr3D <google-contributors@shapr3d.com>
|
||||
Shashank Thakur <shashankt2004@gmail.com>
|
||||
Shuo Chen <chenshuo@chenshuo.com>
|
||||
Staffan Tjernstrom <staffantj@gmail.com>
|
||||
Steinar H. Gunderson <sgunderson@bigfoot.com>
|
||||
Stripe, Inc.
|
||||
Tobias Schmidt <tobias.schmidt@in.tum.de>
|
||||
XiaoWei Lu <shaway77606@gmail.com>
|
||||
Yixuan Qiu <yixuanq@gmail.com>
|
||||
Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
Zbigniew Skowron <zbychs@gmail.com>
|
||||
125
thirdparty/benchmark/BUILD.bazel
vendored
125
thirdparty/benchmark/BUILD.bazel
vendored
@ -1,125 +0,0 @@
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
COPTS = [
|
||||
"-pedantic",
|
||||
"-pedantic-errors",
|
||||
"-std=c++17",
|
||||
"-Wall",
|
||||
"-Wconversion",
|
||||
"-Wextra",
|
||||
"-Wshadow",
|
||||
# "-Wshorten-64-to-32",
|
||||
"-Wfloat-equal",
|
||||
"-Wformat=2",
|
||||
"-fstrict-aliasing",
|
||||
## assert() are used a lot in tests upstream, which may be optimised out leading to
|
||||
## unused-variable warning.
|
||||
"-Wno-unused-variable",
|
||||
"-Werror=old-style-cast",
|
||||
]
|
||||
|
||||
MSVC_COPTS = [
|
||||
"/std:c++17",
|
||||
]
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = ["@platforms//os:windows"],
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "perfcounters",
|
||||
define_values = {
|
||||
"pfm": "1",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "benchmark",
|
||||
srcs = glob(
|
||||
[
|
||||
"src/*.cc",
|
||||
"src/*.h",
|
||||
],
|
||||
exclude = ["src/benchmark_main.cc"],
|
||||
),
|
||||
hdrs = [
|
||||
"include/benchmark/benchmark.h",
|
||||
"include/benchmark/benchmark_api.h",
|
||||
"include/benchmark/counter.h",
|
||||
"include/benchmark/export.h",
|
||||
"include/benchmark/macros.h",
|
||||
"include/benchmark/managers.h",
|
||||
"include/benchmark/registration.h",
|
||||
"include/benchmark/reporter.h",
|
||||
"include/benchmark/state.h",
|
||||
"include/benchmark/statistics.h",
|
||||
"include/benchmark/sysinfo.h",
|
||||
"include/benchmark/types.h",
|
||||
"include/benchmark/utils.h",
|
||||
],
|
||||
copts = select({
|
||||
":windows": MSVC_COPTS,
|
||||
"//conditions:default": COPTS,
|
||||
}),
|
||||
defines = [
|
||||
"BENCHMARK_STATIC_DEFINE",
|
||||
"BENCHMARK_VERSION=\\\"" + (module_version() if module_version() != None else "") + "\\\"",
|
||||
] + select({
|
||||
":perfcounters": ["HAVE_LIBPFM"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
includes = ["include"],
|
||||
linkopts = select({
|
||||
":windows": ["-DEFAULTLIB:shlwapi.lib"],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
# Only static linking is allowed; no .so will be produced.
|
||||
# Using `defines` (i.e. not `local_defines`) means that no
|
||||
# dependent rules need to bother about defining the macro.
|
||||
linkstatic = True,
|
||||
local_defines = [
|
||||
# Turn on Large-file Support
|
||||
"_FILE_OFFSET_BITS=64",
|
||||
"_LARGEFILE64_SOURCE",
|
||||
"_LARGEFILE_SOURCE",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = select({
|
||||
":perfcounters": ["@libpfm"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "benchmark_main",
|
||||
srcs = ["src/benchmark_main.cc"],
|
||||
hdrs = [
|
||||
"include/benchmark/benchmark.h",
|
||||
"include/benchmark/benchmark_api.h",
|
||||
"include/benchmark/counter.h",
|
||||
"include/benchmark/export.h",
|
||||
"include/benchmark/macros.h",
|
||||
"include/benchmark/managers.h",
|
||||
"include/benchmark/registration.h",
|
||||
"include/benchmark/reporter.h",
|
||||
"include/benchmark/state.h",
|
||||
"include/benchmark/statistics.h",
|
||||
"include/benchmark/sysinfo.h",
|
||||
"include/benchmark/types.h",
|
||||
"include/benchmark/utils.h",
|
||||
],
|
||||
includes = ["include"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [":benchmark"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "benchmark_internal_headers",
|
||||
hdrs = glob(["src/*.h"]),
|
||||
visibility = ["//test:__pkg__"],
|
||||
)
|
||||
368
thirdparty/benchmark/CMakeLists.txt
vendored
368
thirdparty/benchmark/CMakeLists.txt
vendored
@ -1,368 +0,0 @@
|
||||
# Require CMake 3.13. If available, use the policies up to CMake 3.22.
|
||||
cmake_minimum_required (VERSION 3.13...3.22)
|
||||
|
||||
project (benchmark VERSION 1.9.5 LANGUAGES CXX)
|
||||
|
||||
option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON)
|
||||
option(BENCHMARK_ENABLE_EXCEPTIONS "Enable the use of exceptions in the benchmark library." ON)
|
||||
option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF)
|
||||
option(BENCHMARK_USE_LIBCXX "Build and test using libc++ as the standard library." OFF)
|
||||
option(BENCHMARK_ENABLE_WERROR "Build Release candidates with -Werror." ON)
|
||||
option(BENCHMARK_FORCE_WERROR "Build Release candidates with -Werror regardless of compiler issues." OFF)
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "PGI")
|
||||
# PGC++ maybe reporting false positives.
|
||||
set(BENCHMARK_ENABLE_WERROR OFF)
|
||||
endif()
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "NVHPC")
|
||||
set(BENCHMARK_ENABLE_WERROR OFF)
|
||||
endif()
|
||||
if(BENCHMARK_FORCE_WERROR)
|
||||
set(BENCHMARK_ENABLE_WERROR ON)
|
||||
endif(BENCHMARK_FORCE_WERROR)
|
||||
|
||||
if(NOT (MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))
|
||||
option(BENCHMARK_BUILD_32_BITS "Build a 32 bit version of the library." OFF)
|
||||
else()
|
||||
set(BENCHMARK_BUILD_32_BITS OFF CACHE BOOL "Build a 32 bit version of the library - unsupported when using MSVC)" FORCE)
|
||||
endif()
|
||||
option(BENCHMARK_ENABLE_INSTALL "Enable installation of benchmark. (Projects embedding benchmark may want to turn this OFF.)" ON)
|
||||
option(BENCHMARK_ENABLE_DOXYGEN "Build documentation with Doxygen." OFF)
|
||||
option(BENCHMARK_INSTALL_DOCS "Enable installation of documentation." ON)
|
||||
option(BENCHMARK_INSTALL_TOOLS "Enable installation of tools." ON)
|
||||
|
||||
# Allow unmet dependencies to be met using CMake's ExternalProject mechanics, which
|
||||
# may require downloading the source code.
|
||||
option(BENCHMARK_DOWNLOAD_DEPENDENCIES "Allow the downloading and in-tree building of unmet dependencies" OFF)
|
||||
|
||||
# This option can be used to disable building and running unit tests which depend on gtest
|
||||
# in cases where it is not possible to build or find a valid version of gtest.
|
||||
option(BENCHMARK_ENABLE_GTEST_TESTS "Enable building the unit tests which depend on gtest" ON)
|
||||
option(BENCHMARK_USE_BUNDLED_GTEST "Use bundled GoogleTest. If disabled, the find_package(GTest) will be used." ON)
|
||||
|
||||
option(BENCHMARK_ENABLE_LIBPFM "Enable performance counters provided by libpfm" OFF)
|
||||
|
||||
# Export only public symbols
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# As of CMake 3.18, CMAKE_SYSTEM_PROCESSOR is not set properly for MSVC and
|
||||
# cross-compilation (e.g. Host=x86_64, target=aarch64) requires using the
|
||||
# undocumented, but working variable.
|
||||
# See https://gitlab.kitware.com/cmake/cmake/-/issues/15170
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${MSVC_CXX_ARCHITECTURE_ID})
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM")
|
||||
set(CMAKE_CROSSCOMPILING TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ENABLE_ASSEMBLY_TESTS_DEFAULT OFF)
|
||||
function(should_enable_assembly_tests)
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
|
||||
if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage")
|
||||
# FIXME: The --coverage flag needs to be removed when building assembly
|
||||
# tests for this to work.
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
if (MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
|
||||
return()
|
||||
elseif(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||
return()
|
||||
elseif(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
# FIXME: Make these work on 32 bit builds
|
||||
return()
|
||||
elseif(BENCHMARK_BUILD_32_BITS)
|
||||
# FIXME: Make these work on 32 bit builds
|
||||
return()
|
||||
endif()
|
||||
find_program(LLVM_FILECHECK_EXE FileCheck)
|
||||
if (LLVM_FILECHECK_EXE)
|
||||
set(LLVM_FILECHECK_EXE "${LLVM_FILECHECK_EXE}" CACHE PATH "llvm filecheck" FORCE)
|
||||
message(STATUS "LLVM FileCheck Found: ${LLVM_FILECHECK_EXE}")
|
||||
else()
|
||||
message(STATUS "Failed to find LLVM FileCheck")
|
||||
return()
|
||||
endif()
|
||||
set(ENABLE_ASSEMBLY_TESTS_DEFAULT ON PARENT_SCOPE)
|
||||
endfunction()
|
||||
should_enable_assembly_tests()
|
||||
|
||||
# This option disables the building and running of the assembly verification tests
|
||||
option(BENCHMARK_ENABLE_ASSEMBLY_TESTS "Enable building and running the assembly tests"
|
||||
${ENABLE_ASSEMBLY_TESTS_DEFAULT})
|
||||
|
||||
# Make sure we can import out CMake functions
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
|
||||
# Read the git tags to determine the project version
|
||||
include(GetGitVersion)
|
||||
get_git_version(GIT_VERSION)
|
||||
|
||||
# If no git version can be determined, use the version
|
||||
# from the project() command
|
||||
if ("${GIT_VERSION}" STREQUAL "v0.0.0")
|
||||
set(VERSION "v${benchmark_VERSION}")
|
||||
else()
|
||||
set(VERSION "${GIT_VERSION}")
|
||||
endif()
|
||||
|
||||
# Normalize version: drop "v" prefix, replace first "-" with ".",
|
||||
# drop everything after second "-" (including said "-").
|
||||
string(STRIP ${VERSION} VERSION)
|
||||
if(VERSION MATCHES v[^-]*-)
|
||||
string(REGEX REPLACE "v([^-]*)-([0-9]+)-.*" "\\1.\\2" NORMALIZED_VERSION ${VERSION})
|
||||
else()
|
||||
string(REGEX REPLACE "v(.*)" "\\1" NORMALIZED_VERSION ${VERSION})
|
||||
endif()
|
||||
|
||||
# Tell the user what versions we are using
|
||||
message(STATUS "Google Benchmark version: ${VERSION}, normalized to ${NORMALIZED_VERSION}")
|
||||
|
||||
# The version of the libraries
|
||||
set(GENERIC_LIB_VERSION ${NORMALIZED_VERSION})
|
||||
string(SUBSTRING ${NORMALIZED_VERSION} 0 1 GENERIC_LIB_SOVERSION)
|
||||
|
||||
# Import our CMake modules
|
||||
include(AddCXXCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckLibraryExists)
|
||||
include(CXXFeatureCheck)
|
||||
|
||||
# Check for rt library, but explicitly disable for QNX
|
||||
if(QNXNTO)
|
||||
set(HAVE_LIB_RT FALSE)
|
||||
else()
|
||||
check_library_exists(rt shm_open "" HAVE_LIB_RT)
|
||||
endif()
|
||||
|
||||
if (BENCHMARK_BUILD_32_BITS)
|
||||
add_required_cxx_compiler_flag(-m32)
|
||||
endif()
|
||||
|
||||
set(BENCHMARK_CXX_STANDARD 17)
|
||||
|
||||
set(CMAKE_CXX_STANDARD ${BENCHMARK_CXX_STANDARD})
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if (MSVC)
|
||||
# Turn compiler warnings up to 11
|
||||
string(REGEX REPLACE "[-/]W[1-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
|
||||
# MP flag only applies to cl, not cl frontends to other compilers (e.g. clang-cl, icx-cl etc)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
endif()
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if(BENCHMARK_ENABLE_WERROR)
|
||||
add_cxx_compiler_flag(-WX)
|
||||
endif()
|
||||
|
||||
if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
|
||||
add_cxx_compiler_flag(-EHs-)
|
||||
add_cxx_compiler_flag(-EHa-)
|
||||
add_definitions(-D_HAS_EXCEPTIONS=0)
|
||||
endif()
|
||||
# Link time optimisation
|
||||
if (BENCHMARK_ENABLE_LTO)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /GL")
|
||||
string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO}")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
|
||||
string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
|
||||
string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /GL")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL "${CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL} /LTCG")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL} /LTCG")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} /LTCG")
|
||||
endif()
|
||||
else()
|
||||
# Turn on Large-file Support
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE)
|
||||
add_definitions(-D_LARGEFILE_SOURCE)
|
||||
# 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(-Wfloat-equal)
|
||||
add_cxx_compiler_flag(-Wold-style-cast)
|
||||
add_cxx_compiler_flag(-Wconversion)
|
||||
add_cxx_compiler_flag(-Wformat=2)
|
||||
if(BENCHMARK_ENABLE_WERROR)
|
||||
add_cxx_compiler_flag(-Werror)
|
||||
add_cxx_compiler_flag(-pedantic-errors)
|
||||
endif()
|
||||
if (NOT BENCHMARK_ENABLE_TESTING)
|
||||
# Disable warning when compiling tests as gtest does not use 'override'.
|
||||
add_cxx_compiler_flag(-Wsuggest-override)
|
||||
endif()
|
||||
add_cxx_compiler_flag(-pedantic)
|
||||
add_cxx_compiler_flag(-Wshorten-64-to-32)
|
||||
add_cxx_compiler_flag(-fstrict-aliasing)
|
||||
# Disable warnings regarding deprecated parts of the library while building
|
||||
# and testing those parts of the library.
|
||||
add_cxx_compiler_flag(-Wno-deprecated-declarations)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" OR CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
|
||||
# Intel silently ignores '-Wno-deprecated-declarations',
|
||||
# warning no. 1786 must be explicitly disabled.
|
||||
# See #631 for rationale.
|
||||
add_cxx_compiler_flag(-wd1786)
|
||||
add_cxx_compiler_flag(-fno-finite-math-only)
|
||||
# ICC17u2: overloaded virtual function "benchmark::Fixture::SetUp" is only partially
|
||||
# overridden (because of deprecated overload)
|
||||
add_cxx_compiler_flag(-wd654)
|
||||
endif()
|
||||
# Disable deprecation warnings for release builds (when -Werror is enabled).
|
||||
if(BENCHMARK_ENABLE_WERROR)
|
||||
add_cxx_compiler_flag(-Wno-deprecated)
|
||||
endif()
|
||||
if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
|
||||
add_cxx_compiler_flag(-fno-exceptions)
|
||||
endif()
|
||||
|
||||
if (HAVE_CXX_FLAG_FSTRICT_ALIASING)
|
||||
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") #ICC17u2: Many false positives for Wstrict-aliasing
|
||||
add_cxx_compiler_flag(-Wstrict-aliasing)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_cxx_compiler_flag(-Wthread-safety)
|
||||
if (HAVE_CXX_FLAG_WTHREAD_SAFETY)
|
||||
cxx_feature_check(THREAD_SAFETY_ATTRIBUTES "-DINCLUDE_DIRECTORIES=${PROJECT_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
# On most UNIX like platforms g++ and clang++ define _GNU_SOURCE as a
|
||||
# predefined macro, which turns on all of the wonderful libc extensions.
|
||||
# However g++ doesn't do this in Cygwin so we have to define it ourselves
|
||||
# since we depend on GNU/POSIX/BSD extensions.
|
||||
if (CYGWIN)
|
||||
add_definitions(-D_GNU_SOURCE=1)
|
||||
endif()
|
||||
|
||||
if (QNXNTO)
|
||||
add_definitions(-D_QNX_SOURCE)
|
||||
endif()
|
||||
|
||||
# Link time optimisation
|
||||
if (BENCHMARK_ENABLE_LTO)
|
||||
add_cxx_compiler_flag(-flto)
|
||||
add_cxx_compiler_flag(-Wno-lto-type-mismatch)
|
||||
if ("${CMAKE_CXX_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()
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
include(llvm-toolchain)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Coverage build type
|
||||
set(BENCHMARK_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG}"
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE)
|
||||
set(BENCHMARK_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_DEBUG}"
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE)
|
||||
set(BENCHMARK_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(
|
||||
BENCHMARK_CXX_FLAGS_COVERAGE
|
||||
BENCHMARK_EXE_LINKER_FLAGS_COVERAGE
|
||||
BENCHMARK_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.")
|
||||
add_cxx_compiler_flag(--coverage COVERAGE)
|
||||
endif()
|
||||
|
||||
if (BENCHMARK_USE_LIBCXX)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
add_cxx_compiler_flag(-stdlib=libc++)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
|
||||
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" OR
|
||||
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "IntelLLVM")
|
||||
add_cxx_compiler_flag(-nostdinc++)
|
||||
message(WARNING "libc++ header path must be manually specified using CMAKE_CXX_FLAGS")
|
||||
# Adding -nodefaultlibs directly to CMAKE_<TYPE>_LINKER_FLAGS will break
|
||||
# configuration checks such as 'find_package(Threads)'
|
||||
list(APPEND BENCHMARK_CXX_LINKER_FLAGS -nodefaultlibs)
|
||||
# -lc++ cannot be added directly to CMAKE_<TYPE>_LINKER_FLAGS because
|
||||
# linker flags appear before all linker inputs and -lc++ must appear after.
|
||||
list(APPEND BENCHMARK_CXX_LIBRARIES c++)
|
||||
else()
|
||||
message(FATAL_ERROR "-DBENCHMARK_USE_LIBCXX:BOOL=ON is not supported for compiler")
|
||||
endif()
|
||||
endif(BENCHMARK_USE_LIBCXX)
|
||||
|
||||
# C++ feature checks
|
||||
# Determine the correct regular expression engine to use
|
||||
cxx_feature_check(STD_REGEX)
|
||||
cxx_feature_check(GNU_POSIX_REGEX)
|
||||
cxx_feature_check(POSIX_REGEX)
|
||||
if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
|
||||
message(FATAL_ERROR "Failed to determine the source files for the regular expression backend")
|
||||
endif()
|
||||
if (NOT BENCHMARK_ENABLE_EXCEPTIONS AND HAVE_STD_REGEX
|
||||
AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
|
||||
message(WARNING "Using std::regex with exceptions disabled is not fully supported")
|
||||
endif()
|
||||
|
||||
cxx_feature_check(STEADY_CLOCK)
|
||||
# Ensure we have pthreads
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
# cxx_feature_check relies on try_run to probe compiler features. Because this
|
||||
# check does not produce a real target, target_link_libraries cannot be applied.
|
||||
# Therefore, link libraries are forwarded to try_run through
|
||||
# BENCHMARK_CXX_LIBRARIES.
|
||||
list(APPEND BENCHMARK_CXX_LIBRARIES Threads::Threads)
|
||||
cxx_feature_check(PTHREAD_AFFINITY)
|
||||
|
||||
if (BENCHMARK_ENABLE_LIBPFM)
|
||||
find_package(PFM REQUIRED)
|
||||
endif()
|
||||
|
||||
# Set up directories
|
||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
|
||||
# Build the targets
|
||||
add_subdirectory(src)
|
||||
|
||||
if (BENCHMARK_ENABLE_TESTING)
|
||||
enable_testing()
|
||||
if (BENCHMARK_ENABLE_GTEST_TESTS AND
|
||||
NOT (TARGET gtest AND TARGET gtest_main AND
|
||||
TARGET gmock AND TARGET gmock_main))
|
||||
if (BENCHMARK_USE_BUNDLED_GTEST)
|
||||
include(GoogleTest)
|
||||
else()
|
||||
find_package(GTest CONFIG REQUIRED)
|
||||
add_library(gtest ALIAS GTest::gtest)
|
||||
add_library(gtest_main ALIAS GTest::gtest_main)
|
||||
add_library(gmock ALIAS GTest::gmock)
|
||||
add_library(gmock_main ALIAS GTest::gmock_main)
|
||||
endif()
|
||||
endif()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
63
thirdparty/benchmark/CONTRIBUTING.md
vendored
63
thirdparty/benchmark/CONTRIBUTING.md
vendored
@ -1,63 +0,0 @@
|
||||
# How to contribute #
|
||||
|
||||
We'd love to accept your patches and contributions to this project. There are
|
||||
a just a few small guidelines you need to follow.
|
||||
|
||||
|
||||
## Contributor License Agreement ##
|
||||
|
||||
Contributions to any Google project must be accompanied by a Contributor
|
||||
License Agreement. This is not a copyright **assignment**, it simply gives
|
||||
Google permission to use and redistribute your contributions as part of the
|
||||
project.
|
||||
|
||||
* If you are an individual writing original source code and you're sure you
|
||||
own the intellectual property, then you'll need to sign an [individual
|
||||
CLA][].
|
||||
|
||||
* If you work for a company that wants to allow you to contribute your work,
|
||||
then you'll need to sign a [corporate CLA][].
|
||||
|
||||
You generally only need to submit a CLA once, so if you've already submitted
|
||||
one (even if it was for a different project), you probably don't need to do it
|
||||
again.
|
||||
|
||||
[individual CLA]: https://developers.google.com/open-source/cla/individual
|
||||
[corporate CLA]: https://developers.google.com/open-source/cla/corporate
|
||||
|
||||
Once your CLA is submitted (or if you already submitted one for
|
||||
another Google project), make a commit adding yourself to the
|
||||
[AUTHORS][] and [CONTRIBUTORS][] files. This commit can be part
|
||||
of your first [pull request][].
|
||||
|
||||
[AUTHORS]: AUTHORS
|
||||
[CONTRIBUTORS]: CONTRIBUTORS
|
||||
|
||||
|
||||
## Submitting a patch ##
|
||||
|
||||
1. It's generally best to start by opening a new issue describing the bug or
|
||||
feature you're intending to fix. Even if you think it's relatively minor,
|
||||
it's helpful to know what people are working on. Mention in the initial
|
||||
issue that you are planning to work on that bug or feature so that it can
|
||||
be assigned to you.
|
||||
|
||||
1. Follow the normal process of [forking][] the project, and setup a new
|
||||
branch to work in. It's important that each group of changes be done in
|
||||
separate branches in order to ensure that a pull request only includes the
|
||||
commits related to that bug or feature.
|
||||
|
||||
1. Do your best to have [well-formed commit messages][] for each change.
|
||||
This provides consistency throughout the project, and ensures that commit
|
||||
messages are able to be formatted properly by various git tools.
|
||||
|
||||
1. Finally, push the commits to your fork and submit a [pull request][].
|
||||
|
||||
|
||||
## AI usage ##
|
||||
|
||||
Please consult [AGENTS](AGENTS.md) file.
|
||||
|
||||
[forking]: https://help.github.com/articles/fork-a-repo
|
||||
[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
[pull request]: https://help.github.com/articles/creating-a-pull-request
|
||||
108
thirdparty/benchmark/CONTRIBUTORS
vendored
108
thirdparty/benchmark/CONTRIBUTORS
vendored
@ -1,108 +0,0 @@
|
||||
# People who have agreed to one of the CLAs and can contribute patches.
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees are listed here
|
||||
# but not in AUTHORS, because Google holds the copyright.
|
||||
#
|
||||
# Names should be added to this file only after verifying that
|
||||
# the individual or the individual's organization has agreed to
|
||||
# the appropriate Contributor License Agreement, found here:
|
||||
#
|
||||
# https://developers.google.com/open-source/cla/individual
|
||||
# https://developers.google.com/open-source/cla/corporate
|
||||
#
|
||||
# The agreement for individuals can be filled out on the web.
|
||||
#
|
||||
# When adding J Random Contributor's name to this file,
|
||||
# either J's name or J's organization's name should be
|
||||
# added to the AUTHORS file, depending on whether the
|
||||
# individual or corporate CLA was used.
|
||||
#
|
||||
# Names should be added to this file as:
|
||||
# Name <email address>
|
||||
#
|
||||
# Please keep the list sorted.
|
||||
|
||||
Abhina Sreeskantharajan <abhina.sreeskantharajan@ibm.com>
|
||||
Albert Pretorius <pretoalb@gmail.com>
|
||||
Alex Steele <steelal123@gmail.com>
|
||||
Andriy Berestovskyy <berestovskyy@gmail.com>
|
||||
Arne Beer <arne@twobeer.de>
|
||||
Bátor Tallér <bator.taller@shapr3d.com>
|
||||
Benjamin King <kingbenja5@gmail.com>
|
||||
Billy Robert O'Neal III <billy.oneal@gmail.com> <bion@microsoft.com>
|
||||
Cezary Skrzyński <czars1988@gmail.com>
|
||||
Chris Kennelly <ckennelly@google.com> <ckennelly@ckennelly.com>
|
||||
Christian Wassermann <christian_wassermann@web.de>
|
||||
Christopher Seymour <chris.j.seymour@hotmail.com>
|
||||
Colin Braley <braley.colin@gmail.com>
|
||||
Cyrille Faucheux <cyrille.faucheux@gmail.com>
|
||||
Daniel Harvey <danielharvey458@gmail.com>
|
||||
David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
|
||||
Deniz Evrenci <denizevrenci@gmail.com>
|
||||
Dominic Hamon <dma@stripysock.com> <dominic@google.com>
|
||||
Dominik Czarnota <dominik.b.czarnota@gmail.com>
|
||||
Dominik Korman <kormandominik@gmail.com>
|
||||
Donald Aingworth <donalds_junk_mail@yahoo.com>
|
||||
Doug Evans <xdje42@gmail.com>
|
||||
Eric Backus <eric_backus@alum.mit.edu>
|
||||
Eric Fiselier <eric@efcs.ca>
|
||||
Eugene Zhuk <eugene.zhuk@gmail.com>
|
||||
Evgeny Safronov <division494@gmail.com>
|
||||
Fabien Pichot <pichot.fabien@gmail.com>
|
||||
Fanbo Meng <fanbo.meng@ibm.com>
|
||||
Federico Ficarelli <federico.ficarelli@gmail.com>
|
||||
Felix Homann <linuxaudio@showlabor.de>
|
||||
Felmon Fekadu <felmonon@gmail.com>
|
||||
Geoffrey Martin-Noble <gcmn@google.com> <gmngeoffrey@gmail.com>
|
||||
Gergely Meszaros <maetveis@gmail.com>
|
||||
Gergő Szitár <szitar.gergo@gmail.com>
|
||||
Haihan Jiang <haihanj99@gmail.com>
|
||||
Hannes Hauswedell <h2@fsfe.org>
|
||||
Henrique Bucher <hbucher@gmail.com>
|
||||
Ismael Jimenez Martinez <ismael.jimenez.martinez@gmail.com>
|
||||
Iakov Sergeev <yahontu@gmail.com>
|
||||
Jern-Kuan Leong <jernkuan@gmail.com>
|
||||
JianXiong Zhou <zhoujianxiong2@gmail.com>
|
||||
Joao Paulo Magalhaes <joaoppmagalhaes@gmail.com>
|
||||
John Millikin <jmillikin@stripe.com>
|
||||
Jordan Williams <jwillikers@protonmail.com>
|
||||
Jussi Knuuttila <jussi.knuuttila@gmail.com>
|
||||
Kaito Udagawa <umireon@gmail.com>
|
||||
Kai Wolf <kai.wolf@gmail.com>
|
||||
Kishan Kumar <kumar.kishan@outlook.com>
|
||||
Kostiantyn Lazukin <konstantin.lazukin@gmail.com>
|
||||
Lei Xu <eddyxu@gmail.com>
|
||||
Marcel Jacobse <mjacobse@uni-bremen.de>
|
||||
Matt Clarkson <mattyclarkson@gmail.com>
|
||||
Maxim Vafin <maxvafin@gmail.com>
|
||||
Mike Apodaca <gatorfax@gmail.com>
|
||||
Min-Yih Hsu <yihshyng223@gmail.com>
|
||||
Nick Hutchinson <nshutchinson@gmail.com>
|
||||
Norman Heino <norman.heino@gmail.com>
|
||||
Oleksandr Sochka <sasha.sochka@gmail.com>
|
||||
Olga Fadeeva <olga.kiselik@gmail.com>
|
||||
Ori Livneh <ori.livneh@gmail.com>
|
||||
Pascal Leroy <phl@google.com>
|
||||
Paul Redmond <paul.redmond@gmail.com>
|
||||
Pierre Phaneuf <pphaneuf@google.com>
|
||||
Prithvi Rao <ee22b024@smail.iitm.ac.in>
|
||||
qorexdev <sanenkosana600@gmail.com>
|
||||
Radoslav Yovchev <radoslav.tm@gmail.com>
|
||||
Raghu Raja <raghu@enfabrica.net>
|
||||
Rainer Orth <ro@cebitec.uni-bielefeld.de>
|
||||
Raul Marin <rmrodriguez@cartodb.com>
|
||||
Ray Glover <ray.glover@uk.ibm.com>
|
||||
Robert Guo <robert.guo@mongodb.com>
|
||||
Roman Lebedev <lebedev.ri@gmail.com>
|
||||
Sayan Bhattacharjee <aero.sayan@gmail.com>
|
||||
Shashank Thakur <shashankt2004@gmail.com>
|
||||
ShengYi Hung <aokblast@FreeBSD.org>
|
||||
Shuo Chen <chenshuo@chenshuo.com>
|
||||
Steven Wan <wan.yu@ibm.com>
|
||||
Tobias Schmidt <tobias.schmidt@in.tum.de>
|
||||
Tobias Ulvgård <tobias.ulvgard@dirac.se>
|
||||
Tom Madams <tom.ej.madams@gmail.com> <tmadams@google.com>
|
||||
XiaoWei Lu <shaway77606@gmail.com>
|
||||
Yixuan Qiu <yixuanq@gmail.com>
|
||||
Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
Zbigniew Skowron <zbychs@gmail.com>
|
||||
202
thirdparty/benchmark/LICENSE
vendored
202
thirdparty/benchmark/LICENSE
vendored
@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
41
thirdparty/benchmark/MODULE.bazel
vendored
41
thirdparty/benchmark/MODULE.bazel
vendored
@ -1,41 +0,0 @@
|
||||
module(
|
||||
name = "google_benchmark",
|
||||
version = "1.9.5",
|
||||
)
|
||||
|
||||
bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
||||
bazel_dep(name = "platforms", version = "0.0.10")
|
||||
bazel_dep(name = "rules_cc", version = "0.0.9")
|
||||
|
||||
bazel_dep(name = "rules_python", version = "1.0.0", dev_dependency = True)
|
||||
bazel_dep(name = "googletest", version = "1.14.0", dev_dependency = True, repo_name = "com_google_googletest")
|
||||
|
||||
bazel_dep(name = "libpfm", version = "4.11.0.bcr.1")
|
||||
|
||||
# Register a toolchain for Python 3.9 to be able to build numpy. Python
|
||||
# versions >=3.10 are problematic.
|
||||
# A second reason for this is to be able to build Python hermetically instead
|
||||
# of relying on the changing default version from rules_python.
|
||||
|
||||
python = use_extension("@rules_python//python/extensions:python.bzl", "python", dev_dependency = True)
|
||||
python.toolchain(python_version = "3.8")
|
||||
python.toolchain(python_version = "3.9")
|
||||
python.toolchain(python_version = "3.10")
|
||||
python.toolchain(python_version = "3.11")
|
||||
python.toolchain(
|
||||
is_default = True,
|
||||
python_version = "3.12",
|
||||
)
|
||||
python.toolchain(python_version = "3.13")
|
||||
|
||||
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip", dev_dependency = True)
|
||||
pip.parse(
|
||||
hub_name = "tools_pip_deps",
|
||||
python_version = "3.12",
|
||||
requirements_lock = "//tools:requirements.txt",
|
||||
)
|
||||
use_repo(pip, "tools_pip_deps")
|
||||
|
||||
# -- bazel_dep definitions -- #
|
||||
|
||||
bazel_dep(name = "nanobind_bazel", version = "2.9.2", dev_dependency = True)
|
||||
275
thirdparty/benchmark/README.md
vendored
275
thirdparty/benchmark/README.md
vendored
@ -1,275 +0,0 @@
|
||||
# Benchmark
|
||||
|
||||
[](https://github.com/google/benchmark/actions?query=workflow%3Abuild-and-test)
|
||||
[](https://github.com/google/benchmark/actions/workflows/bazel.yml)
|
||||
[](https://github.com/google/benchmark/actions?query=workflow%3Atest-bindings)
|
||||
[](https://coveralls.io/r/google/benchmark)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/google/benchmark)
|
||||
|
||||
[](https://discord.gg/cz7UX7wKC2)
|
||||
|
||||
A library to benchmark code snippets, similar to unit tests. Example:
|
||||
|
||||
```c++
|
||||
#include <benchmark/registration.h>
|
||||
#include <benchmark/state.h>
|
||||
|
||||
static void BM_SomeFunction(benchmark::State& state) {
|
||||
// Perform setup here
|
||||
for (auto _ : state) {
|
||||
// This code gets timed
|
||||
SomeFunction();
|
||||
}
|
||||
}
|
||||
// Register the function as a benchmark
|
||||
BENCHMARK(BM_SomeFunction);
|
||||
// Run the benchmark
|
||||
BENCHMARK_MAIN();
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started, see [Requirements](#requirements) and
|
||||
[Installation](#installation). See [Usage](#usage) for a full example and the
|
||||
[User Guide](docs/user_guide.md) for a more comprehensive feature overview.
|
||||
|
||||
It may also help to read the [Google Test documentation](https://github.com/google/googletest/blob/main/docs/primer.md)
|
||||
as some of the structural aspects of the APIs are similar.
|
||||
|
||||
## Resources
|
||||
|
||||
[Discussion group](https://groups.google.com/d/forum/benchmark-discuss)
|
||||
|
||||
IRC channels:
|
||||
* [libera](https://libera.chat) #benchmark
|
||||
|
||||
[Additional Tooling Documentation](docs/tools.md)
|
||||
|
||||
[Assembly Testing Documentation](docs/AssemblyTests.md)
|
||||
|
||||
[Building and installing Python bindings](docs/python_bindings.md)
|
||||
|
||||
## Requirements
|
||||
|
||||
The library can be used with C++11. However, it requires C++17 to build,
|
||||
including compiler and standard library support.
|
||||
|
||||
_See [dependencies.md](docs/dependencies.md) for more details regarding supported
|
||||
compilers and standards._
|
||||
|
||||
If you have need for a particular compiler to be supported, patches are very welcome.
|
||||
|
||||
See [Platform-Specific Build Instructions](docs/platform_specific_build_instructions.md).
|
||||
|
||||
## Installation
|
||||
|
||||
This describes the installation process using cmake. As pre-requisites, you'll
|
||||
need git and cmake installed.
|
||||
|
||||
_See [dependencies.md](docs/dependencies.md) for more details regarding supported
|
||||
versions of build tools._
|
||||
|
||||
```bash
|
||||
# Check out the library.
|
||||
$ git clone https://github.com/google/benchmark.git
|
||||
# Go to the library root directory
|
||||
$ cd benchmark
|
||||
# Make a build directory to place the build output.
|
||||
$ cmake -E make_directory "build"
|
||||
# Generate build system files with cmake, and download any dependencies.
|
||||
$ cmake -DBENCHMARK_DOWNLOAD_DEPENDENCIES=on -DCMAKE_BUILD_TYPE=Release -S . -B "build"
|
||||
# Build the library.
|
||||
$ cmake --build "build" --config Release
|
||||
```
|
||||
This builds the `benchmark` and `benchmark_main` libraries and tests.
|
||||
On a unix system, the build directory should now look something like this:
|
||||
|
||||
```
|
||||
/benchmark
|
||||
/build
|
||||
/src
|
||||
/libbenchmark.a
|
||||
/libbenchmark_main.a
|
||||
/test
|
||||
...
|
||||
```
|
||||
|
||||
Next, you can run the tests to check the build.
|
||||
|
||||
```bash
|
||||
$ cmake -E chdir "build" ctest --build-config Release
|
||||
```
|
||||
|
||||
If you want to install the library globally, also run:
|
||||
|
||||
```
|
||||
sudo cmake --build "build" --config Release --target install
|
||||
```
|
||||
|
||||
Note that Google Benchmark requires Google Test to build and run the tests. This
|
||||
dependency can be provided two ways:
|
||||
|
||||
* Checkout the Google Test sources into `benchmark/googletest`.
|
||||
* Otherwise, if `-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON` is specified during
|
||||
configuration as above, the library will automatically download and build
|
||||
any required dependencies.
|
||||
|
||||
If you do not wish to build and run the tests, add `-DBENCHMARK_ENABLE_GTEST_TESTS=OFF`
|
||||
to `CMAKE_ARGS`.
|
||||
|
||||
### 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, add
|
||||
`-DCMAKE_BUILD_TYPE=Release` when generating the build system files, as shown
|
||||
above. The use of `--config Release` in build commands is needed to properly
|
||||
support multi-configuration tools (like Visual Studio for example) and can be
|
||||
skipped for other build systems (like Makefile).
|
||||
|
||||
To enable link-time optimisation, also add `-DBENCHMARK_ENABLE_LTO=true` when
|
||||
generating the build system files.
|
||||
|
||||
If you are using gcc, you might need to set `GCC_AR` and `GCC_RANLIB` cmake
|
||||
cache variables, if autodetection fails.
|
||||
|
||||
If you are using clang, you may need to set `LLVMAR_EXECUTABLE`,
|
||||
`LLVMNM_EXECUTABLE` and `LLVMRANLIB_EXECUTABLE` cmake cache variables.
|
||||
|
||||
To enable sanitizer checks (eg., `asan` and `tsan`), add:
|
||||
```
|
||||
-DCMAKE_C_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=address -fsanitize=thread -fno-sanitize-recover=all"
|
||||
-DCMAKE_CXX_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=address -fsanitize=thread -fno-sanitize-recover=all "
|
||||
```
|
||||
|
||||
### Stable and Experimental Library Versions
|
||||
|
||||
The main branch contains the latest stable version of the benchmarking library;
|
||||
the API of which can be considered largely stable, with source breaking changes
|
||||
being made only upon the release of a new major version.
|
||||
|
||||
Newer, experimental, features are implemented and tested on the
|
||||
[`v2` branch](https://github.com/google/benchmark/tree/v2). Users who wish
|
||||
to use, test, and provide feedback on the new features are encouraged to try
|
||||
this branch. However, this branch provides no stability guarantees and reserves
|
||||
the right to change and break the API at any time.
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic usage
|
||||
|
||||
Define a function that executes the code to measure, register it as a benchmark
|
||||
function using the `BENCHMARK` macro, and ensure an appropriate `main` function
|
||||
is available:
|
||||
|
||||
```c++
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
static void BM_StringCreation(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
std::string empty_string;
|
||||
}
|
||||
// Register the function as a benchmark
|
||||
BENCHMARK(BM_StringCreation);
|
||||
|
||||
// Define another benchmark
|
||||
static void BM_StringCopy(benchmark::State& state) {
|
||||
std::string x = "hello";
|
||||
for (auto _ : state)
|
||||
std::string copy(x);
|
||||
}
|
||||
BENCHMARK(BM_StringCopy);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
```
|
||||
|
||||
To run the benchmark, compile and link against the `benchmark` library
|
||||
(libbenchmark.a/.so). If you followed the build steps above, this library will
|
||||
be under the build directory you created.
|
||||
|
||||
```bash
|
||||
# Example on linux after running the build steps above. Assumes the
|
||||
# `benchmark` and `build` directories are under the current directory.
|
||||
$ g++ mybenchmark.cc -std=c++11 -isystem benchmark/include \
|
||||
-Lbenchmark/build/src -lbenchmark -lpthread -o mybenchmark
|
||||
```
|
||||
|
||||
Alternatively, link against the `benchmark_main` library and remove
|
||||
`BENCHMARK_MAIN();` above to get the same behavior.
|
||||
|
||||
The compiled executable will run all benchmarks by default. Pass the `--help`
|
||||
flag for option information or see the [User Guide](docs/user_guide.md).
|
||||
|
||||
### Usage with CMake
|
||||
|
||||
If using CMake, it is recommended to link against the project-provided
|
||||
`benchmark::benchmark` or `benchmark::benchmark_main` targets using
|
||||
`target_link_libraries`. Link to `benchmark::benchmark` when your target
|
||||
defines its own `main` function, or link to `benchmark::benchmark_main` to use
|
||||
the default benchmark entry point. The `benchmark::benchmark_main` target links
|
||||
`benchmark::benchmark` transitively.
|
||||
It is possible to use ```find_package``` to import an installed version of the
|
||||
library.
|
||||
```cmake
|
||||
find_package(benchmark REQUIRED)
|
||||
```
|
||||
Alternatively, ```add_subdirectory``` will incorporate the library directly in
|
||||
to one's CMake project.
|
||||
```cmake
|
||||
add_subdirectory(benchmark)
|
||||
```
|
||||
Either way, link to the library as follows.
|
||||
```cmake
|
||||
target_link_libraries(MyTarget benchmark::benchmark)
|
||||
# Or, when you do not define your own main:
|
||||
target_link_libraries(MyTarget benchmark::benchmark_main)
|
||||
```
|
||||
When benchmark sources are shared through an intermediate CMake target, choose
|
||||
an object library instead of a static library:
|
||||
|
||||
```cmake
|
||||
add_library(shared_benchmarks OBJECT bench.cc)
|
||||
target_link_libraries(shared_benchmarks benchmark::benchmark_main)
|
||||
add_executable(runnable_benchmarks)
|
||||
target_link_libraries(runnable_benchmarks shared_benchmarks)
|
||||
```
|
||||
|
||||
This links the object file that contains `BENCHMARK` registrations into the
|
||||
final executable. If those registrations are placed only in an intermediate
|
||||
`STATIC` library, the linker may not copy static registration symbols, and thus
|
||||
benchmarks will not be part of the final executable.
|
||||
|
||||
#### Embedding Google Benchmark in another CMake project
|
||||
|
||||
There are two common ways to consume Google Benchmark from a CMake project:
|
||||
|
||||
* Use an installed or package-managed copy, for example from a system package
|
||||
manager or vcpkg, and import it with `find_package(benchmark REQUIRED)`.
|
||||
* Add this repository to the source tree, for example as a submodule or
|
||||
`FetchContent` dependency, and call `add_subdirectory`.
|
||||
|
||||
The installed form keeps Google Benchmark's build separate from the parent
|
||||
project and is usually the simplest choice for system packages and vcpkg. The
|
||||
source-tree form is useful when the parent project wants to pin a specific
|
||||
commit or build Google Benchmark as part of its normal CMake configure step.
|
||||
|
||||
When embedding from source, most projects should turn off Google Benchmark's
|
||||
tests and install rules:
|
||||
|
||||
```cmake
|
||||
set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
|
||||
set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(third_party/benchmark)
|
||||
target_link_libraries(MyTarget benchmark::benchmark)
|
||||
```
|
||||
|
||||
If Google Test is not already provided by the parent build, either check out the
|
||||
Google Test sources under `benchmark/googletest` or configure with
|
||||
`BENCHMARK_DOWNLOAD_DEPENDENCIES=ON`. For projects that only link the benchmark
|
||||
library and do not build Google Benchmark's tests, disabling
|
||||
`BENCHMARK_ENABLE_GTEST_TESTS` avoids the Google Test dependency.
|
||||
|
||||
Google Benchmark follows CMake's `BUILD_SHARED_LIBS` setting when selecting
|
||||
static or shared library output. On Windows, keep this setting consistent with
|
||||
the rest of the project and make sure the same runtime library configuration is
|
||||
used across the benchmark library and the targets that link it.
|
||||
20
thirdparty/benchmark/WORKSPACE
vendored
20
thirdparty/benchmark/WORKSPACE
vendored
@ -1,20 +0,0 @@
|
||||
workspace(name = "com_github_google_benchmark")
|
||||
|
||||
load("//:bazel/benchmark_deps.bzl", "benchmark_deps")
|
||||
|
||||
benchmark_deps()
|
||||
|
||||
load("@rules_python//python:repositories.bzl", "py_repositories")
|
||||
|
||||
py_repositories()
|
||||
|
||||
load("@rules_python//python:pip.bzl", "pip_parse")
|
||||
|
||||
pip_parse(
|
||||
name = "tools_pip_deps",
|
||||
requirements_lock = "//tools:requirements.txt",
|
||||
)
|
||||
|
||||
load("@tools_pip_deps//:requirements.bzl", "install_deps")
|
||||
|
||||
install_deps()
|
||||
2
thirdparty/benchmark/WORKSPACE.bzlmod
vendored
2
thirdparty/benchmark/WORKSPACE.bzlmod
vendored
@ -1,2 +0,0 @@
|
||||
# This file marks the root of the Bazel workspace.
|
||||
# See MODULE.bazel for dependencies and setup.
|
||||
2
thirdparty/benchmark/_config.yml
vendored
2
thirdparty/benchmark/_config.yml
vendored
@ -1,2 +0,0 @@
|
||||
theme: jekyll-theme-midnight
|
||||
markdown: GFM
|
||||
50
thirdparty/benchmark/appveyor.yml
vendored
50
thirdparty/benchmark/appveyor.yml
vendored
@ -1,50 +0,0 @@
|
||||
version: '{build}'
|
||||
|
||||
image: Visual Studio 2017
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017"
|
||||
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017 Win64"
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
generator: "Visual Studio 14 2015"
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
generator: "Visual Studio 14 2015 Win64"
|
||||
|
||||
- compiler: gcc-5.3.0-posix
|
||||
generator: "MinGW Makefiles"
|
||||
cxx_path: 'C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
install:
|
||||
# git bash conflicts with MinGW makefiles
|
||||
- if "%generator%"=="MinGW Makefiles" (set "PATH=%PATH:C:\Program Files\Git\usr\bin;=%")
|
||||
- if not "%cxx_path%"=="" (set "PATH=%PATH%;%cxx_path%")
|
||||
|
||||
build_script:
|
||||
- md _build -Force
|
||||
- cd _build
|
||||
- echo %configuration%
|
||||
- cmake -G "%generator%" "-DCMAKE_BUILD_TYPE=%configuration%" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON ..
|
||||
- cmake --build . --config %configuration%
|
||||
|
||||
test_script:
|
||||
- ctest --build-config %configuration% --timeout 300 --output-on-failure
|
||||
|
||||
artifacts:
|
||||
- path: '_build/CMakeFiles/*.log'
|
||||
name: logs
|
||||
- path: '_build/Testing/**/*.xml'
|
||||
name: test_results
|
||||
54
thirdparty/benchmark/bazel/benchmark_deps.bzl
vendored
54
thirdparty/benchmark/bazel/benchmark_deps.bzl
vendored
@ -1,54 +0,0 @@
|
||||
"""
|
||||
This file contains the Bazel build dependencies for Google Benchmark (both C++ source and Python bindings).
|
||||
"""
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
def benchmark_deps():
|
||||
"""Loads dependencies required to build Google Benchmark."""
|
||||
|
||||
if "bazel_skylib" not in native.existing_rules():
|
||||
http_archive(
|
||||
name = "bazel_skylib",
|
||||
sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
if "rules_python" not in native.existing_rules():
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
sha256 = "e85ae30de33625a63eca7fc40a94fea845e641888e52f32b6beea91e8b1b2793",
|
||||
strip_prefix = "rules_python-0.27.1",
|
||||
url = "https://github.com/bazelbuild/rules_python/releases/download/0.27.1/rules_python-0.27.1.tar.gz",
|
||||
)
|
||||
|
||||
if "com_google_googletest" not in native.existing_rules():
|
||||
new_git_repository(
|
||||
name = "com_google_googletest",
|
||||
remote = "https://github.com/google/googletest.git",
|
||||
tag = "release-1.12.1",
|
||||
)
|
||||
|
||||
if "nanobind" not in native.existing_rules():
|
||||
new_git_repository(
|
||||
name = "nanobind",
|
||||
remote = "https://github.com/wjakob/nanobind.git",
|
||||
tag = "v1.9.2",
|
||||
build_file = "@//bindings/python:nanobind.BUILD",
|
||||
recursive_init_submodules = True,
|
||||
)
|
||||
|
||||
if "libpfm" not in native.existing_rules():
|
||||
# Downloaded from v4.9.0 tag at https://sourceforge.net/p/perfmon2/libpfm4/ref/master/tags/
|
||||
http_archive(
|
||||
name = "libpfm",
|
||||
build_file = str(Label("//tools:libpfm.BUILD.bazel")),
|
||||
sha256 = "5da5f8872bde14b3634c9688d980f68bda28b510268723cc12973eedbab9fecc",
|
||||
type = "tar.gz",
|
||||
strip_prefix = "libpfm-4.11.0",
|
||||
urls = ["https://sourceforge.net/projects/perfmon2/files/libpfm4/libpfm-4.11.0.tar.gz/download"],
|
||||
)
|
||||
@ -1,34 +0,0 @@
|
||||
load("@nanobind_bazel//:build_defs.bzl", "nanobind_extension", "nanobind_stubgen")
|
||||
load("@rules_python//python:defs.bzl", "py_library", "py_test")
|
||||
|
||||
py_library(
|
||||
name = "google_benchmark",
|
||||
srcs = ["__init__.py"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":_benchmark",
|
||||
],
|
||||
)
|
||||
|
||||
nanobind_extension(
|
||||
name = "_benchmark",
|
||||
srcs = ["benchmark.cc"],
|
||||
deps = ["//:benchmark"],
|
||||
)
|
||||
|
||||
nanobind_stubgen(
|
||||
name = "benchmark_stubgen",
|
||||
marker_file = "bindings/python/google_benchmark/py.typed",
|
||||
module = ":_benchmark",
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "example",
|
||||
srcs = ["example.py"],
|
||||
python_version = "PY3",
|
||||
srcs_version = "PY3",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":google_benchmark",
|
||||
],
|
||||
)
|
||||
@ -1,136 +0,0 @@
|
||||
# Copyright 2020 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Python benchmarking utilities.
|
||||
|
||||
Example usage:
|
||||
import google_benchmark as benchmark
|
||||
|
||||
@benchmark.register
|
||||
def my_benchmark(state):
|
||||
... # Code executed outside `while` loop is not timed.
|
||||
|
||||
while state:
|
||||
... # Code executed within `while` loop is timed.
|
||||
|
||||
if __name__ == '__main__':
|
||||
benchmark.main()
|
||||
"""
|
||||
|
||||
import atexit
|
||||
|
||||
from google_benchmark import _benchmark
|
||||
from google_benchmark._benchmark import (
|
||||
Counter as Counter,
|
||||
State as State,
|
||||
kMicrosecond as kMicrosecond,
|
||||
kMillisecond as kMillisecond,
|
||||
kNanosecond as kNanosecond,
|
||||
kSecond as kSecond,
|
||||
o1 as o1,
|
||||
oAuto as oAuto,
|
||||
oLambda as oLambda,
|
||||
oLogN as oLogN,
|
||||
oN as oN,
|
||||
oNCubed as oNCubed,
|
||||
oNLogN as oNLogN,
|
||||
oNone as oNone,
|
||||
oNSquared as oNSquared,
|
||||
)
|
||||
|
||||
__version__ = "1.9.5"
|
||||
|
||||
|
||||
class __OptionMaker:
|
||||
"""A stateless class to collect benchmark options.
|
||||
|
||||
Collect all decorator calls like @option.range(start=0, limit=1<<5).
|
||||
"""
|
||||
|
||||
class Options:
|
||||
"""Pure data class to store options calls, along with the benchmarked
|
||||
function."""
|
||||
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
self.builder_calls = []
|
||||
|
||||
@classmethod
|
||||
def make(cls, func_or_options):
|
||||
"""Make Options from Options or the benchmarked function."""
|
||||
if isinstance(func_or_options, cls.Options):
|
||||
return func_or_options
|
||||
return cls.Options(func_or_options)
|
||||
|
||||
def __getattr__(self, builder_name):
|
||||
"""Append option call in the Options."""
|
||||
|
||||
# The function that get returned on @option.range(start=0, limit=1<<5).
|
||||
def __builder_method(*args, **kwargs):
|
||||
# The decorator that get called, either with the benchmared function
|
||||
# or the previous Options
|
||||
def __decorator(func_or_options):
|
||||
options = self.make(func_or_options)
|
||||
options.builder_calls.append((builder_name, args, kwargs))
|
||||
# The decorator returns Options so it is not technically a
|
||||
# decorator and needs a final call to @register
|
||||
return options
|
||||
|
||||
return __decorator
|
||||
|
||||
return __builder_method
|
||||
|
||||
|
||||
# Alias for nicer API.
|
||||
# We have to instantiate an object, even if stateless, to be able to use
|
||||
# __getattr__ on option.range
|
||||
option = __OptionMaker()
|
||||
|
||||
|
||||
def register(undefined=None, *, name=None):
|
||||
"""Register function for benchmarking."""
|
||||
if undefined is None:
|
||||
# Decorator is called without parenthesis so we return a decorator
|
||||
return lambda f: register(f, name=name)
|
||||
|
||||
# We have either the function to benchmark (simple case) or an instance of
|
||||
# Options (@option._ case).
|
||||
options = __OptionMaker.make(undefined)
|
||||
|
||||
if name is None:
|
||||
name = options.func.__name__
|
||||
|
||||
# We register the benchmark and reproduce all the @option._ calls onto the
|
||||
# benchmark builder pattern
|
||||
benchmark = _benchmark.RegisterBenchmark(name, options.func)
|
||||
for name, args, kwargs in options.builder_calls[::-1]:
|
||||
getattr(benchmark, name)(*args, **kwargs)
|
||||
|
||||
# return the benchmarked function because the decorator does not modify it
|
||||
return options.func
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> None:
|
||||
import sys
|
||||
|
||||
_benchmark.Initialize(argv or sys.argv)
|
||||
return _benchmark.RunSpecifiedBenchmarks()
|
||||
|
||||
|
||||
# FIXME: can we rerun with disabled ASLR?
|
||||
|
||||
# Methods for use with custom main function.
|
||||
initialize = _benchmark.Initialize
|
||||
run_benchmarks = _benchmark.RunSpecifiedBenchmarks
|
||||
add_custom_context = _benchmark.AddCustomContext
|
||||
atexit.register(_benchmark.ClearRegisteredBenchmarks)
|
||||
@ -1,189 +0,0 @@
|
||||
// Benchmark for Python.
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "nanobind/nanobind.h"
|
||||
#include "nanobind/operators.h"
|
||||
#include "nanobind/stl/bind_map.h"
|
||||
#include "nanobind/stl/string.h"
|
||||
#include "nanobind/stl/vector.h"
|
||||
|
||||
NB_MAKE_OPAQUE(benchmark::UserCounters);
|
||||
|
||||
namespace {
|
||||
namespace nb = nanobind;
|
||||
|
||||
std::vector<std::string> Initialize(const std::vector<std::string>& argv) {
|
||||
std::vector<char*> ptrs;
|
||||
ptrs.reserve(argv.size());
|
||||
for (auto& arg : argv) {
|
||||
ptrs.push_back(const_cast<char*>(arg.c_str()));
|
||||
}
|
||||
if (!ptrs.empty()) {
|
||||
// The `argv` pointers here become invalid when this function returns, but
|
||||
// benchmark holds the pointer to `argv[0]`. We create a static copy of it
|
||||
// so it persists, and replace the pointer below.
|
||||
static std::string executable_name(argv[0]);
|
||||
ptrs[0] = const_cast<char*>(executable_name.c_str());
|
||||
}
|
||||
int argc = static_cast<int>(argv.size());
|
||||
benchmark::Initialize(&argc, ptrs.data());
|
||||
std::vector<std::string> remaining_argv;
|
||||
remaining_argv.reserve(argc);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
remaining_argv.emplace_back(ptrs[i]);
|
||||
}
|
||||
return remaining_argv;
|
||||
}
|
||||
|
||||
benchmark::Benchmark* RegisterBenchmark(const std::string& name,
|
||||
nb::callable f) {
|
||||
return benchmark::RegisterBenchmark(
|
||||
name, [f](benchmark::State& state) { f(&state); });
|
||||
}
|
||||
|
||||
NB_MODULE(_benchmark, m) {
|
||||
using benchmark::TimeUnit;
|
||||
nb::enum_<TimeUnit>(m, "TimeUnit")
|
||||
.value("kNanosecond", TimeUnit::kNanosecond)
|
||||
.value("kMicrosecond", TimeUnit::kMicrosecond)
|
||||
.value("kMillisecond", TimeUnit::kMillisecond)
|
||||
.value("kSecond", TimeUnit::kSecond)
|
||||
.export_values();
|
||||
|
||||
using benchmark::BigO;
|
||||
nb::enum_<BigO>(m, "BigO")
|
||||
.value("oNone", BigO::oNone)
|
||||
.value("o1", BigO::o1)
|
||||
.value("oN", BigO::oN)
|
||||
.value("oNSquared", BigO::oNSquared)
|
||||
.value("oNCubed", BigO::oNCubed)
|
||||
.value("oLogN", BigO::oLogN)
|
||||
.value("oNLogN", BigO::oNLogN)
|
||||
.value("oAuto", BigO::oAuto)
|
||||
.value("oLambda", BigO::oLambda)
|
||||
.export_values();
|
||||
|
||||
using benchmark::Benchmark;
|
||||
nb::class_<Benchmark>(m, "Benchmark")
|
||||
// For methods returning a pointer to the current object, reference
|
||||
// return policy is used to ask nanobind not to take ownership of the
|
||||
// returned object and avoid calling delete on it.
|
||||
// https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies
|
||||
//
|
||||
// For methods taking a const std::vector<...>&, a copy is created
|
||||
// because a it is bound to a Python list.
|
||||
// https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html
|
||||
.def("unit", &Benchmark::Unit, nb::rv_policy::reference)
|
||||
.def("arg", &Benchmark::Arg, nb::rv_policy::reference)
|
||||
.def("args", &Benchmark::Args, nb::rv_policy::reference)
|
||||
.def("range", &Benchmark::Range, nb::rv_policy::reference,
|
||||
nb::arg("start"), nb::arg("limit"))
|
||||
.def("dense_range", &Benchmark::DenseRange, nb::rv_policy::reference,
|
||||
nb::arg("start"), nb::arg("limit"), nb::arg("step") = 1)
|
||||
.def("ranges", &Benchmark::Ranges, nb::rv_policy::reference)
|
||||
.def("args_product", &Benchmark::ArgsProduct, nb::rv_policy::reference)
|
||||
.def("arg_name", &Benchmark::ArgName, nb::rv_policy::reference)
|
||||
.def("arg_names", &Benchmark::ArgNames, nb::rv_policy::reference)
|
||||
.def("range_pair", &Benchmark::RangePair, nb::rv_policy::reference,
|
||||
nb::arg("lo1"), nb::arg("hi1"), nb::arg("lo2"), nb::arg("hi2"))
|
||||
.def("range_multiplier", &Benchmark::RangeMultiplier,
|
||||
nb::rv_policy::reference)
|
||||
.def("min_time", &Benchmark::MinTime, nb::rv_policy::reference)
|
||||
.def("min_warmup_time", &Benchmark::MinWarmUpTime,
|
||||
nb::rv_policy::reference)
|
||||
.def("iterations", &Benchmark::Iterations, nb::rv_policy::reference)
|
||||
.def("repetitions", &Benchmark::Repetitions, nb::rv_policy::reference)
|
||||
.def("report_aggregates_only", &Benchmark::ReportAggregatesOnly,
|
||||
nb::rv_policy::reference, nb::arg("value") = true)
|
||||
.def("display_aggregates_only", &Benchmark::DisplayAggregatesOnly,
|
||||
nb::rv_policy::reference, nb::arg("value") = true)
|
||||
.def("measure_process_cpu_time", &Benchmark::MeasureProcessCPUTime,
|
||||
nb::rv_policy::reference)
|
||||
.def("use_real_time", &Benchmark::UseRealTime, nb::rv_policy::reference)
|
||||
.def("use_manual_time", &Benchmark::UseManualTime,
|
||||
nb::rv_policy::reference)
|
||||
.def(
|
||||
"complexity",
|
||||
(Benchmark * (Benchmark::*)(benchmark::BigO)) & Benchmark::Complexity,
|
||||
nb::rv_policy::reference, nb::arg("complexity") = benchmark::oAuto);
|
||||
|
||||
using benchmark::Counter;
|
||||
nb::class_<Counter> py_counter(m, "Counter");
|
||||
|
||||
nb::enum_<Counter::Flags>(py_counter, "Flags", nb::is_arithmetic(),
|
||||
nb::is_flag())
|
||||
.value("kDefaults", Counter::Flags::kDefaults)
|
||||
.value("kIsRate", Counter::Flags::kIsRate)
|
||||
.value("kAvgThreads", Counter::Flags::kAvgThreads)
|
||||
.value("kAvgThreadsRate", Counter::Flags::kAvgThreadsRate)
|
||||
.value("kIsIterationInvariant", Counter::Flags::kIsIterationInvariant)
|
||||
.value("kIsIterationInvariantRate",
|
||||
Counter::Flags::kIsIterationInvariantRate)
|
||||
.value("kAvgIterations", Counter::Flags::kAvgIterations)
|
||||
.value("kAvgIterationsRate", Counter::Flags::kAvgIterationsRate)
|
||||
.value("kInvert", Counter::Flags::kInvert)
|
||||
.export_values();
|
||||
|
||||
nb::enum_<Counter::OneK>(py_counter, "OneK")
|
||||
.value("kIs1000", Counter::OneK::kIs1000)
|
||||
.value("kIs1024", Counter::OneK::kIs1024)
|
||||
.export_values();
|
||||
|
||||
py_counter
|
||||
.def(nb::init<double, Counter::Flags, Counter::OneK>(),
|
||||
nb::arg("value") = 0., nb::arg("flags") = Counter::kDefaults,
|
||||
nb::arg("k") = Counter::kIs1000)
|
||||
.def("__init__",
|
||||
([](Counter* c, double value) { new (c) Counter(value); }))
|
||||
.def_rw("value", &Counter::value)
|
||||
.def_rw("flags", &Counter::flags)
|
||||
.def_rw("oneK", &Counter::oneK)
|
||||
.def(nb::init_implicit<double>());
|
||||
|
||||
nb::implicitly_convertible<nb::int_, Counter>();
|
||||
|
||||
nb::bind_map<benchmark::UserCounters>(m, "UserCounters");
|
||||
|
||||
using benchmark::State;
|
||||
nb::class_<State>(m, "State")
|
||||
.def("__bool__", &State::KeepRunning)
|
||||
.def_prop_ro("keep_running", &State::KeepRunning)
|
||||
.def("pause_timing", &State::PauseTiming)
|
||||
.def("resume_timing", &State::ResumeTiming)
|
||||
.def("skip_with_error", &State::SkipWithError)
|
||||
.def_prop_ro("error_occurred", &State::error_occurred)
|
||||
.def("set_iteration_time", &State::SetIterationTime)
|
||||
.def_prop_rw("bytes_processed", &State::bytes_processed,
|
||||
&State::SetBytesProcessed)
|
||||
.def_prop_rw("complexity_n", &State::complexity_length_n,
|
||||
&State::SetComplexityN)
|
||||
.def_prop_rw("items_processed", &State::items_processed,
|
||||
&State::SetItemsProcessed)
|
||||
.def("set_label", &State::SetLabel)
|
||||
.def(
|
||||
"range",
|
||||
[](const State& state, std::size_t pos = 0) -> int64_t {
|
||||
if (pos < state.range_size()) {
|
||||
return state.range(pos);
|
||||
}
|
||||
throw nb::index_error("pos is out of range");
|
||||
},
|
||||
nb::arg("pos") = 0)
|
||||
.def_prop_ro("iterations", &State::iterations)
|
||||
.def_prop_ro("name", &State::name)
|
||||
.def_rw("counters", &State::counters)
|
||||
.def_prop_ro("thread_index", &State::thread_index)
|
||||
.def_prop_ro("threads", &State::threads);
|
||||
|
||||
m.def("Initialize", Initialize);
|
||||
m.def("RegisterBenchmark", RegisterBenchmark, nb::rv_policy::reference);
|
||||
m.def("RunSpecifiedBenchmarks",
|
||||
[]() { benchmark::RunSpecifiedBenchmarks(); });
|
||||
m.def("ClearRegisteredBenchmarks", benchmark::ClearRegisteredBenchmarks);
|
||||
m.def("AddCustomContext", benchmark::AddCustomContext, nb::arg("key"),
|
||||
nb::arg("value"),
|
||||
"Add a key-value pair to output as part of the context stanza in the "
|
||||
"report.");
|
||||
};
|
||||
} // namespace
|
||||
@ -1,142 +0,0 @@
|
||||
# Copyright 2020 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Example of Python using C++ benchmark framework.
|
||||
|
||||
To run this example, you must first install the `google_benchmark` Python
|
||||
package.
|
||||
|
||||
To install using `setup.py`, download and extract the `google_benchmark` source.
|
||||
In the extracted directory, execute:
|
||||
python setup.py install
|
||||
"""
|
||||
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
|
||||
import google_benchmark as benchmark
|
||||
from google_benchmark import Counter
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def empty(state):
|
||||
while state:
|
||||
pass
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def sum_million(state):
|
||||
while state:
|
||||
sum(range(1_000_000))
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def pause_timing(state):
|
||||
"""Pause timing every iteration."""
|
||||
while state:
|
||||
# Construct a list of random ints every iteration without timing it
|
||||
state.pause_timing()
|
||||
random_list = [random.randint(0, 100) for _ in range(100)]
|
||||
state.resume_timing()
|
||||
# Time the in place sorting algorithm
|
||||
random_list.sort()
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def skipped(state):
|
||||
if True: # Test some predicate here.
|
||||
state.skip_with_error("some error")
|
||||
return # NOTE: You must explicitly return, or benchmark will continue.
|
||||
|
||||
# Benchmark code would be here.
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.use_manual_time()
|
||||
def manual_timing(state):
|
||||
while state:
|
||||
# Manually count Python CPU time
|
||||
start = time.perf_counter() # perf_counter_ns() in Python 3.7+
|
||||
# Something to benchmark
|
||||
time.sleep(0.01)
|
||||
end = time.perf_counter()
|
||||
state.set_iteration_time(end - start)
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def custom_counters(state):
|
||||
"""Collect custom metric using benchmark.Counter."""
|
||||
num_foo = 0.0
|
||||
while state:
|
||||
# Benchmark some code here
|
||||
# Collect some custom metric named foo
|
||||
num_foo += 0.13
|
||||
|
||||
# Automatic Counter from numbers.
|
||||
state.counters["foo"] = num_foo
|
||||
# Set a counter as a rate.
|
||||
state.counters["foo_rate"] = Counter(num_foo, Counter.kIsRate)
|
||||
# Set a counter as an inverse of rate.
|
||||
state.counters["foo_inv_rate"] = Counter(
|
||||
num_foo, Counter.kIsRate | Counter.kInvert
|
||||
)
|
||||
# Set a counter as a thread-average quantity.
|
||||
state.counters["foo_avg"] = Counter(num_foo, Counter.kAvgThreads)
|
||||
# There's also a combined flag:
|
||||
state.counters["foo_avg_rate"] = Counter(num_foo, Counter.kAvgThreadsRate)
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.measure_process_cpu_time()
|
||||
@benchmark.option.use_real_time()
|
||||
def with_options(state):
|
||||
while state:
|
||||
sum(range(1_000_000))
|
||||
|
||||
|
||||
@benchmark.register(name="sum_million_microseconds")
|
||||
@benchmark.option.unit(benchmark.kMicrosecond)
|
||||
def with_options2(state):
|
||||
while state:
|
||||
sum(range(1_000_000))
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.arg(100)
|
||||
@benchmark.option.arg(1000)
|
||||
def passing_argument(state):
|
||||
while state:
|
||||
sum(range(state.range(0)))
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.range(8, limit=8 << 10)
|
||||
def using_range(state):
|
||||
while state:
|
||||
sum(range(state.range(0)))
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.range_multiplier(2)
|
||||
@benchmark.option.range(1 << 10, 1 << 18)
|
||||
@benchmark.option.complexity(benchmark.oN)
|
||||
def computing_complexity(state):
|
||||
while state:
|
||||
sum(range(state.range(0)))
|
||||
state.complexity_n = state.range(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
benchmark.add_custom_context("python", sys.version)
|
||||
benchmark.main()
|
||||
@ -1,78 +0,0 @@
|
||||
# - Adds a compiler flag if it is supported by the compiler
|
||||
#
|
||||
# This function checks that the supplied compiler flag is supported and then
|
||||
# adds it to the corresponding compiler flags
|
||||
#
|
||||
# add_cxx_compiler_flag(<FLAG> [<VARIANT>])
|
||||
#
|
||||
# - Example
|
||||
#
|
||||
# include(AddCXXCompilerFlag)
|
||||
# add_cxx_compiler_flag(-Wall)
|
||||
# add_cxx_compiler_flag(-no-strict-aliasing RELEASE)
|
||||
# Requires CMake 2.6+
|
||||
|
||||
if(__add_cxx_compiler_flag)
|
||||
return()
|
||||
endif()
|
||||
set(__add_cxx_compiler_flag INCLUDED)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
function(mangle_compiler_flag FLAG OUTPUT)
|
||||
string(TOUPPER "HAVE_CXX_FLAG_${FLAG}" SANITIZED_FLAG)
|
||||
string(REPLACE "+" "X" SANITIZED_FLAG ${SANITIZED_FLAG})
|
||||
string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG})
|
||||
string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG})
|
||||
set(${OUTPUT} "${SANITIZED_FLAG}" PARENT_SCOPE)
|
||||
endfunction(mangle_compiler_flag)
|
||||
|
||||
function(add_cxx_compiler_flag FLAG)
|
||||
mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}")
|
||||
check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
|
||||
set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
|
||||
if(${MANGLED_FLAG})
|
||||
if(ARGC GREATER 1)
|
||||
set(VARIANT ${ARGV1})
|
||||
string(TOUPPER "_${VARIANT}" VARIANT)
|
||||
else()
|
||||
set(VARIANT "")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${BENCHMARK_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(add_required_cxx_compiler_flag FLAG)
|
||||
mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}")
|
||||
check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
|
||||
set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
|
||||
if(${MANGLED_FLAG})
|
||||
if(ARGC GREATER 1)
|
||||
set(VARIANT ${ARGV1})
|
||||
string(TOUPPER "_${VARIANT}" VARIANT)
|
||||
else()
|
||||
set(VARIANT "")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}" PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR "Required flag '${FLAG}' is not supported by the compiler")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(check_cxx_warning_flag FLAG)
|
||||
mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
# Add -Werror to ensure the compiler generates an error if the warning flag
|
||||
# doesn't exist.
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror ${FLAG}")
|
||||
check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
|
||||
set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
|
||||
endfunction()
|
||||
85
thirdparty/benchmark/cmake/CXXFeatureCheck.cmake
vendored
85
thirdparty/benchmark/cmake/CXXFeatureCheck.cmake
vendored
@ -1,85 +0,0 @@
|
||||
# - Compile and run code to check for C++ features
|
||||
#
|
||||
# This functions compiles a source file under the `cmake` folder
|
||||
# and adds the corresponding `HAVE_[FILENAME]` flag to the CMake
|
||||
# environment
|
||||
#
|
||||
# cxx_feature_check(<FLAG> [<VARIANT>])
|
||||
#
|
||||
# - Example
|
||||
#
|
||||
# include(CXXFeatureCheck)
|
||||
# cxx_feature_check(STD_REGEX)
|
||||
# Requires CMake 2.8.12+
|
||||
|
||||
if(__cxx_feature_check)
|
||||
return()
|
||||
endif()
|
||||
set(__cxx_feature_check INCLUDED)
|
||||
|
||||
option(CXXFEATURECHECK_DEBUG OFF)
|
||||
|
||||
function(cxx_feature_check FILE)
|
||||
string(TOLOWER ${FILE} FILE)
|
||||
string(TOUPPER ${FILE} VAR)
|
||||
string(TOUPPER "HAVE_${VAR}" FEATURE)
|
||||
if (DEFINED HAVE_${VAR})
|
||||
if(HAVE_${VAR})
|
||||
add_definitions(-DHAVE_${VAR})
|
||||
endif()
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(FEATURE_CHECK_CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
|
||||
if (ARGC GREATER 1)
|
||||
message(STATUS "Enabling additional flags: ${ARGV1}")
|
||||
list(APPEND FEATURE_CHECK_CMAKE_FLAGS ${ARGV1})
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED COMPILE_${FEATURE})
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
message(STATUS "Cross-compiling to test ${FEATURE}")
|
||||
try_compile(COMPILE_${FEATURE}
|
||||
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CMAKE_FLAGS ${FEATURE_CHECK_CMAKE_FLAGS}
|
||||
LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}
|
||||
OUTPUT_VARIABLE COMPILE_OUTPUT_VAR)
|
||||
if(COMPILE_${FEATURE})
|
||||
message(WARNING
|
||||
"If you see build failures due to cross compilation, try setting HAVE_${VAR} to 0")
|
||||
set(RUN_${FEATURE} 0 CACHE INTERNAL "")
|
||||
else()
|
||||
set(RUN_${FEATURE} 1 CACHE INTERNAL "")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Compiling and running to test ${FEATURE}")
|
||||
try_run(RUN_${FEATURE} COMPILE_${FEATURE}
|
||||
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CMAKE_FLAGS ${FEATURE_CHECK_CMAKE_FLAGS}
|
||||
LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}
|
||||
COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT_VAR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(COMPILE_${FEATURE})
|
||||
if(DEFINED RUN_${FEATURE} AND RUN_${FEATURE} EQUAL 0)
|
||||
message(STATUS "Performing Test ${FEATURE} -- success")
|
||||
set(HAVE_${VAR} 1 CACHE INTERNAL "")
|
||||
add_definitions(-DHAVE_${VAR})
|
||||
else()
|
||||
message(STATUS "Performing Test ${FEATURE} -- compiled but failed to run")
|
||||
set(HAVE_${VAR} 0 CACHE INTERNAL "")
|
||||
endif()
|
||||
else()
|
||||
if(CXXFEATURECHECK_DEBUG)
|
||||
message(STATUS "Performing Test ${FEATURE} -- failed to compile: ${COMPILE_OUTPUT_VAR}")
|
||||
else()
|
||||
message(STATUS "Performing Test ${FEATURE} -- failed to compile")
|
||||
endif()
|
||||
set(HAVE_${VAR} 0 CACHE INTERNAL "")
|
||||
endif()
|
||||
endfunction()
|
||||
12
thirdparty/benchmark/cmake/Config.cmake.in
vendored
12
thirdparty/benchmark/cmake/Config.cmake.in
vendored
@ -1,12 +0,0 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include (CMakeFindDependencyMacro)
|
||||
|
||||
find_dependency (Threads)
|
||||
|
||||
if (@BENCHMARK_ENABLE_LIBPFM@)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
find_dependency (PFM)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
|
||||
36
thirdparty/benchmark/cmake/GetGitVersion.cmake
vendored
36
thirdparty/benchmark/cmake/GetGitVersion.cmake
vendored
@ -1,36 +0,0 @@
|
||||
# - Returns a version string from Git tags
|
||||
#
|
||||
# This function inspects the annotated git tags for the project and returns a string
|
||||
# into a CMake variable
|
||||
#
|
||||
# get_git_version(<var>)
|
||||
#
|
||||
# - Example
|
||||
#
|
||||
# include(GetGitVersion)
|
||||
# get_git_version(GIT_VERSION)
|
||||
#
|
||||
# Requires CMake 2.8.11+
|
||||
find_package(Git)
|
||||
|
||||
if(__get_git_version)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_version INCLUDED)
|
||||
|
||||
function(get_git_version var)
|
||||
if(GIT_EXECUTABLE)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8 --dirty
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
RESULT_VARIABLE status
|
||||
OUTPUT_VARIABLE GIT_VERSION
|
||||
ERROR_QUIET)
|
||||
if(status)
|
||||
set(GIT_VERSION "v0.0.0")
|
||||
endif()
|
||||
else()
|
||||
set(GIT_VERSION "v0.0.0")
|
||||
endif()
|
||||
|
||||
set(${var} ${GIT_VERSION} PARENT_SCOPE)
|
||||
endfunction()
|
||||
58
thirdparty/benchmark/cmake/GoogleTest.cmake
vendored
58
thirdparty/benchmark/cmake/GoogleTest.cmake
vendored
@ -1,58 +0,0 @@
|
||||
# Download and unpack googletest at configure time
|
||||
set(GOOGLETEST_PREFIX "${benchmark_BINARY_DIR}/third_party/googletest")
|
||||
configure_file(${benchmark_SOURCE_DIR}/cmake/GoogleTest.cmake.in ${GOOGLETEST_PREFIX}/CMakeLists.txt @ONLY)
|
||||
|
||||
set(GOOGLETEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/googletest" CACHE PATH "") # Mind the quotes
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}"
|
||||
-DALLOW_DOWNLOADING_GOOGLETEST=${BENCHMARK_DOWNLOAD_DEPENDENCIES} -DGOOGLETEST_PATH:PATH=${GOOGLETEST_PATH} .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${GOOGLETEST_PREFIX}
|
||||
)
|
||||
|
||||
if(result)
|
||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${GOOGLETEST_PREFIX}
|
||||
)
|
||||
|
||||
if(result)
|
||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
# Prevent overriding the parent project's compiler/linker
|
||||
# settings on Windows
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
include(${GOOGLETEST_PREFIX}/googletest-paths.cmake)
|
||||
|
||||
# Add googletest directly to our build. This defines
|
||||
# the gtest and gtest_main targets.
|
||||
add_subdirectory(${GOOGLETEST_SOURCE_DIR}
|
||||
${GOOGLETEST_BINARY_DIR}
|
||||
EXCLUDE_FROM_ALL)
|
||||
|
||||
# googletest doesn't seem to want to stay build warning clean so let's not hurt ourselves.
|
||||
if (MSVC)
|
||||
target_compile_options(gtest PRIVATE "/wd4244" "/wd4722")
|
||||
target_compile_options(gtest_main PRIVATE "/wd4244" "/wd4722")
|
||||
target_compile_options(gmock PRIVATE "/wd4244" "/wd4722")
|
||||
target_compile_options(gmock_main PRIVATE "/wd4244" "/wd4722")
|
||||
else()
|
||||
target_compile_options(gtest PRIVATE "-w")
|
||||
target_compile_options(gtest_main PRIVATE "-w")
|
||||
target_compile_options(gmock PRIVATE "-w")
|
||||
target_compile_options(gmock_main PRIVATE "-w")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED GTEST_COMPILE_COMMANDS)
|
||||
set(GTEST_COMPILE_COMMANDS ON)
|
||||
endif()
|
||||
|
||||
set_target_properties(gtest PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gtest,INTERFACE_INCLUDE_DIRECTORIES> EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
|
||||
set_target_properties(gtest_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gtest_main,INTERFACE_INCLUDE_DIRECTORIES> EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
|
||||
set_target_properties(gmock PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gmock,INTERFACE_INCLUDE_DIRECTORIES> EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
|
||||
set_target_properties(gmock_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gmock_main,INTERFACE_INCLUDE_DIRECTORIES> EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
|
||||
60
thirdparty/benchmark/cmake/GoogleTest.cmake.in
vendored
60
thirdparty/benchmark/cmake/GoogleTest.cmake.in
vendored
@ -1,60 +0,0 @@
|
||||
cmake_minimum_required (VERSION 3.13...3.22)
|
||||
|
||||
project(googletest-download NONE)
|
||||
|
||||
# Enable ExternalProject CMake module
|
||||
include(ExternalProject)
|
||||
|
||||
option(ALLOW_DOWNLOADING_GOOGLETEST "If googletest src tree is not found in location specified by GOOGLETEST_PATH, do fetch the archive from internet" OFF)
|
||||
set(GOOGLETEST_PATH "/usr/src/googletest" CACHE PATH
|
||||
"Path to the googletest root tree. Should contain googletest and googlemock subdirs. And CMakeLists.txt in root, and in both of these subdirs")
|
||||
|
||||
# Download and install GoogleTest
|
||||
|
||||
message(STATUS "Looking for Google Test sources")
|
||||
message(STATUS "Looking for Google Test sources in ${GOOGLETEST_PATH}")
|
||||
if(EXISTS "${GOOGLETEST_PATH}" AND IS_DIRECTORY "${GOOGLETEST_PATH}" AND EXISTS "${GOOGLETEST_PATH}/CMakeLists.txt" AND
|
||||
EXISTS "${GOOGLETEST_PATH}/googletest" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googletest" AND EXISTS "${GOOGLETEST_PATH}/googletest/CMakeLists.txt" AND
|
||||
EXISTS "${GOOGLETEST_PATH}/googlemock" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googlemock" AND EXISTS "${GOOGLETEST_PATH}/googlemock/CMakeLists.txt")
|
||||
message(STATUS "Found Google Test in ${GOOGLETEST_PATH}")
|
||||
|
||||
ExternalProject_Add(
|
||||
googletest
|
||||
PREFIX "${CMAKE_BINARY_DIR}"
|
||||
DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/download"
|
||||
SOURCE_DIR "${GOOGLETEST_PATH}" # use existing src dir.
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
else()
|
||||
if(NOT ALLOW_DOWNLOADING_GOOGLETEST)
|
||||
message(SEND_ERROR "Did not find Google Test sources! Either pass correct path in GOOGLETEST_PATH, or enable BENCHMARK_DOWNLOAD_DEPENDENCIES, or disable BENCHMARK_USE_BUNDLED_GTEST, or disable BENCHMARK_ENABLE_GTEST_TESTS / BENCHMARK_ENABLE_TESTING.")
|
||||
return()
|
||||
else()
|
||||
message(STATUS "Did not find Google Test sources! Fetching from web...")
|
||||
ExternalProject_Add(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG "v1.15.2"
|
||||
GIT_SHALLOW "ON"
|
||||
PREFIX "${CMAKE_BINARY_DIR}"
|
||||
STAMP_DIR "${CMAKE_BINARY_DIR}/stamp"
|
||||
DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/download"
|
||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/src"
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ExternalProject_Get_Property(googletest SOURCE_DIR BINARY_DIR)
|
||||
file(WRITE googletest-paths.cmake
|
||||
"set(GOOGLETEST_SOURCE_DIR \"${SOURCE_DIR}\")
|
||||
set(GOOGLETEST_BINARY_DIR \"${BINARY_DIR}\")
|
||||
")
|
||||
@ -1,16 +0,0 @@
|
||||
include(FeatureSummary)
|
||||
|
||||
find_program(LLVMAR_EXECUTABLE
|
||||
NAMES llvm-ar
|
||||
DOC "The llvm-ar executable"
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LLVMAr
|
||||
DEFAULT_MSG
|
||||
LLVMAR_EXECUTABLE)
|
||||
|
||||
SET_PACKAGE_PROPERTIES(LLVMAr PROPERTIES
|
||||
URL https://llvm.org/docs/CommandGuide/llvm-ar.html
|
||||
DESCRIPTION "create, modify, and extract from archives"
|
||||
)
|
||||
@ -1,16 +0,0 @@
|
||||
include(FeatureSummary)
|
||||
|
||||
find_program(LLVMNM_EXECUTABLE
|
||||
NAMES llvm-nm
|
||||
DOC "The llvm-nm executable"
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LLVMNm
|
||||
DEFAULT_MSG
|
||||
LLVMNM_EXECUTABLE)
|
||||
|
||||
SET_PACKAGE_PROPERTIES(LLVMNm PROPERTIES
|
||||
URL https://llvm.org/docs/CommandGuide/llvm-nm.html
|
||||
DESCRIPTION "list LLVM bitcode and object file’s symbol table"
|
||||
)
|
||||
@ -1,15 +0,0 @@
|
||||
include(FeatureSummary)
|
||||
|
||||
find_program(LLVMRANLIB_EXECUTABLE
|
||||
NAMES llvm-ranlib
|
||||
DOC "The llvm-ranlib executable"
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LLVMRanLib
|
||||
DEFAULT_MSG
|
||||
LLVMRANLIB_EXECUTABLE)
|
||||
|
||||
SET_PACKAGE_PROPERTIES(LLVMRanLib PROPERTIES
|
||||
DESCRIPTION "generate index for LLVM archive"
|
||||
)
|
||||
28
thirdparty/benchmark/cmake/Modules/FindPFM.cmake
vendored
28
thirdparty/benchmark/cmake/Modules/FindPFM.cmake
vendored
@ -1,28 +0,0 @@
|
||||
# If successful, the following variables will be defined:
|
||||
# PFM_FOUND.
|
||||
# PFM_LIBRARIES
|
||||
# PFM_INCLUDE_DIRS
|
||||
# the following target will be defined:
|
||||
# PFM::libpfm
|
||||
|
||||
include(FeatureSummary)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
set_package_properties(PFM PROPERTIES
|
||||
URL http://perfmon2.sourceforge.net/
|
||||
DESCRIPTION "A helper library to develop monitoring tools"
|
||||
PURPOSE "Used to program specific performance monitoring events")
|
||||
|
||||
find_library(PFM_LIBRARY NAMES pfm)
|
||||
find_path(PFM_INCLUDE_DIR NAMES perfmon/pfmlib.h)
|
||||
|
||||
find_package_handle_standard_args(PFM REQUIRED_VARS PFM_LIBRARY PFM_INCLUDE_DIR)
|
||||
|
||||
if (PFM_FOUND AND NOT TARGET PFM::libpfm)
|
||||
add_library(PFM::libpfm UNKNOWN IMPORTED)
|
||||
set_target_properties(PFM::libpfm PROPERTIES
|
||||
IMPORTED_LOCATION "${PFM_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${PFM_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(PFM_LIBRARY PFM_INCLUDE_DIR)
|
||||
12
thirdparty/benchmark/cmake/benchmark.pc.in
vendored
12
thirdparty/benchmark/cmake/benchmark.pc.in
vendored
@ -1,12 +0,0 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=@BENCHMARK_PKG_CONFIG_LIBDIR@
|
||||
includedir=@BENCHMARK_PKG_CONFIG_INCLUDEDIR@
|
||||
|
||||
Name: @PROJECT_NAME@
|
||||
Description: Google microbenchmark framework
|
||||
Version: @NORMALIZED_VERSION@
|
||||
|
||||
Libs: -L${libdir} -lbenchmark
|
||||
Libs.private: -lpthread @BENCHMARK_PRIVATE_LINK_LIBRARIES@
|
||||
Cflags: -I${includedir}
|
||||
@ -1,9 +0,0 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=@BENCHMARK_PKG_CONFIG_LIBDIR@
|
||||
|
||||
Name: @PROJECT_NAME@
|
||||
Description: Google microbenchmark framework (with main() function)
|
||||
Version: @NORMALIZED_VERSION@
|
||||
Requires: benchmark
|
||||
Libs: -L${libdir} -lbenchmark_main
|
||||
12
thirdparty/benchmark/cmake/gnu_posix_regex.cpp
vendored
12
thirdparty/benchmark/cmake/gnu_posix_regex.cpp
vendored
@ -1,12 +0,0 @@
|
||||
#include <gnuregex.h>
|
||||
#include <string>
|
||||
int main() {
|
||||
std::string str = "test0159";
|
||||
regex_t re;
|
||||
int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB);
|
||||
if (ec != 0) {
|
||||
return ec;
|
||||
}
|
||||
return regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
find_package(LLVMAr REQUIRED)
|
||||
set(CMAKE_AR "${LLVMAR_EXECUTABLE}" CACHE FILEPATH "" FORCE)
|
||||
|
||||
find_package(LLVMNm REQUIRED)
|
||||
set(CMAKE_NM "${LLVMNM_EXECUTABLE}" CACHE FILEPATH "" FORCE)
|
||||
|
||||
find_package(LLVMRanLib REQUIRED)
|
||||
set(CMAKE_RANLIB "${LLVMRANLIB_EXECUTABLE}" CACHE FILEPATH "" FORCE)
|
||||
14
thirdparty/benchmark/cmake/posix_regex.cpp
vendored
14
thirdparty/benchmark/cmake/posix_regex.cpp
vendored
@ -1,14 +0,0 @@
|
||||
#include <regex.h>
|
||||
#include <string>
|
||||
int main() {
|
||||
std::string str = "test0159";
|
||||
regex_t re;
|
||||
int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB);
|
||||
if (ec != 0) {
|
||||
return ec;
|
||||
}
|
||||
int ret = regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0;
|
||||
regfree(&re);
|
||||
return ret;
|
||||
}
|
||||
|
||||
19
thirdparty/benchmark/cmake/pthread_affinity.cpp
vendored
19
thirdparty/benchmark/cmake/pthread_affinity.cpp
vendored
@ -1,19 +0,0 @@
|
||||
#include <pthread.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
int main() {
|
||||
cpu_set_t set;
|
||||
CPU_ZERO(&set);
|
||||
for (int i = 0; i < CPU_SETSIZE; ++i) {
|
||||
CPU_SET(i, &set);
|
||||
CPU_CLR(i, &set);
|
||||
}
|
||||
pthread_t self = pthread_self();
|
||||
int ret;
|
||||
ret = pthread_getaffinity_np(self, sizeof(set), &set);
|
||||
if (ret != 0) return ret;
|
||||
ret = pthread_setaffinity_np(self, sizeof(set), &set);
|
||||
if (ret != 0) return ret;
|
||||
return 0;
|
||||
}
|
||||
3
thirdparty/benchmark/cmake/split_list.cmake
vendored
3
thirdparty/benchmark/cmake/split_list.cmake
vendored
@ -1,3 +0,0 @@
|
||||
macro(split_list listname)
|
||||
string(REPLACE ";" " " ${listname} "${${listname}}")
|
||||
endmacro()
|
||||
10
thirdparty/benchmark/cmake/std_regex.cpp
vendored
10
thirdparty/benchmark/cmake/std_regex.cpp
vendored
@ -1,10 +0,0 @@
|
||||
#include <regex>
|
||||
#include <string>
|
||||
int main() {
|
||||
const std::string str = "test0159";
|
||||
std::regex re;
|
||||
re = std::regex("^[a-z]+[0-9]+$",
|
||||
std::regex_constants::extended | std::regex_constants::nosubs);
|
||||
return std::regex_search(str, re) ? 0 : -1;
|
||||
}
|
||||
|
||||
7
thirdparty/benchmark/cmake/steady_clock.cpp
vendored
7
thirdparty/benchmark/cmake/steady_clock.cpp
vendored
@ -1,7 +0,0 @@
|
||||
#include <chrono>
|
||||
|
||||
int main() {
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
Clock::time_point tp = Clock::now();
|
||||
((void)tp);
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
#if defined(__clang__)
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE_(x) __attribute__((x))
|
||||
#else
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE_(x)
|
||||
#endif
|
||||
|
||||
#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(capability(x))
|
||||
#define ACQUIRE() THREAD_ANNOTATION_ATTRIBUTE_(acquire_capability())
|
||||
#define RELEASE() THREAD_ANNOTATION_ATTRIBUTE_(release_capability())
|
||||
|
||||
class CAPABILITY("mutex") Mutex {
|
||||
public:
|
||||
void lock() ACQUIRE();
|
||||
void unlock() RELEASE();
|
||||
};
|
||||
|
||||
void Mutex::lock() ACQUIRE() {}
|
||||
void Mutex::unlock() RELEASE() {}
|
||||
|
||||
int main() {
|
||||
Mutex m;
|
||||
m.lock();
|
||||
m.unlock();
|
||||
return 0;
|
||||
}
|
||||
149
thirdparty/benchmark/docs/AssemblyTests.md
vendored
149
thirdparty/benchmark/docs/AssemblyTests.md
vendored
@ -1,149 +0,0 @@
|
||||
# Assembly Tests
|
||||
|
||||
The Benchmark library provides a number of functions whose primary
|
||||
purpose in to affect assembly generation, including `DoNotOptimize`
|
||||
and `ClobberMemory`. In addition there are other functions,
|
||||
such as `KeepRunning`, for which generating good assembly is paramount.
|
||||
|
||||
For these functions it's important to have tests that verify the
|
||||
correctness and quality of the implementation. This requires testing
|
||||
the code generated by the compiler.
|
||||
|
||||
This document describes how the Benchmark library tests compiler output,
|
||||
as well as how to properly write new tests.
|
||||
|
||||
|
||||
## Anatomy of a Test
|
||||
|
||||
Writing a test has two steps:
|
||||
|
||||
* Write the code you want to generate assembly for.
|
||||
* Add `// CHECK` lines to match against the verified assembly.
|
||||
|
||||
Example:
|
||||
```c++
|
||||
|
||||
// CHECK-LABEL: test_add:
|
||||
extern "C" int test_add() {
|
||||
extern int ExternInt;
|
||||
return ExternInt + 1;
|
||||
|
||||
// CHECK: movl ExternInt(%rip), %eax
|
||||
// CHECK: addl %eax
|
||||
// CHECK: ret
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### LLVM Filecheck
|
||||
|
||||
[LLVM's Filecheck](https://llvm.org/docs/CommandGuide/FileCheck.html)
|
||||
is used to test the generated assembly against the `// CHECK` lines
|
||||
specified in the tests source file. Please see the documentation
|
||||
linked above for information on how to write `CHECK` directives.
|
||||
|
||||
#### Tips and Tricks:
|
||||
|
||||
* Tests should match the minimal amount of output required to establish
|
||||
correctness. `CHECK` directives don't have to match on the exact next line
|
||||
after the previous match, so tests should omit checks for unimportant
|
||||
bits of assembly. ([`CHECK-NEXT`](https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-next-directive)
|
||||
can be used to ensure a match occurs exactly after the previous match).
|
||||
|
||||
* The tests are compiled with `-O3 -g0`. So we're only testing the
|
||||
optimized output.
|
||||
|
||||
* The assembly output is further cleaned up using `tools/strip_asm.py`.
|
||||
This removes comments, assembler directives, and unused labels before
|
||||
the test is run.
|
||||
|
||||
* The generated and stripped assembly file for a test is output under
|
||||
`<build-directory>/test/<test-name>.s`
|
||||
|
||||
* Filecheck supports using [`CHECK` prefixes](https://llvm.org/docs/CommandGuide/FileCheck.html#cmdoption-check-prefixes)
|
||||
to specify lines that should only match in certain situations.
|
||||
The Benchmark tests use `CHECK-CLANG` and `CHECK-GNU` for lines that
|
||||
are only expected to match Clang or GCC's output respectively. Normal
|
||||
`CHECK` lines match against all compilers. (Note: `CHECK-NOT` and
|
||||
`CHECK-LABEL` are NOT prefixes. They are versions of non-prefixed
|
||||
`CHECK` lines)
|
||||
|
||||
* Use `extern "C"` to disable name mangling for specific functions. This
|
||||
makes them easier to name in the `CHECK` lines.
|
||||
|
||||
|
||||
## Problems Writing Portable Tests
|
||||
|
||||
Writing tests which check the code generated by a compiler are
|
||||
inherently non-portable. Different compilers and even different compiler
|
||||
versions may generate entirely different code. The Benchmark tests
|
||||
must tolerate this.
|
||||
|
||||
LLVM Filecheck provides a number of mechanisms to help write
|
||||
"more portable" tests; including [matching using regular expressions](https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-pattern-matching-syntax),
|
||||
allowing the creation of [named variables](https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-variables)
|
||||
for later matching, and [checking non-sequential matches](https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-dag-directive).
|
||||
|
||||
#### Capturing Variables
|
||||
|
||||
For example, say GCC stores a variable in a register but Clang stores
|
||||
it in memory. To write a test that tolerates both cases we "capture"
|
||||
the destination of the store, and then use the captured expression
|
||||
to write the remainder of the test.
|
||||
|
||||
```c++
|
||||
// CHECK-LABEL: test_div_no_op_into_shr:
|
||||
extern "C" void test_div_no_op_into_shr(int value) {
|
||||
int divisor = 2;
|
||||
benchmark::DoNotOptimize(divisor); // hide the value from the optimizer
|
||||
return value / divisor;
|
||||
|
||||
// CHECK: movl $2, [[DEST:.*]]
|
||||
// CHECK: idivl [[DEST]]
|
||||
// CHECK: ret
|
||||
}
|
||||
```
|
||||
|
||||
#### Using Regular Expressions to Match Differing Output
|
||||
|
||||
Often tests require testing assembly lines which may subtly differ
|
||||
between compilers or compiler versions. A common example of this
|
||||
is matching stack frame addresses. In this case regular expressions
|
||||
can be used to match the differing bits of output. For example:
|
||||
|
||||
<!-- {% raw %} -->
|
||||
```c++
|
||||
int ExternInt;
|
||||
struct Point { int x, y, z; };
|
||||
|
||||
// CHECK-LABEL: test_store_point:
|
||||
extern "C" void test_store_point() {
|
||||
Point p{ExternInt, ExternInt, ExternInt};
|
||||
benchmark::DoNotOptimize(p);
|
||||
|
||||
// CHECK: movl ExternInt(%rip), %eax
|
||||
// CHECK: movl %eax, -{{[0-9]+}}(%rsp)
|
||||
// CHECK: movl %eax, -{{[0-9]+}}(%rsp)
|
||||
// CHECK: movl %eax, -{{[0-9]+}}(%rsp)
|
||||
// CHECK: ret
|
||||
}
|
||||
```
|
||||
<!-- {% endraw %} -->
|
||||
|
||||
## Current Requirements and Limitations
|
||||
|
||||
The tests require Filecheck to be installed along the `PATH` of the
|
||||
build machine. Otherwise the tests will be disabled.
|
||||
|
||||
Additionally, as mentioned in the previous section, codegen tests are
|
||||
inherently non-portable. Currently the tests are limited to:
|
||||
|
||||
* x86_64 targets.
|
||||
* Compiled with GCC or Clang
|
||||
|
||||
Further work could be done, at least on a limited basis, to extend the
|
||||
tests to other architectures and compilers (using `CHECK` prefixes).
|
||||
|
||||
Furthermore, the tests fail for builds which specify additional flags
|
||||
that modify code generation, including `--coverage` or `-fsanitize=`.
|
||||
|
||||
3
thirdparty/benchmark/docs/_config.yml
vendored
3
thirdparty/benchmark/docs/_config.yml
vendored
@ -1,3 +0,0 @@
|
||||
theme: jekyll-theme-minimal
|
||||
logo: /assets/images/icon_black.png
|
||||
show_downloads: true
|
||||
BIN
thirdparty/benchmark/docs/assets/images/icon.png
vendored
BIN
thirdparty/benchmark/docs/assets/images/icon.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
BIN
thirdparty/benchmark/docs/assets/images/icon.xcf
vendored
BIN
thirdparty/benchmark/docs/assets/images/icon.xcf
vendored
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
19
thirdparty/benchmark/docs/dependencies.md
vendored
19
thirdparty/benchmark/docs/dependencies.md
vendored
@ -1,19 +0,0 @@
|
||||
# Build tool dependency policy
|
||||
|
||||
We follow the [Foundational C++ support policy](https://opensource.google/documentation/policies/cplusplus-support) for our build tools. In
|
||||
particular the ["Build Systems" section](https://opensource.google/documentation/policies/cplusplus-support#build-systems).
|
||||
|
||||
## CMake
|
||||
|
||||
The current supported version is CMake 3.13 as of 2024-10-24. Most modern
|
||||
distributions include newer versions, for example:
|
||||
|
||||
* Ubuntu 20.04 provides CMake 3.16.3
|
||||
* Debian 11.4 provides CMake 3.18.4
|
||||
* Ubuntu 22.04 provides CMake 3.22.1
|
||||
|
||||
## Python
|
||||
|
||||
The Python bindings require Python 3.10+ as of v1.9.0 (2024-08-16) for installation from PyPI.
|
||||
Building from source for older versions probably still works, though. See the [user guide](python_bindings.md) for details on how to build from source.
|
||||
The minimum theoretically supported version is Python 3.8, since the used bindings generator (nanobind) only supports Python 3.8+.
|
||||
12
thirdparty/benchmark/docs/index.md
vendored
12
thirdparty/benchmark/docs/index.md
vendored
@ -1,12 +0,0 @@
|
||||
# Benchmark
|
||||
|
||||
* [Assembly Tests](AssemblyTests.md)
|
||||
* [Dependencies](dependencies.md)
|
||||
* [Perf Counters](perf_counters.md)
|
||||
* [Platform Specific Build Instructions](platform_specific_build_instructions.md)
|
||||
* [Python Bindings](python_bindings.md)
|
||||
* [Random Interleaving](random_interleaving.md)
|
||||
* [Reducing Variance](reducing_variance.md)
|
||||
* [Releasing](releasing.md)
|
||||
* [Tools](tools.md)
|
||||
* [User Guide](user_guide.md)
|
||||
35
thirdparty/benchmark/docs/perf_counters.md
vendored
35
thirdparty/benchmark/docs/perf_counters.md
vendored
@ -1,35 +0,0 @@
|
||||
<a name="perf-counters" />
|
||||
|
||||
# User-Requested Performance Counters
|
||||
|
||||
When running benchmarks, the user may choose to request collection of
|
||||
performance counters. This may be useful in investigation scenarios - narrowing
|
||||
down the cause of a regression; or verifying that the underlying cause of a
|
||||
performance improvement matches expectations.
|
||||
|
||||
This feature is available if:
|
||||
|
||||
* The benchmark is run on an architecture featuring a Performance Monitoring
|
||||
Unit (PMU),
|
||||
* The benchmark is compiled with support for collecting counters. Currently,
|
||||
this requires [libpfm](http://perfmon2.sourceforge.net/), which is built as a
|
||||
dependency via Bazel.
|
||||
|
||||
The feature does not require modifying benchmark code. Counter collection is
|
||||
handled at the boundaries where timer collection is also handled.
|
||||
|
||||
To opt-in:
|
||||
* If using a Bazel build, add `--define pfm=1` to your build flags
|
||||
* If using CMake:
|
||||
* Install `libpfm4-dev`, e.g. `apt-get install libpfm4-dev`.
|
||||
* Enable the CMake flag `BENCHMARK_ENABLE_LIBPFM` in `CMakeLists.txt`.
|
||||
|
||||
To use, pass a comma-separated list of counter names through the
|
||||
`--benchmark_perf_counters` flag. The names are decoded through libpfm - meaning,
|
||||
they are platform specific, but some (e.g. `CYCLES` or `INSTRUCTIONS`) are
|
||||
mapped by libpfm to platform-specifics - see libpfm
|
||||
[documentation](http://perfmon2.sourceforge.net/docs.html) for more details.
|
||||
|
||||
The counter values are reported back through the [User Counters](../README.md#custom-counters)
|
||||
mechanism, meaning, they are available in all the formats (e.g. JSON) supported
|
||||
by User Counters.
|
||||
@ -1,52 +0,0 @@
|
||||
# Platform Specific Build Instructions
|
||||
|
||||
## Building with GCC
|
||||
|
||||
When the library is built using GCC it is necessary to link with the pthread
|
||||
library due to how GCC implements `std::thread`. Failing to link to pthread will
|
||||
lead to runtime exceptions (unless you're using libc++), not linker errors. See
|
||||
[issue #67](https://github.com/google/benchmark/issues/67) for more details. You
|
||||
can link to pthread by adding `-pthread` to your linker command. Note, you can
|
||||
also use `-lpthread`, but there are potential issues with ordering of command
|
||||
line parameters if you use that.
|
||||
|
||||
On QNX, the pthread library is part of libc and usually included automatically
|
||||
(see
|
||||
[`pthread_create()`](https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.lib_ref/topic/p/pthread_create.html)).
|
||||
There's no separate pthread library to link.
|
||||
|
||||
## Building with Visual Studio 2015, 2017 or 2022
|
||||
|
||||
The `shlwapi` library (`-lshlwapi`) is required to support a call to `CPUInfo` which reads the registry. Either add `shlwapi.lib` under `[ Configuration Properties > Linker > Input ]`, or use the following:
|
||||
|
||||
```
|
||||
// Alternatively, can add libraries using linker options.
|
||||
|
||||
// First, Add the path to the generated library files (directory containing the `benchmark.lib`) in `[Configuration Properties > Linker > General > Additional Library Directories]`. Then do the following:
|
||||
#ifdef _WIN32
|
||||
#pragma comment ( lib, "Shlwapi.lib" )
|
||||
#ifdef _DEBUG
|
||||
#pragma comment ( lib, "benchmark.lib" )
|
||||
#else
|
||||
#pragma comment ( lib, "benchmark.lib" )
|
||||
#endif
|
||||
#endif
|
||||
```
|
||||
|
||||
When using the static library, make sure to add `BENCHMARK_STATIC_DEFINE` under `[Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions]`
|
||||
|
||||
Can also use the graphical version of CMake:
|
||||
* Open `CMake GUI`.
|
||||
* Under `Where to build the binaries`, same path as source plus `build`.
|
||||
* Under `CMAKE_INSTALL_PREFIX`, same path as source plus `install`.
|
||||
* Click `Configure`, `Generate`, `Open Project`.
|
||||
* If build fails, try deleting entire directory and starting again, or unticking options to build less.
|
||||
|
||||
## Building with Intel 2015 Update 1 or Intel System Studio Update 4
|
||||
|
||||
See instructions for building with Visual Studio. Once built, right click on the solution and change the build to Intel.
|
||||
|
||||
## Building on Solaris
|
||||
|
||||
If you're running benchmarks on solaris, you'll want the kstat library linked in
|
||||
too (`-lkstat`).
|
||||
34
thirdparty/benchmark/docs/python_bindings.md
vendored
34
thirdparty/benchmark/docs/python_bindings.md
vendored
@ -1,34 +0,0 @@
|
||||
# Building and installing Python bindings
|
||||
|
||||
Python bindings are available as wheels on [PyPI](https://pypi.org/project/google-benchmark/) for importing and
|
||||
using Google Benchmark directly in Python.
|
||||
Currently, pre-built wheels exist for macOS (both ARM64 and Intel x86), Linux x86-64 and 64-bit Windows.
|
||||
Supported Python versions are Python 3.8 - 3.12.
|
||||
|
||||
To install Google Benchmark's Python bindings, run:
|
||||
|
||||
```bash
|
||||
python -m pip install --upgrade pip # for manylinux2014 support
|
||||
python -m pip install google-benchmark
|
||||
```
|
||||
|
||||
In order to keep your system Python interpreter clean, it is advisable to run these commands in a virtual
|
||||
environment. See the [official Python documentation](https://docs.python.org/3/library/venv.html)
|
||||
on how to create virtual environments.
|
||||
|
||||
To build a wheel directly from source, you can follow these steps:
|
||||
```bash
|
||||
git clone https://github.com/google/benchmark.git
|
||||
cd benchmark
|
||||
# create a virtual environment and activate it
|
||||
python3 -m venv venv --system-site-packages
|
||||
source venv/bin/activate # .\venv\Scripts\Activate.ps1 on Windows
|
||||
|
||||
# upgrade Python's system-wide packages
|
||||
python -m pip install --upgrade pip build
|
||||
# builds the wheel and stores it in the directory "dist".
|
||||
python -m build
|
||||
```
|
||||
|
||||
NB: Building wheels from source requires Bazel. For platform-specific instructions on how to install Bazel,
|
||||
refer to the [Bazel installation docs](https://bazel.build/install).
|
||||
13
thirdparty/benchmark/docs/random_interleaving.md
vendored
13
thirdparty/benchmark/docs/random_interleaving.md
vendored
@ -1,13 +0,0 @@
|
||||
<a name="interleaving" />
|
||||
|
||||
# Random Interleaving
|
||||
|
||||
[Random Interleaving](https://github.com/google/benchmark/issues/1051) is a
|
||||
technique to lower run-to-run variance. It randomly interleaves repetitions of a
|
||||
microbenchmark with repetitions from other microbenchmarks in the same benchmark
|
||||
test. Data shows it is able to lower run-to-run variance by
|
||||
[40%](https://github.com/google/benchmark/issues/1051) on average.
|
||||
|
||||
To use, you mainly need to set `--benchmark_enable_random_interleaving=true`,
|
||||
and optionally specify non-zero repetition count `--benchmark_repetitions=9`
|
||||
and optionally decrease the per-repetition time `--benchmark_min_time=0.1`.
|
||||
138
thirdparty/benchmark/docs/reducing_variance.md
vendored
138
thirdparty/benchmark/docs/reducing_variance.md
vendored
@ -1,138 +0,0 @@
|
||||
# Reducing Variance
|
||||
|
||||
<a name="disabling-cpu-frequency-scaling" />
|
||||
|
||||
## Disabling CPU Frequency Scaling
|
||||
|
||||
If you see this error:
|
||||
|
||||
```
|
||||
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
|
||||
```
|
||||
|
||||
you might want to disable the CPU frequency scaling while running the
|
||||
benchmark, as well as consider other ways to stabilize the performance of
|
||||
your system while benchmarking.
|
||||
|
||||
Exactly how to do this depends on the Linux distribution,
|
||||
desktop environment, and installed programs. Specific details are a moving
|
||||
target, so we will not attempt to exhaustively document them here.
|
||||
|
||||
One simple option is to use the `cpupower` program to change the
|
||||
performance governor to "performance". This tool is maintained along with
|
||||
the Linux kernel and provided by your distribution.
|
||||
|
||||
It must be run as root, like this:
|
||||
|
||||
```bash
|
||||
sudo cpupower frequency-set --governor performance
|
||||
```
|
||||
|
||||
After this you can verify that all CPUs are using the performance governor
|
||||
by running this command:
|
||||
|
||||
```bash
|
||||
cpupower frequency-info -o proc
|
||||
```
|
||||
|
||||
The benchmarks you subsequently run will have less variance.
|
||||
|
||||
<a name="reducing-variance" />
|
||||
|
||||
## Disabling ASLR
|
||||
|
||||
If you see this error:
|
||||
|
||||
```
|
||||
***WARNING*** ASLR is enabled, the results may have unreproducible noise in them.
|
||||
```
|
||||
|
||||
you might want to disable the ASLR security hardening feature while running the
|
||||
benchmark.
|
||||
|
||||
The simplest way is to add
|
||||
```
|
||||
benchmark::MaybeReenterWithoutASLR(argc, argv);
|
||||
```
|
||||
as the first line of your `main()` function. It will try to disable ASLR
|
||||
for the current processor, and, if successful, re-execute the binary.
|
||||
Note that `personality(2)` may be forbidden by e.g. seccomp (which happens
|
||||
by default if you are running in a Docker container).
|
||||
|
||||
Note that if you link to `benchmark_main` already does that for you.
|
||||
|
||||
To globally disable ASLR on Linux, run
|
||||
```
|
||||
echo 0 > /proc/sys/kernel/randomize_va_space
|
||||
```
|
||||
|
||||
To run a single benchmark with ASLR disabled on Linux, do:
|
||||
```
|
||||
setarch `uname -m` -R ./a_benchmark
|
||||
```
|
||||
|
||||
Note that for the information on how to disable ASLR on other operating systems,
|
||||
please refer to their documentation.
|
||||
|
||||
## Reducing Variance in Benchmarks
|
||||
|
||||
The Linux CPU frequency governor [discussed
|
||||
above](user_guide#disabling-cpu-frequency-scaling) is not the only source
|
||||
of noise in benchmarks. Some, but not all, of the sources of variance
|
||||
include:
|
||||
|
||||
1. On multi-core machines not all CPUs/CPU cores/CPU threads run the same
|
||||
speed, so running a benchmark one time and then again may give a
|
||||
different result depending on which CPU it ran on.
|
||||
2. CPU scaling features that run on the CPU, like Intel's Turbo Boost and
|
||||
AMD Turbo Core and Precision Boost, can temporarily change the CPU
|
||||
frequency even when the using the "performance" governor on Linux.
|
||||
3. Context switching between CPUs, or scheduling competition on the CPU the
|
||||
benchmark is running on.
|
||||
4. Intel Hyperthreading or AMD SMT causing the same issue as above.
|
||||
5. Cache effects caused by code running on other CPUs.
|
||||
6. Non-uniform memory architectures (NUMA).
|
||||
|
||||
These can cause variance in benchmarks results within a single run
|
||||
(`--benchmark_repetitions=N`) or across multiple runs of the benchmark
|
||||
program.
|
||||
|
||||
Reducing sources of variance is OS and architecture dependent, which is one
|
||||
reason some companies maintain machines dedicated to performance testing.
|
||||
|
||||
Some of the easier and effective ways of reducing variance on a typical
|
||||
Linux workstation are:
|
||||
|
||||
1. Use the performance governor as [discussed
|
||||
above](user_guide#disabling-cpu-frequency-scaling).
|
||||
2. Disable processor boosting by:
|
||||
```sh
|
||||
echo 0 | sudo tee /sys/devices/system/cpu/cpufreq/boost
|
||||
```
|
||||
See the Linux kernel's
|
||||
[boost.txt](https://www.kernel.org/doc/Documentation/cpu-freq/boost.txt)
|
||||
for more information.
|
||||
3. Set the benchmark program's task affinity to a fixed cpu. For example:
|
||||
```sh
|
||||
taskset -c 0 ./mybenchmark
|
||||
```
|
||||
4. Increase the program's scheduling priority to minimize context switches using `nice` or `chrt`:
|
||||
```sh
|
||||
sudo nice -n -20 ./mybenchmark
|
||||
sudo chrt -f 80 ./mybenchmark
|
||||
```
|
||||
5. Disabling Hyperthreading/SMT. This can be done in the Bios or using the
|
||||
`/sys` file system (see the LLVM project's [Benchmarking
|
||||
tips](https://llvm.org/docs/Benchmarking.html)).
|
||||
6. Close other programs that do non-trivial things based on timers, such as
|
||||
your web browser, desktop environment, etc.
|
||||
7. Reduce the working set of your benchmark to fit within the L1 cache, but
|
||||
do be aware that this may lead you to optimize for an unrealistic
|
||||
situation.
|
||||
|
||||
Further resources on this topic:
|
||||
|
||||
1. The LLVM project's [Benchmarking
|
||||
tips](https://llvm.org/docs/Benchmarking.html).
|
||||
1. The Arch Wiki [Cpu frequency
|
||||
scaling](https://wiki.archlinux.org/title/CPU_frequency_scaling) page.
|
||||
38
thirdparty/benchmark/docs/releasing.md
vendored
38
thirdparty/benchmark/docs/releasing.md
vendored
@ -1,38 +0,0 @@
|
||||
# How to release
|
||||
|
||||
* Make sure you're on main and synced to HEAD
|
||||
* Ensure the project builds and tests run
|
||||
* `parallel -j0 exec ::: test/*_test` can help ensure everything at least
|
||||
passes
|
||||
* Prepare release notes
|
||||
* `git log $(git describe --abbrev=0 --tags)..HEAD` gives you the list of
|
||||
commits between the last annotated tag and HEAD
|
||||
* Pick the most interesting.
|
||||
* Create one last commit that updates the version saved in `CMakeLists.txt`, `MODULE.bazel`,
|
||||
and `bindings/python/google_benchmark/__init__.py` to the release version you're creating.
|
||||
(This version will be used if benchmark is installed from the archive you'll be creating
|
||||
in the next step.)
|
||||
|
||||
```
|
||||
# CMakeLists.txt
|
||||
project (benchmark VERSION 1.9.0 LANGUAGES CXX)
|
||||
```
|
||||
|
||||
```
|
||||
# MODULE.bazel
|
||||
module(name = "com_github_google_benchmark", version="1.9.0")
|
||||
```
|
||||
|
||||
```
|
||||
# google_benchmark/__init__.py
|
||||
__version__ = "1.9.0"
|
||||
```
|
||||
|
||||
* Create a release through github's interface
|
||||
* Note this will create a lightweight tag.
|
||||
* Update this to an annotated tag:
|
||||
* `git pull --tags`
|
||||
* `git tag -a -f <tag> <tag>`
|
||||
* `git push --force --tags origin`
|
||||
* Confirm that the "Build and upload Python wheels" action runs to completion
|
||||
* Run it manually if it hasn't run.
|
||||
343
thirdparty/benchmark/docs/tools.md
vendored
343
thirdparty/benchmark/docs/tools.md
vendored
@ -1,343 +0,0 @@
|
||||
# Benchmark Tools
|
||||
|
||||
## compare.py
|
||||
|
||||
The `compare.py` can be used to compare the result of benchmarks.
|
||||
|
||||
### Dependencies
|
||||
The utility relies on the [scipy](https://www.scipy.org) package which can be installed using pip:
|
||||
```bash
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
### Displaying aggregates only
|
||||
|
||||
The switch `-a` / `--display_aggregates_only` can be used to control the
|
||||
displayment of the normal iterations vs the aggregates. When passed, it will
|
||||
be passthrough to the benchmark binaries to be run, and will be accounted for
|
||||
in the tool itself; only the aggregates will be displayed, but not normal runs.
|
||||
It only affects the display, the separate runs will still be used to calculate
|
||||
the U test.
|
||||
|
||||
### Modes of operation
|
||||
|
||||
There are three modes of operation:
|
||||
|
||||
1. Just compare two benchmarks
|
||||
The program is invoked like:
|
||||
|
||||
``` bash
|
||||
$ compare.py benchmarks <benchmark_baseline> <benchmark_contender> [benchmark options]...
|
||||
```
|
||||
Where `<benchmark_baseline>` and `<benchmark_contender>` either specify a benchmark executable file, or a JSON output file. The type of the input file is automatically detected. If a benchmark executable is specified then the benchmark is run to obtain the results. Otherwise the results are simply loaded from the output file.
|
||||
|
||||
`[benchmark options]` will be passed to the benchmarks invocations. They can be anything that binary accepts, be it either normal `--benchmark_*` parameters, or some custom parameters your binary takes.
|
||||
|
||||
Example output:
|
||||
```
|
||||
$ ./compare.py benchmarks ./a.out ./a.out
|
||||
RUNNING: ./a.out --benchmark_out=/tmp/tmprBT5nW
|
||||
Run on (8 X 4000 MHz CPU s)
|
||||
2017-11-07 21:16:44
|
||||
------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
------------------------------------------------------
|
||||
BM_memcpy/8 36 ns 36 ns 19101577 211.669MB/s
|
||||
BM_memcpy/64 76 ns 76 ns 9412571 800.199MB/s
|
||||
BM_memcpy/512 84 ns 84 ns 8249070 5.64771GB/s
|
||||
BM_memcpy/1024 116 ns 116 ns 6181763 8.19505GB/s
|
||||
BM_memcpy/8192 643 ns 643 ns 1062855 11.8636GB/s
|
||||
BM_copy/8 222 ns 222 ns 3137987 34.3772MB/s
|
||||
BM_copy/64 1608 ns 1608 ns 432758 37.9501MB/s
|
||||
BM_copy/512 12589 ns 12589 ns 54806 38.7867MB/s
|
||||
BM_copy/1024 25169 ns 25169 ns 27713 38.8003MB/s
|
||||
BM_copy/8192 201165 ns 201112 ns 3486 38.8466MB/s
|
||||
RUNNING: ./a.out --benchmark_out=/tmp/tmpt1wwG_
|
||||
Run on (8 X 4000 MHz CPU s)
|
||||
2017-11-07 21:16:53
|
||||
------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
------------------------------------------------------
|
||||
BM_memcpy/8 36 ns 36 ns 19397903 211.255MB/s
|
||||
BM_memcpy/64 73 ns 73 ns 9691174 839.635MB/s
|
||||
BM_memcpy/512 85 ns 85 ns 8312329 5.60101GB/s
|
||||
BM_memcpy/1024 118 ns 118 ns 6438774 8.11608GB/s
|
||||
BM_memcpy/8192 656 ns 656 ns 1068644 11.6277GB/s
|
||||
BM_copy/8 223 ns 223 ns 3146977 34.2338MB/s
|
||||
BM_copy/64 1611 ns 1611 ns 435340 37.8751MB/s
|
||||
BM_copy/512 12622 ns 12622 ns 54818 38.6844MB/s
|
||||
BM_copy/1024 25257 ns 25239 ns 27779 38.6927MB/s
|
||||
BM_copy/8192 205013 ns 205010 ns 3479 38.108MB/s
|
||||
Comparing ./a.out to ./a.out
|
||||
Benchmark Time CPU Time Old Time New CPU Old CPU New
|
||||
------------------------------------------------------------------------------------------------------
|
||||
BM_memcpy/8 +0.0020 +0.0020 36 36 36 36
|
||||
BM_memcpy/64 -0.0468 -0.0470 76 73 76 73
|
||||
BM_memcpy/512 +0.0081 +0.0083 84 85 84 85
|
||||
BM_memcpy/1024 +0.0098 +0.0097 116 118 116 118
|
||||
BM_memcpy/8192 +0.0200 +0.0203 643 656 643 656
|
||||
BM_copy/8 +0.0046 +0.0042 222 223 222 223
|
||||
BM_copy/64 +0.0020 +0.0020 1608 1611 1608 1611
|
||||
BM_copy/512 +0.0027 +0.0026 12589 12622 12589 12622
|
||||
BM_copy/1024 +0.0035 +0.0028 25169 25257 25169 25239
|
||||
BM_copy/8192 +0.0191 +0.0194 201165 205013 201112 205010
|
||||
```
|
||||
|
||||
What it does is for the every benchmark from the first run it looks for the benchmark with exactly the same name in the second run, and then compares the results. If the names differ, the benchmark is omitted from the diff.
|
||||
As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`.
|
||||
|
||||
2. Compare two different filters of one benchmark
|
||||
The program is invoked like:
|
||||
|
||||
``` bash
|
||||
$ compare.py filters <benchmark> <filter_baseline> <filter_contender> [benchmark options]...
|
||||
```
|
||||
Where `<benchmark>` either specify a benchmark executable file, or a JSON output file. The type of the input file is automatically detected. If a benchmark executable is specified then the benchmark is run to obtain the results. Otherwise the results are simply loaded from the output file.
|
||||
|
||||
Where `<filter_baseline>` and `<filter_contender>` are the same regex filters that you would pass to the `[--benchmark_filter=<regex>]` parameter of the benchmark binary.
|
||||
|
||||
`[benchmark options]` will be passed to the benchmarks invocations. They can be anything that binary accepts, be it either normal `--benchmark_*` parameters, or some custom parameters your binary takes.
|
||||
|
||||
Example output:
|
||||
```
|
||||
$ ./compare.py filters ./a.out BM_memcpy BM_copy
|
||||
RUNNING: ./a.out --benchmark_filter=BM_memcpy --benchmark_out=/tmp/tmpBWKk0k
|
||||
Run on (8 X 4000 MHz CPU s)
|
||||
2017-11-07 21:37:28
|
||||
------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
------------------------------------------------------
|
||||
BM_memcpy/8 36 ns 36 ns 17891491 211.215MB/s
|
||||
BM_memcpy/64 74 ns 74 ns 9400999 825.646MB/s
|
||||
BM_memcpy/512 87 ns 87 ns 8027453 5.46126GB/s
|
||||
BM_memcpy/1024 111 ns 111 ns 6116853 8.5648GB/s
|
||||
BM_memcpy/8192 657 ns 656 ns 1064679 11.6247GB/s
|
||||
RUNNING: ./a.out --benchmark_filter=BM_copy --benchmark_out=/tmp/tmpAvWcOM
|
||||
Run on (8 X 4000 MHz CPU s)
|
||||
2017-11-07 21:37:33
|
||||
----------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
----------------------------------------------------
|
||||
BM_copy/8 227 ns 227 ns 3038700 33.6264MB/s
|
||||
BM_copy/64 1640 ns 1640 ns 426893 37.2154MB/s
|
||||
BM_copy/512 12804 ns 12801 ns 55417 38.1444MB/s
|
||||
BM_copy/1024 25409 ns 25407 ns 27516 38.4365MB/s
|
||||
BM_copy/8192 202986 ns 202990 ns 3454 38.4871MB/s
|
||||
Comparing BM_memcpy to BM_copy (from ./a.out)
|
||||
Benchmark Time CPU Time Old Time New CPU Old CPU New
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
[BM_memcpy vs. BM_copy]/8 +5.2829 +5.2812 36 227 36 227
|
||||
[BM_memcpy vs. BM_copy]/64 +21.1719 +21.1856 74 1640 74 1640
|
||||
[BM_memcpy vs. BM_copy]/512 +145.6487 +145.6097 87 12804 87 12801
|
||||
[BM_memcpy vs. BM_copy]/1024 +227.1860 +227.1776 111 25409 111 25407
|
||||
[BM_memcpy vs. BM_copy]/8192 +308.1664 +308.2898 657 202986 656 202990
|
||||
```
|
||||
|
||||
As you can see, it applies filter to the benchmarks, both when running the benchmark, and before doing the diff. And to make the diff work, the matches are replaced with some common string. Thus, you can compare two different benchmark families within one benchmark binary.
|
||||
As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`.
|
||||
|
||||
3. Compare filter one from benchmark one to filter two from benchmark two:
|
||||
The program is invoked like:
|
||||
|
||||
``` bash
|
||||
$ compare.py filters <benchmark_baseline> <filter_baseline> <benchmark_contender> <filter_contender> [benchmark options]...
|
||||
```
|
||||
|
||||
Where `<benchmark_baseline>` and `<benchmark_contender>` either specify a benchmark executable file, or a JSON output file. The type of the input file is automatically detected. If a benchmark executable is specified then the benchmark is run to obtain the results. Otherwise the results are simply loaded from the output file.
|
||||
|
||||
Where `<filter_baseline>` and `<filter_contender>` are the same regex filters that you would pass to the `[--benchmark_filter=<regex>]` parameter of the benchmark binary.
|
||||
|
||||
`[benchmark options]` will be passed to the benchmarks invocations. They can be anything that binary accepts, be it either normal `--benchmark_*` parameters, or some custom parameters your binary takes.
|
||||
|
||||
Example output:
|
||||
```
|
||||
$ ./compare.py benchmarksfiltered ./a.out BM_memcpy ./a.out BM_copy
|
||||
RUNNING: ./a.out --benchmark_filter=BM_memcpy --benchmark_out=/tmp/tmp_FvbYg
|
||||
Run on (8 X 4000 MHz CPU s)
|
||||
2017-11-07 21:38:27
|
||||
------------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
------------------------------------------------------
|
||||
BM_memcpy/8 37 ns 37 ns 18953482 204.118MB/s
|
||||
BM_memcpy/64 74 ns 74 ns 9206578 828.245MB/s
|
||||
BM_memcpy/512 91 ns 91 ns 8086195 5.25476GB/s
|
||||
BM_memcpy/1024 120 ns 120 ns 5804513 7.95662GB/s
|
||||
BM_memcpy/8192 664 ns 664 ns 1028363 11.4948GB/s
|
||||
RUNNING: ./a.out --benchmark_filter=BM_copy --benchmark_out=/tmp/tmpDfL5iE
|
||||
Run on (8 X 4000 MHz CPU s)
|
||||
2017-11-07 21:38:32
|
||||
----------------------------------------------------
|
||||
Benchmark Time CPU Iterations
|
||||
----------------------------------------------------
|
||||
BM_copy/8 230 ns 230 ns 2985909 33.1161MB/s
|
||||
BM_copy/64 1654 ns 1653 ns 419408 36.9137MB/s
|
||||
BM_copy/512 13122 ns 13120 ns 53403 37.2156MB/s
|
||||
BM_copy/1024 26679 ns 26666 ns 26575 36.6218MB/s
|
||||
BM_copy/8192 215068 ns 215053 ns 3221 36.3283MB/s
|
||||
Comparing BM_memcpy (from ./a.out) to BM_copy (from ./a.out)
|
||||
Benchmark Time CPU Time Old Time New CPU Old CPU New
|
||||
--------------------------------------------------------------------------------------------------------------------
|
||||
[BM_memcpy vs. BM_copy]/8 +5.1649 +5.1637 37 230 37 230
|
||||
[BM_memcpy vs. BM_copy]/64 +21.4352 +21.4374 74 1654 74 1653
|
||||
[BM_memcpy vs. BM_copy]/512 +143.6022 +143.5865 91 13122 91 13120
|
||||
[BM_memcpy vs. BM_copy]/1024 +221.5903 +221.4790 120 26679 120 26666
|
||||
[BM_memcpy vs. BM_copy]/8192 +322.9059 +323.0096 664 215068 664 215053
|
||||
```
|
||||
This is a mix of the previous two modes, two (potentially different) benchmark binaries are run, and a different filter is applied to each one.
|
||||
As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`.
|
||||
|
||||
### Note: Interpreting the output
|
||||
|
||||
Performance measurements are an art, and performance comparisons are doubly so.
|
||||
Results are often noisy and don't necessarily have large absolute differences to
|
||||
them, so just by visual inspection, it is not at all apparent if two
|
||||
measurements are actually showing a performance change or not. It is even more
|
||||
confusing with multiple benchmark repetitions.
|
||||
|
||||
Thankfully, what we can do, is use statistical tests on the results to determine
|
||||
whether the performance has statistically-significantly changed. `compare.py`
|
||||
uses [Mann–Whitney U
|
||||
test](https://en.wikipedia.org/wiki/Mann%E2%80%93Whitney_U_test), with a null
|
||||
hypothesis being that there's no difference in performance.
|
||||
|
||||
**The below output is a summary of a benchmark comparison with statistics
|
||||
provided for a multi-threaded process.**
|
||||
```
|
||||
Benchmark Time CPU Time Old Time New CPU Old CPU New
|
||||
-----------------------------------------------------------------------------------------------------------------------------
|
||||
benchmark/threads:1/process_time/real_time_pvalue 0.0000 0.0000 U Test, Repetitions: 27 vs 27
|
||||
benchmark/threads:1/process_time/real_time_mean -0.1442 -0.1442 90 77 90 77
|
||||
benchmark/threads:1/process_time/real_time_median -0.1444 -0.1444 90 77 90 77
|
||||
benchmark/threads:1/process_time/real_time_stddev +0.3974 +0.3933 0 0 0 0
|
||||
benchmark/threads:1/process_time/real_time_cv +0.6329 +0.6280 0 0 0 0
|
||||
OVERALL_GEOMEAN -0.1442 -0.1442 0 0 0 0
|
||||
```
|
||||
--------------------------------------------
|
||||
Here's a breakdown of each row:
|
||||
|
||||
**benchmark/threads:1/process_time/real_time_pvalue**: This shows the _p-value_ for
|
||||
the statistical test comparing the performance of the process running with one
|
||||
thread. A value of 0.0000 suggests a statistically significant difference in
|
||||
performance. The comparison was conducted using the U Test (Mann-Whitney
|
||||
U Test) with 27 repetitions for each case.
|
||||
|
||||
**benchmark/threads:1/process_time/real_time_mean**: This shows the relative
|
||||
difference in mean execution time between two different cases. The negative
|
||||
value (-0.1442) implies that the new process is faster by about 14.42%. The old
|
||||
time was 90 units, while the new time is 77 units.
|
||||
|
||||
**benchmark/threads:1/process_time/real_time_median**: Similarly, this shows the
|
||||
relative difference in the median execution time. Again, the new process is
|
||||
faster by 14.44%.
|
||||
|
||||
**benchmark/threads:1/process_time/real_time_stddev**: This is the relative
|
||||
difference in the standard deviation of the execution time, which is a measure
|
||||
of how much variation or dispersion there is from the mean. A positive value
|
||||
(+0.3974) implies there is more variance in the execution time in the new
|
||||
process.
|
||||
|
||||
**benchmark/threads:1/process_time/real_time_cv**: CV stands for Coefficient of
|
||||
Variation. It is the ratio of the standard deviation to the mean. It provides a
|
||||
standardized measure of dispersion. An increase (+0.6329) indicates more
|
||||
relative variability in the new process.
|
||||
|
||||
**OVERALL_GEOMEAN**: Geomean stands for geometric mean, a type of average that is
|
||||
less influenced by outliers. The negative value indicates a general improvement
|
||||
in the new process. However, given the values are all zero for the old and new
|
||||
times, this seems to be a mistake or placeholder in the output.
|
||||
|
||||
-----------------------------------------
|
||||
|
||||
|
||||
|
||||
Let's first try to see what the different columns represent in the above
|
||||
`compare.py` benchmarking output:
|
||||
|
||||
1. **Benchmark:** The name of the function being benchmarked, along with the
|
||||
size of the input (after the slash).
|
||||
|
||||
2. **Time:** The average time per operation, across all iterations.
|
||||
|
||||
3. **CPU:** The average CPU time per operation, across all iterations.
|
||||
|
||||
4. **Iterations:** The number of iterations the benchmark was run to get a
|
||||
stable estimate.
|
||||
|
||||
5. **Time Old and Time New:** These represent the average time it takes for a
|
||||
function to run in two different scenarios or versions. For example, you
|
||||
might be comparing how fast a function runs before and after you make some
|
||||
changes to it.
|
||||
|
||||
6. **CPU Old and CPU New:** These show the average amount of CPU time that the
|
||||
function uses in two different scenarios or versions. This is similar to
|
||||
Time Old and Time New, but focuses on CPU usage instead of overall time.
|
||||
|
||||
In the comparison section, the relative differences in both time and CPU time
|
||||
are displayed for each input size.
|
||||
|
||||
|
||||
A statistically-significant difference is determined by a **p-value**, which is
|
||||
a measure of the probability that the observed difference could have occurred
|
||||
just by random chance. A smaller p-value indicates stronger evidence against the
|
||||
null hypothesis.
|
||||
|
||||
**Therefore:**
|
||||
1. If the p-value is less than the chosen significance level (alpha), we
|
||||
reject the null hypothesis and conclude the benchmarks are significantly
|
||||
different.
|
||||
2. If the p-value is greater than or equal to alpha, we fail to reject the
|
||||
null hypothesis and treat the two benchmarks as similar.
|
||||
|
||||
|
||||
|
||||
The result of said the statistical test is additionally communicated through color coding:
|
||||
```diff
|
||||
+ Green:
|
||||
```
|
||||
The benchmarks are _**statistically different**_. This could mean the
|
||||
performance has either **significantly improved** or **significantly
|
||||
deteriorated**. You should look at the actual performance numbers to see which
|
||||
is the case.
|
||||
```diff
|
||||
- Red:
|
||||
```
|
||||
The benchmarks are _**statistically similar**_. This means the performance
|
||||
**hasn't significantly changed**.
|
||||
|
||||
In statistical terms, **'green'** means we reject the null hypothesis that
|
||||
there's no difference in performance, and **'red'** means we fail to reject the
|
||||
null hypothesis. This might seem counter-intuitive if you're expecting 'green'
|
||||
to mean 'improved performance' and 'red' to mean 'worsened performance'.
|
||||
```bash
|
||||
But remember, in this context:
|
||||
|
||||
'Success' means 'successfully finding a difference'.
|
||||
'Failure' means 'failing to find a difference'.
|
||||
```
|
||||
|
||||
|
||||
Also, please note that **even if** we determine that there **is** a
|
||||
statistically-significant difference between the two measurements, it does not
|
||||
_necessarily_ mean that the actual benchmarks that were measured **are**
|
||||
different, or vice versa, even if we determine that there is **no**
|
||||
statistically-significant difference between the two measurements, it does not
|
||||
necessarily mean that the actual benchmarks that were measured **are not**
|
||||
different.
|
||||
|
||||
|
||||
|
||||
### U test
|
||||
|
||||
If there is a sufficient repetition count of the benchmarks, the tool can do
|
||||
a [U Test](https://en.wikipedia.org/wiki/Mann%E2%80%93Whitney_U_test), of the
|
||||
null hypothesis that it is equally likely that a randomly selected value from
|
||||
one sample will be less than or greater than a randomly selected value from a
|
||||
second sample.
|
||||
|
||||
If the calculated p-value is below this value is lower than the significance
|
||||
level alpha, then the result is said to be statistically significant and the
|
||||
null hypothesis is rejected. Which in other words means that the two benchmarks
|
||||
aren't identical.
|
||||
|
||||
**WARNING**: requires **LARGE** (no less than 9) number of repetitions to be
|
||||
meaningful!
|
||||
1765
thirdparty/benchmark/docs/user_guide.md
vendored
1765
thirdparty/benchmark/docs/user_guide.md
vendored
File diff suppressed because it is too large
Load Diff
@ -1,30 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_BENCHMARK_H_
|
||||
#define BENCHMARK_BENCHMARK_H_
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "benchmark/counter.h"
|
||||
#include "benchmark/macros.h"
|
||||
#include "benchmark/managers.h"
|
||||
#include "benchmark/registration.h"
|
||||
#include "benchmark/reporter.h"
|
||||
#include "benchmark/state.h"
|
||||
#include "benchmark/statistics.h"
|
||||
#include "benchmark/sysinfo.h"
|
||||
#include "benchmark/types.h"
|
||||
#include "benchmark/utils.h"
|
||||
|
||||
#endif // BENCHMARK_BENCHMARK_H_
|
||||
@ -1,292 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_BENCHMARK_API_H_
|
||||
#define BENCHMARK_BENCHMARK_API_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4251)
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/counter.h"
|
||||
#include "benchmark/macros.h"
|
||||
#include "benchmark/state.h"
|
||||
#include "benchmark/statistics.h"
|
||||
#include "benchmark/types.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
const char kDefaultMinTimeStr[] = "0.5s";
|
||||
|
||||
BENCHMARK_EXPORT void MaybeReenterWithoutASLR(int, char**);
|
||||
|
||||
BENCHMARK_EXPORT std::string GetBenchmarkVersion();
|
||||
|
||||
BENCHMARK_EXPORT void PrintDefaultHelp();
|
||||
|
||||
BENCHMARK_EXPORT void Initialize(int* argc, char** argv,
|
||||
void (*HelperPrintf)() = PrintDefaultHelp);
|
||||
BENCHMARK_EXPORT void Shutdown();
|
||||
|
||||
BENCHMARK_EXPORT bool ReportUnrecognizedArguments(int argc, char** argv);
|
||||
|
||||
BENCHMARK_EXPORT std::string GetBenchmarkFilter();
|
||||
|
||||
BENCHMARK_EXPORT void SetBenchmarkFilter(std::string value);
|
||||
|
||||
BENCHMARK_EXPORT int32_t GetBenchmarkVerbosity();
|
||||
|
||||
BENCHMARK_EXPORT BenchmarkReporter* CreateDefaultDisplayReporter();
|
||||
|
||||
BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks();
|
||||
BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(std::string spec);
|
||||
|
||||
BENCHMARK_EXPORT size_t
|
||||
RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter);
|
||||
BENCHMARK_EXPORT size_t
|
||||
RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, std::string spec);
|
||||
|
||||
BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(
|
||||
BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter);
|
||||
BENCHMARK_EXPORT size_t
|
||||
RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
|
||||
BenchmarkReporter* file_reporter, std::string spec);
|
||||
|
||||
BENCHMARK_EXPORT TimeUnit GetDefaultTimeUnit();
|
||||
|
||||
BENCHMARK_EXPORT void SetDefaultTimeUnit(TimeUnit unit);
|
||||
|
||||
BENCHMARK_EXPORT
|
||||
void AddCustomContext(std::string key, std::string value);
|
||||
|
||||
struct ThreadRunnerBase {
|
||||
virtual ~ThreadRunnerBase() {}
|
||||
virtual void RunThreads(const std::function<void(int)>& fn) = 0;
|
||||
};
|
||||
|
||||
using threadrunner_factory =
|
||||
std::function<std::unique_ptr<ThreadRunnerBase>(int)>;
|
||||
|
||||
namespace internal {
|
||||
class BenchmarkFamilies;
|
||||
class BenchmarkInstance;
|
||||
} // namespace internal
|
||||
|
||||
class BENCHMARK_EXPORT Benchmark {
|
||||
public:
|
||||
virtual ~Benchmark();
|
||||
|
||||
Benchmark* Name(const std::string& name);
|
||||
Benchmark* Arg(int64_t x);
|
||||
Benchmark* Unit(TimeUnit unit);
|
||||
Benchmark* Range(int64_t start, int64_t limit);
|
||||
Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1);
|
||||
Benchmark* Args(const std::vector<int64_t>& args);
|
||||
Benchmark* ArgPair(int64_t x, int64_t y) {
|
||||
std::vector<int64_t> args;
|
||||
args.push_back(x);
|
||||
args.push_back(y);
|
||||
return Args(args);
|
||||
}
|
||||
Benchmark* Ranges(const std::vector<std::pair<int64_t, int64_t>>& ranges);
|
||||
Benchmark* ArgsProduct(const std::vector<std::vector<int64_t>>& arglists);
|
||||
Benchmark* ArgName(const std::string& name);
|
||||
Benchmark* ArgNames(const std::vector<std::string>& names);
|
||||
Benchmark* RangePair(int64_t lo1, int64_t hi1, int64_t lo2, int64_t hi2) {
|
||||
std::vector<std::pair<int64_t, int64_t>> ranges;
|
||||
ranges.push_back(std::make_pair(lo1, hi1));
|
||||
ranges.push_back(std::make_pair(lo2, hi2));
|
||||
return Ranges(ranges);
|
||||
}
|
||||
Benchmark* Setup(callback_function&&);
|
||||
Benchmark* Setup(const callback_function&);
|
||||
Benchmark* Teardown(callback_function&&);
|
||||
Benchmark* Teardown(const callback_function&);
|
||||
Benchmark* Apply(const std::function<void(Benchmark* benchmark)>&);
|
||||
Benchmark* RangeMultiplier(int multiplier);
|
||||
Benchmark* MinTime(double t);
|
||||
Benchmark* MinWarmUpTime(double t);
|
||||
Benchmark* Iterations(IterationCount n);
|
||||
Benchmark* Repetitions(int n);
|
||||
Benchmark* ReportAggregatesOnly(bool value = true);
|
||||
Benchmark* DisplayAggregatesOnly(bool value = true);
|
||||
Benchmark* MeasureProcessCPUTime();
|
||||
Benchmark* UseRealTime();
|
||||
Benchmark* UseManualTime();
|
||||
Benchmark* Complexity(BigO complexity = benchmark::oAuto);
|
||||
Benchmark* Complexity(BigOFunc* complexity);
|
||||
Benchmark* ComputeStatistics(const std::string& name,
|
||||
StatisticsFunc* statistics,
|
||||
StatisticUnit unit = kTime);
|
||||
Benchmark* Threads(int t);
|
||||
Benchmark* ThreadRange(int min_threads, int max_threads);
|
||||
Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1);
|
||||
Benchmark* ThreadPerCpu();
|
||||
Benchmark* ThreadRunner(threadrunner_factory&& factory);
|
||||
|
||||
virtual void Run(State& state) = 0;
|
||||
|
||||
TimeUnit GetTimeUnit() const;
|
||||
|
||||
protected:
|
||||
explicit Benchmark(const std::string& name);
|
||||
void SetName(const std::string& name);
|
||||
|
||||
public:
|
||||
const char* GetName() const;
|
||||
int ArgsCnt() const;
|
||||
const char* GetArgName(int arg) const;
|
||||
|
||||
private:
|
||||
friend class internal::BenchmarkFamilies;
|
||||
friend class internal::BenchmarkInstance;
|
||||
|
||||
std::string name_;
|
||||
internal::AggregationReportMode aggregation_report_mode_;
|
||||
std::vector<std::string> arg_names_;
|
||||
std::vector<std::vector<int64_t>> args_;
|
||||
|
||||
TimeUnit time_unit_;
|
||||
bool use_default_time_unit_;
|
||||
|
||||
int range_multiplier_;
|
||||
double min_time_;
|
||||
double min_warmup_time_;
|
||||
IterationCount iterations_;
|
||||
int repetitions_;
|
||||
bool measure_process_cpu_time_;
|
||||
bool use_real_time_;
|
||||
bool use_manual_time_;
|
||||
BigO complexity_;
|
||||
BigOFunc* complexity_lambda_;
|
||||
std::vector<internal::Statistics> statistics_;
|
||||
std::vector<int> thread_counts_;
|
||||
|
||||
callback_function setup_;
|
||||
callback_function teardown_;
|
||||
|
||||
threadrunner_factory threadrunner_;
|
||||
|
||||
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(Benchmark);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
typedef BENCHMARK_DEPRECATED_MSG(
|
||||
"Use ::benchmark::Benchmark instead")::benchmark::Benchmark Benchmark;
|
||||
typedef BENCHMARK_DEPRECATED_MSG(
|
||||
"Use ::benchmark::threadrunner_factory instead")::benchmark::
|
||||
threadrunner_factory threadrunner_factory;
|
||||
|
||||
typedef void(Function)(State&);
|
||||
|
||||
BENCHMARK_EXPORT ::benchmark::Benchmark* RegisterBenchmarkInternal(
|
||||
std::unique_ptr<::benchmark::Benchmark>);
|
||||
BENCHMARK_EXPORT std::map<std::string, std::string>*& GetGlobalContext();
|
||||
BENCHMARK_EXPORT void UseCharPointer(char const volatile*);
|
||||
BENCHMARK_EXPORT int InitializeStreams();
|
||||
BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
|
||||
} // namespace internal
|
||||
|
||||
Benchmark* RegisterBenchmark(const std::string& name, internal::Function* fn);
|
||||
|
||||
template <class Lambda>
|
||||
Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn);
|
||||
|
||||
BENCHMARK_EXPORT void ClearRegisteredBenchmarks();
|
||||
|
||||
namespace internal {
|
||||
class BENCHMARK_EXPORT FunctionBenchmark : public benchmark::Benchmark {
|
||||
public:
|
||||
FunctionBenchmark(const std::string& name, Function* func)
|
||||
: Benchmark(name), func_(func) {}
|
||||
void Run(State& st) override;
|
||||
|
||||
private:
|
||||
Function* func_;
|
||||
};
|
||||
|
||||
template <class Lambda>
|
||||
class LambdaBenchmark : public benchmark::Benchmark {
|
||||
public:
|
||||
void Run(State& st) override { lambda_(st); }
|
||||
template <class OLambda>
|
||||
LambdaBenchmark(const std::string& name, OLambda&& lam)
|
||||
: Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
|
||||
|
||||
private:
|
||||
LambdaBenchmark(LambdaBenchmark const&) = delete;
|
||||
Lambda lambda_;
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
inline Benchmark* RegisterBenchmark(const std::string& name,
|
||||
internal::Function* fn) {
|
||||
return internal::RegisterBenchmarkInternal(
|
||||
::benchmark::internal::make_unique<internal::FunctionBenchmark>(name,
|
||||
fn));
|
||||
}
|
||||
|
||||
template <class Lambda>
|
||||
Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn) {
|
||||
using BenchType =
|
||||
internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
|
||||
return internal::RegisterBenchmarkInternal(
|
||||
::benchmark::internal::make_unique<BenchType>(name,
|
||||
std::forward<Lambda>(fn)));
|
||||
}
|
||||
|
||||
template <class Lambda, class... Args>
|
||||
Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn,
|
||||
Args&&... args) {
|
||||
return benchmark::RegisterBenchmark(
|
||||
name, [=](benchmark::State& st) { fn(st, args...); });
|
||||
}
|
||||
|
||||
class Fixture : public Benchmark {
|
||||
public:
|
||||
Fixture() : Benchmark("") {}
|
||||
void Run(State& st) override {
|
||||
this->SetUp(st);
|
||||
this->BenchmarkCase(st);
|
||||
this->TearDown(st);
|
||||
}
|
||||
virtual void SetUp(const State&) {}
|
||||
virtual void TearDown(const State&) {}
|
||||
virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); }
|
||||
virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); }
|
||||
|
||||
protected:
|
||||
virtual void BenchmarkCase(State&) = 0;
|
||||
};
|
||||
|
||||
BENCHMARK_EXPORT
|
||||
std::vector<int64_t> CreateRange(int64_t lo, int64_t hi, int multi);
|
||||
|
||||
BENCHMARK_EXPORT
|
||||
std::vector<int64_t> CreateDenseRange(int64_t start, int64_t limit, int step);
|
||||
|
||||
} // namespace benchmark
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BENCHMARK_BENCHMARK_API_H_
|
||||
80
thirdparty/benchmark/include/benchmark/counter.h
vendored
80
thirdparty/benchmark/include/benchmark/counter.h
vendored
@ -1,80 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_COUNTER_H_
|
||||
#define BENCHMARK_COUNTER_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4251)
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "benchmark/macros.h"
|
||||
#include "benchmark/types.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
class BENCHMARK_EXPORT Counter {
|
||||
public:
|
||||
enum Flags {
|
||||
kDefaults = 0,
|
||||
kIsRate = 1 << 0,
|
||||
kAvgThreads = 1 << 1,
|
||||
kAvgThreadsRate = kIsRate | kAvgThreads,
|
||||
kIsIterationInvariant = 1 << 2,
|
||||
kIsIterationInvariantRate = kIsRate | kIsIterationInvariant,
|
||||
kAvgIterations = 1 << 3,
|
||||
kAvgIterationsRate = kIsRate | kAvgIterations,
|
||||
kInvert = 1 << 31
|
||||
};
|
||||
|
||||
enum OneK { kIs1000 = 1000, kIs1024 = 1024 };
|
||||
|
||||
double value;
|
||||
Flags flags;
|
||||
OneK oneK;
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
Counter(double v = 0., Flags f = kDefaults, OneK k = kIs1000)
|
||||
: value(v), flags(f), oneK(k) {}
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE operator double const&() const { return value; }
|
||||
BENCHMARK_ALWAYS_INLINE operator double&() { return value; }
|
||||
};
|
||||
|
||||
Counter::Flags inline operator|(const Counter::Flags& LHS,
|
||||
const Counter::Flags& RHS) {
|
||||
return static_cast<Counter::Flags>(static_cast<int>(LHS) |
|
||||
static_cast<int>(RHS));
|
||||
}
|
||||
|
||||
using UserCounters = std::map<std::string, Counter>;
|
||||
|
||||
namespace internal {
|
||||
void Finish(UserCounters* l, IterationCount iterations, double cpu_time,
|
||||
double num_threads);
|
||||
void Increment(UserCounters* l, UserCounters const& r);
|
||||
bool SameNames(UserCounters const& l, UserCounters const& r);
|
||||
} // namespace internal
|
||||
|
||||
} // namespace benchmark
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BENCHMARK_COUNTER_H_
|
||||
47
thirdparty/benchmark/include/benchmark/export.h
vendored
47
thirdparty/benchmark/include/benchmark/export.h
vendored
@ -1,47 +0,0 @@
|
||||
#ifndef BENCHMARK_EXPORT_H
|
||||
#define BENCHMARK_EXPORT_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define EXPORT_ATTR __declspec(dllexport)
|
||||
#define IMPORT_ATTR __declspec(dllimport)
|
||||
#define NO_EXPORT_ATTR
|
||||
#define DEPRECATED_ATTR __declspec(deprecated)
|
||||
#else // _WIN32
|
||||
#define EXPORT_ATTR __attribute__((visibility("default")))
|
||||
#define IMPORT_ATTR __attribute__((visibility("default")))
|
||||
#define NO_EXPORT_ATTR __attribute__((visibility("hidden")))
|
||||
#define DEPRECATE_ATTR __attribute__((__deprecated__))
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef BENCHMARK_STATIC_DEFINE
|
||||
#define BENCHMARK_EXPORT
|
||||
#define BENCHMARK_NO_EXPORT
|
||||
#else // BENCHMARK_STATIC_DEFINE
|
||||
#ifndef BENCHMARK_EXPORT
|
||||
#ifdef benchmark_EXPORTS
|
||||
/* We are building this library */
|
||||
#define BENCHMARK_EXPORT EXPORT_ATTR
|
||||
#else // benchmark_EXPORTS
|
||||
/* We are using this library */
|
||||
#define BENCHMARK_EXPORT IMPORT_ATTR
|
||||
#endif // benchmark_EXPORTS
|
||||
#endif // !BENCHMARK_EXPORT
|
||||
|
||||
#ifndef BENCHMARK_NO_EXPORT
|
||||
#define BENCHMARK_NO_EXPORT NO_EXPORT_ATTR
|
||||
#endif // !BENCHMARK_NO_EXPORT
|
||||
#endif // BENCHMARK_STATIC_DEFINE
|
||||
|
||||
#ifndef BENCHMARK_DEPRECATED
|
||||
#define BENCHMARK_DEPRECATED DEPRECATE_ATTR
|
||||
#endif // BENCHMARK_DEPRECATED
|
||||
|
||||
#ifndef BENCHMARK_DEPRECATED_EXPORT
|
||||
#define BENCHMARK_DEPRECATED_EXPORT BENCHMARK_EXPORT BENCHMARK_DEPRECATED
|
||||
#endif // BENCHMARK_DEPRECATED_EXPORT
|
||||
|
||||
#ifndef BENCHMARK_DEPRECATED_NO_EXPORT
|
||||
#define BENCHMARK_DEPRECATED_NO_EXPORT BENCHMARK_NO_EXPORT BENCHMARK_DEPRECATED
|
||||
#endif // BENCHMARK_DEPRECATED_EXPORT
|
||||
|
||||
#endif /* BENCHMARK_EXPORT_H */
|
||||
136
thirdparty/benchmark/include/benchmark/macros.h
vendored
136
thirdparty/benchmark/include/benchmark/macros.h
vendored
@ -1,136 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_MACROS_H_
|
||||
#define BENCHMARK_MACROS_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
TypeName& operator=(const TypeName&) = delete
|
||||
|
||||
#ifdef BENCHMARK_HAS_CXX17
|
||||
#define BENCHMARK_UNUSED [[maybe_unused]]
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define BENCHMARK_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define BENCHMARK_UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#define BENCHMARK_DONT_OPTIMIZE __attribute__((optnone))
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
#define BENCHMARK_DONT_OPTIMIZE __attribute__((optimize(0)))
|
||||
#else
|
||||
#define BENCHMARK_DONT_OPTIMIZE
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER) && !defined(__clang__)
|
||||
#define BENCHMARK_ALWAYS_INLINE __forceinline
|
||||
#define __func__ __FUNCTION__
|
||||
#else
|
||||
#define BENCHMARK_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#define BENCHMARK_INTERNAL_TOSTRING2(x) #x
|
||||
#define BENCHMARK_INTERNAL_TOSTRING(x) BENCHMARK_INTERNAL_TOSTRING2(x)
|
||||
|
||||
#if (defined(__GNUC__) && !defined(__NVCC__) && !defined(__NVCOMPILER)) || \
|
||||
defined(__clang__)
|
||||
#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
|
||||
#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
|
||||
#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
||||
#define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("GCC diagnostic pop")
|
||||
#elif defined(__NVCOMPILER)
|
||||
#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
|
||||
#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
|
||||
#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
|
||||
_Pragma("diagnostic push") \
|
||||
_Pragma("diag_suppress deprecated_entity_with_custom_message")
|
||||
#define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("diagnostic pop")
|
||||
#elif defined(_MSC_VER)
|
||||
#define BENCHMARK_BUILTIN_EXPECT(x, y) x
|
||||
#define BENCHMARK_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
|
||||
#define BENCHMARK_WARNING_MSG(msg) \
|
||||
__pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
|
||||
__LINE__) ") : warning note: " msg))
|
||||
#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
|
||||
__pragma(warning(push)) __pragma(warning(disable : 4996))
|
||||
#define BENCHMARK_RESTORE_DEPRECATED_WARNING __pragma(warning(pop))
|
||||
#else
|
||||
#define BENCHMARK_BUILTIN_EXPECT(x, y) x
|
||||
#define BENCHMARK_DEPRECATED_MSG(msg)
|
||||
#define BENCHMARK_WARNING_MSG(msg) \
|
||||
__pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
|
||||
__LINE__) ") : warning note: " msg))
|
||||
#define BENCHMARK_DISABLE_DEPRECATED_WARNING
|
||||
#define BENCHMARK_RESTORE_DEPRECATED_WARNING
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || __has_builtin(__builtin_unreachable)
|
||||
#define BENCHMARK_UNREACHABLE() __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
#define BENCHMARK_UNREACHABLE() __assume(false)
|
||||
#else
|
||||
#define BENCHMARK_UNREACHABLE() ((void)0)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
|
||||
#elif defined(__powerpc64__)
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 128
|
||||
#elif defined(__aarch64__)
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
|
||||
#elif defined(__arm__)
|
||||
#if defined(__ARM_ARCH_5T__)
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 32
|
||||
#elif defined(__ARM_ARCH_7A__)
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BENCHMARK_INTERNAL_CACHELINE_SIZE
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED \
|
||||
__attribute__((aligned(BENCHMARK_INTERNAL_CACHELINE_SIZE)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED \
|
||||
__declspec(align(BENCHMARK_INTERNAL_CACHELINE_SIZE))
|
||||
#else
|
||||
#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED
|
||||
#endif
|
||||
|
||||
#endif // BENCHMARK_MACROS_H_
|
||||
@ -1,66 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_MANAGERS_H_
|
||||
#define BENCHMARK_MANAGERS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "benchmark/macros.h"
|
||||
#include "benchmark/types.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
class MemoryManager {
|
||||
public:
|
||||
static constexpr int64_t TombstoneValue = std::numeric_limits<int64_t>::max();
|
||||
|
||||
struct Result {
|
||||
Result()
|
||||
: num_allocs(0),
|
||||
max_bytes_used(0),
|
||||
total_allocated_bytes(TombstoneValue),
|
||||
net_heap_growth(TombstoneValue),
|
||||
memory_iterations(0) {}
|
||||
|
||||
int64_t num_allocs;
|
||||
int64_t max_bytes_used;
|
||||
int64_t total_allocated_bytes;
|
||||
int64_t net_heap_growth;
|
||||
IterationCount memory_iterations;
|
||||
};
|
||||
|
||||
virtual ~MemoryManager() {}
|
||||
virtual void Start() = 0;
|
||||
virtual void Stop(Result& result) = 0;
|
||||
};
|
||||
|
||||
BENCHMARK_EXPORT
|
||||
void RegisterMemoryManager(MemoryManager* memory_manager);
|
||||
|
||||
class ProfilerManager {
|
||||
public:
|
||||
virtual ~ProfilerManager() {}
|
||||
virtual void AfterSetupStart() = 0;
|
||||
virtual void BeforeTeardownStop() = 0;
|
||||
};
|
||||
|
||||
BENCHMARK_EXPORT
|
||||
void RegisterProfilerManager(ProfilerManager* profiler_manager);
|
||||
|
||||
} // namespace benchmark
|
||||
|
||||
#endif // BENCHMARK_MANAGERS_H_
|
||||
@ -1,258 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_REGISTRATION_H_
|
||||
#define BENCHMARK_REGISTRATION_H_
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "benchmark/macros.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
#define BENCHMARK_DISABLE_COUNTER_WARNING \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wunknown-warning-option\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wc2y-extensions\"")
|
||||
#define BENCHMARK_RESTORE_COUNTER_WARNING _Pragma("GCC diagnostic pop")
|
||||
#else
|
||||
#define BENCHMARK_DISABLE_COUNTER_WARNING
|
||||
#define BENCHMARK_RESTORE_COUNTER_WARNING
|
||||
#endif
|
||||
|
||||
BENCHMARK_DISABLE_COUNTER_WARNING
|
||||
#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0)
|
||||
#define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__
|
||||
#else
|
||||
#define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__
|
||||
#endif
|
||||
BENCHMARK_RESTORE_COUNTER_WARNING
|
||||
|
||||
#define BENCHMARK_PRIVATE_NAME(...) \
|
||||
BENCHMARK_PRIVATE_CONCAT(benchmark_uniq_, BENCHMARK_PRIVATE_UNIQUE_ID, \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c)
|
||||
#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
|
||||
#define BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method) \
|
||||
BaseClass##_##Method##_Benchmark
|
||||
|
||||
#define BENCHMARK_PRIVATE_DECLARE(n) \
|
||||
BENCHMARK_DISABLE_COUNTER_WARNING \
|
||||
static ::benchmark::Benchmark const* const BENCHMARK_PRIVATE_NAME(n) \
|
||||
BENCHMARK_RESTORE_COUNTER_WARNING BENCHMARK_UNUSED
|
||||
|
||||
#define BENCHMARK(...) \
|
||||
BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique< \
|
||||
::benchmark::internal::FunctionBenchmark>( \
|
||||
#__VA_ARGS__, \
|
||||
static_cast<::benchmark::internal::Function*>(__VA_ARGS__))))
|
||||
|
||||
#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
|
||||
#define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->Args({(a1), (a2)})
|
||||
#define BENCHMARK_WITH_UNIT(n, t) BENCHMARK(n)->Unit((t))
|
||||
#define BENCHMARK_RANGE(n, lo, hi) BENCHMARK(n)->Range((lo), (hi))
|
||||
#define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \
|
||||
BENCHMARK(n)->RangePair({{(l1), (h1)}, {(l2), (h2)}})
|
||||
|
||||
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
|
||||
BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique< \
|
||||
::benchmark::internal::FunctionBenchmark>( \
|
||||
#func "/" #test_case_name, \
|
||||
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
|
||||
|
||||
#define BENCHMARK_NAMED(func, test_case_name) \
|
||||
BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique< \
|
||||
::benchmark::internal::FunctionBenchmark>( \
|
||||
#func "/" #test_case_name, \
|
||||
static_cast<::benchmark::internal::Function*>(func))))
|
||||
|
||||
#define BENCHMARK_TEMPLATE1(n, a) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique< \
|
||||
::benchmark::internal::FunctionBenchmark>( \
|
||||
#n "<" #a ">", \
|
||||
static_cast<::benchmark::internal::Function*>(n<a>))))
|
||||
|
||||
#define BENCHMARK_TEMPLATE2(n, a, b) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique< \
|
||||
::benchmark::internal::FunctionBenchmark>( \
|
||||
#n "<" #a "," #b ">", \
|
||||
static_cast<::benchmark::internal::Function*>(n<a, b>))))
|
||||
|
||||
#define BENCHMARK_TEMPLATE(n, ...) \
|
||||
BENCHMARK_PRIVATE_DECLARE(n) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique< \
|
||||
::benchmark::internal::FunctionBenchmark>( \
|
||||
#n "<" #__VA_ARGS__ ">", \
|
||||
static_cast<::benchmark::internal::Function*>(n<__VA_ARGS__>))))
|
||||
|
||||
#define BENCHMARK_TEMPLATE1_CAPTURE(func, a, test_case_name, ...) \
|
||||
BENCHMARK_CAPTURE(func<a>, test_case_name, __VA_ARGS__)
|
||||
|
||||
#define BENCHMARK_TEMPLATE2_CAPTURE(func, a, b, test_case_name, ...) \
|
||||
BENCHMARK_PRIVATE_DECLARE(func) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique< \
|
||||
::benchmark::internal::FunctionBenchmark>( \
|
||||
#func "<" #a "," #b ">" \
|
||||
"/" #test_case_name, \
|
||||
[](::benchmark::State& st) { func<a, b>(st, __VA_ARGS__); })))
|
||||
|
||||
#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
class BaseClass##_##Method##_Benchmark : public BaseClass { \
|
||||
public: \
|
||||
BaseClass##_##Method##_Benchmark() { \
|
||||
this->SetName(#BaseClass "/" #Method); \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
void BenchmarkCase(::benchmark::State&) override; \
|
||||
};
|
||||
|
||||
#define BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
|
||||
class BaseClass##_##Method##_Benchmark : public BaseClass<a> { \
|
||||
public: \
|
||||
BaseClass##_##Method##_Benchmark() { \
|
||||
this->SetName(#BaseClass "<" #a ">/" #Method); \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
void BenchmarkCase(::benchmark::State&) override; \
|
||||
};
|
||||
|
||||
#define BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
|
||||
class BaseClass##_##Method##_Benchmark : public BaseClass<a, b> { \
|
||||
public: \
|
||||
BaseClass##_##Method##_Benchmark() { \
|
||||
this->SetName(#BaseClass "<" #a "," #b ">/" #Method); \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
void BenchmarkCase(::benchmark::State&) override; \
|
||||
};
|
||||
|
||||
#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, ...) \
|
||||
class BaseClass##_##Method##_Benchmark : public BaseClass<__VA_ARGS__> { \
|
||||
public: \
|
||||
BaseClass##_##Method##_Benchmark() { \
|
||||
this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
void BenchmarkCase(::benchmark::State&) override; \
|
||||
};
|
||||
|
||||
#define BENCHMARK_DEFINE_F(BaseClass, Method) \
|
||||
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) \
|
||||
BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
|
||||
void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_TEMPLATE2_DEFINE_F(BaseClass, Method, a, b) \
|
||||
BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
|
||||
void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, ...) \
|
||||
BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
|
||||
void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_REGISTER_F(BaseClass, Method) \
|
||||
BENCHMARK_PRIVATE_REGISTER_F(BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method))
|
||||
|
||||
#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
|
||||
BENCHMARK_PRIVATE_DECLARE(TestName) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique<TestName>()))
|
||||
|
||||
#define BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F(BaseClass, Method) \
|
||||
BaseClass##_##Method##_BenchmarkTemplate
|
||||
|
||||
#define BENCHMARK_TEMPLATE_METHOD_F(BaseClass, Method) \
|
||||
template <class... Args> \
|
||||
class BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F(BaseClass, Method) \
|
||||
: public BaseClass<Args...> { \
|
||||
protected: \
|
||||
using Base = BaseClass<Args...>; \
|
||||
void BenchmarkCase(::benchmark::State&) override; \
|
||||
}; \
|
||||
template <class... Args> \
|
||||
void BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F( \
|
||||
BaseClass, Method)<Args...>::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_TEMPLATE_PRIVATE_INSTANTIATE_F(BaseClass, Method, \
|
||||
UniqueName, ...) \
|
||||
class UniqueName : public BENCHMARK_TEMPLATE_PRIVATE_CONCAT_NAME_F( \
|
||||
BaseClass, Method)<__VA_ARGS__> { \
|
||||
public: \
|
||||
UniqueName() { this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); } \
|
||||
}; \
|
||||
BENCHMARK_PRIVATE_DECLARE(BaseClass##_##Method##_Benchmark) = \
|
||||
(::benchmark::internal::RegisterBenchmarkInternal( \
|
||||
::benchmark::internal::make_unique<UniqueName>()))
|
||||
|
||||
#define BENCHMARK_TEMPLATE_INSTANTIATE_F(BaseClass, Method, ...) \
|
||||
BENCHMARK_DISABLE_COUNTER_WARNING \
|
||||
BENCHMARK_TEMPLATE_PRIVATE_INSTANTIATE_F( \
|
||||
BaseClass, Method, BENCHMARK_PRIVATE_NAME(BaseClass##Method), \
|
||||
__VA_ARGS__) \
|
||||
BENCHMARK_RESTORE_COUNTER_WARNING
|
||||
|
||||
#define BENCHMARK_F(BaseClass, Method) \
|
||||
BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
|
||||
BENCHMARK_REGISTER_F(BaseClass, Method); \
|
||||
void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) \
|
||||
BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
|
||||
BENCHMARK_REGISTER_F(BaseClass, Method); \
|
||||
void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_TEMPLATE2_F(BaseClass, Method, a, b) \
|
||||
BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
|
||||
BENCHMARK_REGISTER_F(BaseClass, Method); \
|
||||
void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...) \
|
||||
BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
|
||||
void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
|
||||
|
||||
#define BENCHMARK_MAIN() \
|
||||
int main(int argc, char** argv) { \
|
||||
benchmark::MaybeReenterWithoutASLR(argc, argv); \
|
||||
char arg0_default[] = "benchmark"; \
|
||||
char* args_default = reinterpret_cast<char*>(arg0_default); \
|
||||
if (!argv) { \
|
||||
argc = 1; \
|
||||
argv = &args_default; \
|
||||
} \
|
||||
::benchmark::Initialize(&argc, argv); \
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \
|
||||
::benchmark::RunSpecifiedBenchmarks(); \
|
||||
::benchmark::Shutdown(); \
|
||||
return 0; \
|
||||
} \
|
||||
int main(int, char**)
|
||||
|
||||
#endif // BENCHMARK_REGISTRATION_H_
|
||||
238
thirdparty/benchmark/include/benchmark/reporter.h
vendored
238
thirdparty/benchmark/include/benchmark/reporter.h
vendored
@ -1,238 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_REPORTER_H_
|
||||
#define BENCHMARK_REPORTER_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
// C4251: <symbol> needs to have dll-interface to be used by clients of class
|
||||
#pragma warning(disable : 4251)
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/counter.h"
|
||||
#include "benchmark/macros.h"
|
||||
#include "benchmark/managers.h"
|
||||
#include "benchmark/statistics.h"
|
||||
#include "benchmark/sysinfo.h"
|
||||
#include "benchmark/types.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
struct BENCHMARK_EXPORT BenchmarkName {
|
||||
std::string function_name;
|
||||
std::string args;
|
||||
std::string min_time;
|
||||
std::string min_warmup_time;
|
||||
std::string iterations;
|
||||
std::string repetitions;
|
||||
std::string time_type;
|
||||
std::string threads;
|
||||
|
||||
std::string str() const;
|
||||
};
|
||||
|
||||
class BENCHMARK_EXPORT BenchmarkReporter {
|
||||
public:
|
||||
struct Context {
|
||||
CPUInfo const& cpu_info;
|
||||
SystemInfo const& sys_info;
|
||||
size_t name_field_width = 0;
|
||||
static const char* executable_name;
|
||||
Context();
|
||||
};
|
||||
|
||||
struct BENCHMARK_EXPORT Run {
|
||||
static const int64_t no_repetition_index = -1;
|
||||
enum RunType { RT_Iteration, RT_Aggregate };
|
||||
|
||||
Run()
|
||||
: run_type(RT_Iteration),
|
||||
aggregate_unit(kTime),
|
||||
skipped(internal::NotSkipped),
|
||||
iterations(1),
|
||||
threads(1),
|
||||
time_unit(kNanosecond),
|
||||
real_accumulated_time(0),
|
||||
cpu_accumulated_time(0),
|
||||
max_heapbytes_used(0),
|
||||
use_real_time_for_initial_big_o(false),
|
||||
complexity(oNone),
|
||||
complexity_lambda(),
|
||||
complexity_n(0),
|
||||
statistics(),
|
||||
report_big_o(false),
|
||||
report_rms(false),
|
||||
allocs_per_iter(0.0) {}
|
||||
|
||||
std::string benchmark_name() const;
|
||||
BenchmarkName run_name;
|
||||
int64_t family_index;
|
||||
int64_t per_family_instance_index;
|
||||
RunType run_type;
|
||||
std::string aggregate_name;
|
||||
StatisticUnit aggregate_unit;
|
||||
std::string report_label;
|
||||
internal::Skipped skipped;
|
||||
std::string skip_message;
|
||||
|
||||
IterationCount iterations;
|
||||
int64_t threads;
|
||||
int64_t repetition_index;
|
||||
int64_t repetitions;
|
||||
TimeUnit time_unit;
|
||||
double real_accumulated_time;
|
||||
double cpu_accumulated_time;
|
||||
|
||||
double GetAdjustedRealTime() const;
|
||||
double GetAdjustedCPUTime() const;
|
||||
|
||||
double max_heapbytes_used;
|
||||
bool use_real_time_for_initial_big_o;
|
||||
BigO complexity;
|
||||
BigOFunc* complexity_lambda;
|
||||
ComplexityN complexity_n;
|
||||
const std::vector<internal::Statistics>* statistics;
|
||||
bool report_big_o;
|
||||
bool report_rms;
|
||||
UserCounters counters;
|
||||
MemoryManager::Result memory_result;
|
||||
double allocs_per_iter;
|
||||
};
|
||||
|
||||
struct PerFamilyRunReports {
|
||||
PerFamilyRunReports() : num_runs_total(0), num_runs_done(0) {}
|
||||
int num_runs_total;
|
||||
int num_runs_done;
|
||||
std::vector<BenchmarkReporter::Run> Runs;
|
||||
};
|
||||
|
||||
BenchmarkReporter();
|
||||
virtual bool ReportContext(const Context& context) = 0;
|
||||
virtual void ReportRunsConfig(double /*min_time*/,
|
||||
bool /*has_explicit_iters*/,
|
||||
IterationCount /*iters*/) {}
|
||||
virtual void ReportRuns(const std::vector<Run>& report) = 0;
|
||||
virtual void Finalize() {}
|
||||
|
||||
void SetOutputStream(std::ostream* out) {
|
||||
assert(out);
|
||||
output_stream_ = out;
|
||||
}
|
||||
void SetErrorStream(std::ostream* err) {
|
||||
assert(err);
|
||||
error_stream_ = err;
|
||||
}
|
||||
std::ostream& GetOutputStream() const { return *output_stream_; }
|
||||
std::ostream& GetErrorStream() const { return *error_stream_; }
|
||||
virtual ~BenchmarkReporter();
|
||||
static void PrintBasicContext(std::ostream* out, Context const& context);
|
||||
|
||||
private:
|
||||
std::ostream* output_stream_;
|
||||
std::ostream* error_stream_;
|
||||
};
|
||||
|
||||
class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter {
|
||||
public:
|
||||
enum OutputOptions {
|
||||
OO_None = 0,
|
||||
OO_Color = 1,
|
||||
OO_Tabular = 2,
|
||||
OO_ColorTabular = OO_Color | OO_Tabular,
|
||||
OO_Defaults = OO_ColorTabular
|
||||
};
|
||||
explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults)
|
||||
: output_options_(opts_), name_field_width_(0), printed_header_(false) {}
|
||||
|
||||
bool ReportContext(const Context& context) override;
|
||||
void ReportRuns(const std::vector<Run>& reports) override;
|
||||
|
||||
protected:
|
||||
virtual void PrintRunData(const Run& result);
|
||||
virtual void PrintHeader(const Run& run);
|
||||
|
||||
OutputOptions output_options_;
|
||||
size_t name_field_width_;
|
||||
UserCounters prev_counters_;
|
||||
bool printed_header_;
|
||||
};
|
||||
|
||||
class BENCHMARK_EXPORT JSONReporter : public BenchmarkReporter {
|
||||
public:
|
||||
JSONReporter() : first_report_(true) {}
|
||||
bool ReportContext(const Context& context) override;
|
||||
void ReportRuns(const std::vector<Run>& reports) override;
|
||||
void Finalize() override;
|
||||
|
||||
private:
|
||||
void PrintRunData(const Run& run);
|
||||
bool first_report_;
|
||||
};
|
||||
|
||||
class BENCHMARK_EXPORT BENCHMARK_DEPRECATED_MSG(
|
||||
"The CSV Reporter will be removed in a future release") CSVReporter
|
||||
: public BenchmarkReporter {
|
||||
public:
|
||||
CSVReporter() : printed_header_(false) {}
|
||||
bool ReportContext(const Context& context) override;
|
||||
void ReportRuns(const std::vector<Run>& reports) override;
|
||||
|
||||
private:
|
||||
void PrintRunData(const Run& run);
|
||||
bool printed_header_;
|
||||
std::set<std::string> user_counter_names_;
|
||||
};
|
||||
|
||||
inline const char* GetTimeUnitString(TimeUnit unit) {
|
||||
switch (unit) {
|
||||
case kSecond:
|
||||
return "s";
|
||||
case kMillisecond:
|
||||
return "ms";
|
||||
case kMicrosecond:
|
||||
return "us";
|
||||
case kNanosecond:
|
||||
return "ns";
|
||||
}
|
||||
BENCHMARK_UNREACHABLE();
|
||||
}
|
||||
|
||||
inline double GetTimeUnitMultiplier(TimeUnit unit) {
|
||||
switch (unit) {
|
||||
case kSecond:
|
||||
return 1;
|
||||
case kMillisecond:
|
||||
return 1e3;
|
||||
case kMicrosecond:
|
||||
return 1e6;
|
||||
case kNanosecond:
|
||||
return 1e9;
|
||||
}
|
||||
BENCHMARK_UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace benchmark
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BENCHMARK_REPORTER_H_
|
||||
282
thirdparty/benchmark/include/benchmark/state.h
vendored
282
thirdparty/benchmark/include/benchmark/state.h
vendored
@ -1,282 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_STATE_H_
|
||||
#define BENCHMARK_STATE_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4251 4324)
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/counter.h"
|
||||
#include "benchmark/macros.h"
|
||||
#include "benchmark/statistics.h"
|
||||
#include "benchmark/types.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
namespace internal {
|
||||
class BenchmarkInstance;
|
||||
class ThreadTimer;
|
||||
class ThreadManager;
|
||||
class PerfCountersMeasurement;
|
||||
} // namespace internal
|
||||
|
||||
class ProfilerManager;
|
||||
|
||||
class BENCHMARK_EXPORT BENCHMARK_INTERNAL_CACHELINE_ALIGNED State {
|
||||
public:
|
||||
struct StateIterator;
|
||||
friend struct StateIterator;
|
||||
|
||||
inline BENCHMARK_ALWAYS_INLINE StateIterator begin();
|
||||
inline BENCHMARK_ALWAYS_INLINE StateIterator end();
|
||||
|
||||
inline bool KeepRunning();
|
||||
|
||||
inline bool KeepRunningBatch(IterationCount n);
|
||||
|
||||
void PauseTiming();
|
||||
|
||||
void ResumeTiming();
|
||||
|
||||
void SkipWithMessage(const std::string& msg);
|
||||
|
||||
void SkipWithError(const std::string& msg);
|
||||
|
||||
bool skipped() const { return internal::NotSkipped != skipped_; }
|
||||
|
||||
bool error_occurred() const { return internal::SkippedWithError == skipped_; }
|
||||
|
||||
void SetIterationTime(double seconds);
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
void SetBytesProcessed(int64_t bytes) {
|
||||
counters["bytes_per_second"] =
|
||||
Counter(static_cast<double>(bytes), Counter::kIsRate, Counter::kIs1024);
|
||||
}
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
int64_t bytes_processed() const {
|
||||
if (counters.find("bytes_per_second") != counters.end())
|
||||
return static_cast<int64_t>(counters.at("bytes_per_second"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
void SetComplexityN(ComplexityN complexity_n) {
|
||||
complexity_n_ = complexity_n;
|
||||
}
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
ComplexityN complexity_length_n() const { return complexity_n_; }
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
void SetItemsProcessed(int64_t items) {
|
||||
counters["items_per_second"] =
|
||||
Counter(static_cast<double>(items), benchmark::Counter::kIsRate);
|
||||
}
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
int64_t items_processed() const {
|
||||
if (counters.find("items_per_second") != counters.end())
|
||||
return static_cast<int64_t>(counters.at("items_per_second"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetLabel(const std::string& label);
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
int64_t range(std::size_t pos = 0) const {
|
||||
assert(range_.size() > pos);
|
||||
return range_[pos];
|
||||
}
|
||||
|
||||
BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
|
||||
int64_t range_x() const { return range(0); }
|
||||
|
||||
BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead")
|
||||
int64_t range_y() const { return range(1); }
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
int threads() const { return threads_; }
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
int thread_index() const { return thread_index_; }
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
IterationCount iterations() const {
|
||||
if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
|
||||
return 0;
|
||||
}
|
||||
return max_iterations - total_iterations_ + batch_leftover_;
|
||||
}
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
std::string name() const { return name_; }
|
||||
|
||||
size_t range_size() const { return range_.size(); }
|
||||
|
||||
private:
|
||||
IterationCount total_iterations_;
|
||||
|
||||
IterationCount batch_leftover_;
|
||||
|
||||
public:
|
||||
const IterationCount max_iterations;
|
||||
|
||||
private:
|
||||
bool started_;
|
||||
bool finished_;
|
||||
internal::Skipped skipped_;
|
||||
|
||||
std::vector<int64_t> range_;
|
||||
|
||||
ComplexityN complexity_n_;
|
||||
|
||||
public:
|
||||
UserCounters counters;
|
||||
|
||||
private:
|
||||
State(std::string name, IterationCount max_iters,
|
||||
const std::vector<int64_t>& ranges, int thread_i, int n_threads,
|
||||
internal::ThreadTimer* timer, internal::ThreadManager* manager,
|
||||
internal::PerfCountersMeasurement* perf_counters_measurement,
|
||||
ProfilerManager* profiler_manager);
|
||||
|
||||
void StartKeepRunning();
|
||||
inline bool KeepRunningInternal(IterationCount n, bool is_batch);
|
||||
void FinishKeepRunning();
|
||||
|
||||
const std::string name_;
|
||||
const int thread_index_;
|
||||
const int threads_;
|
||||
|
||||
internal::ThreadTimer* const timer_;
|
||||
internal::ThreadManager* const manager_;
|
||||
internal::PerfCountersMeasurement* const perf_counters_measurement_;
|
||||
ProfilerManager* const profiler_manager_;
|
||||
|
||||
friend class internal::BenchmarkInstance;
|
||||
};
|
||||
|
||||
inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() {
|
||||
return KeepRunningInternal(1, /*is_batch=*/false);
|
||||
}
|
||||
|
||||
inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(IterationCount n) {
|
||||
return KeepRunningInternal(n, /*is_batch=*/true);
|
||||
}
|
||||
|
||||
inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(IterationCount n,
|
||||
bool is_batch) {
|
||||
assert(n > 0);
|
||||
assert(is_batch || n == 1);
|
||||
if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) {
|
||||
total_iterations_ -= n;
|
||||
return true;
|
||||
}
|
||||
if (!started_) {
|
||||
StartKeepRunning();
|
||||
if (!skipped() && total_iterations_ >= n) {
|
||||
total_iterations_ -= n;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (is_batch && total_iterations_ != 0) {
|
||||
batch_leftover_ = n - total_iterations_;
|
||||
total_iterations_ = 0;
|
||||
return true;
|
||||
}
|
||||
FinishKeepRunning();
|
||||
return false;
|
||||
}
|
||||
|
||||
struct State::StateIterator {
|
||||
struct BENCHMARK_UNUSED Value {};
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Value value_type;
|
||||
typedef Value reference;
|
||||
typedef Value pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
private:
|
||||
friend class State;
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
StateIterator() : cached_(0), parent_() {}
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
explicit StateIterator(State* st)
|
||||
: cached_(st->skipped() ? 0 : st->max_iterations), parent_(st) {}
|
||||
|
||||
public:
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
Value operator*() const { return Value(); }
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
StateIterator& operator++() {
|
||||
assert(cached_ > 0);
|
||||
--cached_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BENCHMARK_ALWAYS_INLINE
|
||||
bool operator!=(StateIterator const&) const {
|
||||
if (BENCHMARK_BUILTIN_EXPECT(cached_ != 0, true)) return true;
|
||||
parent_->FinishKeepRunning();
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
IterationCount cached_;
|
||||
State* const parent_;
|
||||
};
|
||||
|
||||
inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::begin() {
|
||||
return StateIterator(this);
|
||||
}
|
||||
inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::end() {
|
||||
StartKeepRunning();
|
||||
return StateIterator();
|
||||
}
|
||||
|
||||
class ScopedPauseTiming {
|
||||
public:
|
||||
explicit ScopedPauseTiming(State& state) : state_(state) {
|
||||
state_.PauseTiming();
|
||||
}
|
||||
~ScopedPauseTiming() { state_.ResumeTiming(); }
|
||||
|
||||
ScopedPauseTiming(const ScopedPauseTiming&) = delete;
|
||||
void operator=(const ScopedPauseTiming&) = delete;
|
||||
|
||||
ScopedPauseTiming(ScopedPauseTiming&&) = delete;
|
||||
void operator=(ScopedPauseTiming&&) = delete;
|
||||
|
||||
private:
|
||||
State& state_;
|
||||
};
|
||||
|
||||
} // namespace benchmark
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BENCHMARK_STATE_H_
|
||||
@ -1,65 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_STATISTICS_H_
|
||||
#define BENCHMARK_STATISTICS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/types.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };
|
||||
|
||||
typedef int64_t ComplexityN;
|
||||
|
||||
enum StatisticUnit { kTime, kPercentage };
|
||||
|
||||
typedef double(BigOFunc)(ComplexityN);
|
||||
|
||||
typedef double(StatisticsFunc)(const std::vector<double>&);
|
||||
|
||||
namespace internal {
|
||||
struct Statistics {
|
||||
std::string name_;
|
||||
StatisticsFunc* compute_;
|
||||
StatisticUnit unit_;
|
||||
|
||||
Statistics(const std::string& name, StatisticsFunc* compute,
|
||||
StatisticUnit unit = kTime)
|
||||
: name_(name), compute_(compute), unit_(unit) {}
|
||||
};
|
||||
|
||||
enum AggregationReportMode : unsigned {
|
||||
ARM_Unspecified = 0,
|
||||
ARM_Default = 1U << 0U,
|
||||
ARM_FileReportAggregatesOnly = 1U << 1U,
|
||||
ARM_DisplayReportAggregatesOnly = 1U << 2U,
|
||||
ARM_ReportAggregatesOnly =
|
||||
ARM_FileReportAggregatesOnly | ARM_DisplayReportAggregatesOnly
|
||||
};
|
||||
|
||||
enum Skipped : unsigned {
|
||||
NotSkipped = 0,
|
||||
SkippedWithMessage,
|
||||
SkippedWithError
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace benchmark
|
||||
|
||||
#endif // BENCHMARK_STATISTICS_H_
|
||||
71
thirdparty/benchmark/include/benchmark/sysinfo.h
vendored
71
thirdparty/benchmark/include/benchmark/sysinfo.h
vendored
@ -1,71 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_SYSINFO_H_
|
||||
#define BENCHMARK_SYSINFO_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4251)
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/macros.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
struct BENCHMARK_EXPORT CPUInfo {
|
||||
struct CacheInfo {
|
||||
std::string type;
|
||||
int level;
|
||||
int size;
|
||||
int num_sharing;
|
||||
};
|
||||
|
||||
enum Scaling { UNKNOWN, ENABLED, DISABLED };
|
||||
|
||||
int num_cpus;
|
||||
Scaling scaling;
|
||||
double cycles_per_second;
|
||||
std::vector<CacheInfo> caches;
|
||||
std::vector<double> load_avg;
|
||||
|
||||
static const CPUInfo& Get();
|
||||
|
||||
private:
|
||||
CPUInfo();
|
||||
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo);
|
||||
};
|
||||
|
||||
struct BENCHMARK_EXPORT SystemInfo {
|
||||
enum class ASLR { UNKNOWN, ENABLED, DISABLED };
|
||||
|
||||
std::string name;
|
||||
ASLR ASLRStatus;
|
||||
static const SystemInfo& Get();
|
||||
|
||||
private:
|
||||
SystemInfo();
|
||||
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo);
|
||||
};
|
||||
|
||||
} // namespace benchmark
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BENCHMARK_SYSINFO_H_
|
||||
50
thirdparty/benchmark/include/benchmark/types.h
vendored
50
thirdparty/benchmark/include/benchmark/types.h
vendored
@ -1,50 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_TYPES_H_
|
||||
#define BENCHMARK_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "benchmark/export.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
namespace internal {
|
||||
#if (__cplusplus < 201402L || (defined(_MSC_VER) && _MSVC_LANG < 201402L))
|
||||
template <typename T, typename... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
#else
|
||||
using ::std::make_unique;
|
||||
#endif
|
||||
} // namespace internal
|
||||
|
||||
class BenchmarkReporter;
|
||||
class State;
|
||||
|
||||
using IterationCount = int64_t;
|
||||
|
||||
using callback_function = std::function<void(const benchmark::State&)>;
|
||||
|
||||
enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond, kSecond };
|
||||
|
||||
} // namespace benchmark
|
||||
|
||||
#endif // BENCHMARK_TYPES_H_
|
||||
152
thirdparty/benchmark/include/benchmark/utils.h
vendored
152
thirdparty/benchmark/include/benchmark/utils.h
vendored
@ -1,152 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BENCHMARK_UTILS_H_
|
||||
#define BENCHMARK_UTILS_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "benchmark/export.h"
|
||||
#include "benchmark/macros.h"
|
||||
|
||||
namespace benchmark {
|
||||
|
||||
namespace internal {
|
||||
BENCHMARK_EXPORT void UseCharPointer(char const volatile*);
|
||||
}
|
||||
|
||||
#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \
|
||||
defined(__EMSCRIPTEN__)
|
||||
#define BENCHMARK_HAS_NO_INLINE_ASSEMBLY
|
||||
#endif
|
||||
|
||||
inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
|
||||
std::atomic_signal_fence(std::memory_order_acq_rel);
|
||||
}
|
||||
|
||||
#define BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG \
|
||||
"DoNotOptimize(T const&) can permit undesired compiler optimizations. " \
|
||||
"Pass a non-const lvalue instead; if the argument is an expression result, " \
|
||||
"store it in a local variable first."
|
||||
|
||||
#ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
|
||||
#if !defined(__GNUC__) || defined(__llvm__) || defined(__INTEL_COMPILER)
|
||||
template <class Tp>
|
||||
BENCHMARK_DEPRECATED_MSG(BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG)
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
|
||||
asm volatile("" : : "r,m"(value) : "memory");
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
|
||||
#if defined(__clang__)
|
||||
asm volatile("" : "+r,m"(value) : : "memory");
|
||||
#else
|
||||
asm volatile("" : "+m,r"(value) : : "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
|
||||
#if defined(__clang__)
|
||||
asm volatile("" : "+r,m"(value) : : "memory");
|
||||
#else
|
||||
asm volatile("" : "+m,r"(value) : : "memory");
|
||||
#endif
|
||||
}
|
||||
#elif (__GNUC__ >= 5)
|
||||
template <class Tp>
|
||||
BENCHMARK_DEPRECATED_MSG(BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG)
|
||||
inline BENCHMARK_ALWAYS_INLINE
|
||||
typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
|
||||
(sizeof(Tp) <= sizeof(Tp*))>::type
|
||||
DoNotOptimize(Tp const& value) {
|
||||
asm volatile("" : : "r,m"(value) : "memory");
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
BENCHMARK_DEPRECATED_MSG(BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG)
|
||||
inline BENCHMARK_ALWAYS_INLINE
|
||||
typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
|
||||
(sizeof(Tp) > sizeof(Tp*))>::type
|
||||
DoNotOptimize(Tp const& value) {
|
||||
asm volatile("" : : "m"(value) : "memory");
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE
|
||||
typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
|
||||
(sizeof(Tp) <= sizeof(Tp*))>::type
|
||||
DoNotOptimize(Tp& value) {
|
||||
asm volatile("" : "+m,r"(value) : : "memory");
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE
|
||||
typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
|
||||
(sizeof(Tp) > sizeof(Tp*))>::type
|
||||
DoNotOptimize(Tp& value) {
|
||||
asm volatile("" : "+m"(value) : : "memory");
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE
|
||||
typename std::enable_if<std::is_trivially_copyable<Tp>::value &&
|
||||
(sizeof(Tp) <= sizeof(Tp*))>::type
|
||||
DoNotOptimize(Tp&& value) {
|
||||
asm volatile("" : "+m,r"(value) : : "memory");
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE
|
||||
typename std::enable_if<!std::is_trivially_copyable<Tp>::value ||
|
||||
(sizeof(Tp) > sizeof(Tp*))>::type
|
||||
DoNotOptimize(Tp&& value) {
|
||||
asm volatile("" : "+m"(value) : : "memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
template <class Tp>
|
||||
BENCHMARK_DEPRECATED_MSG(BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG)
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
|
||||
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
|
||||
ClobberMemory();
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
|
||||
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
|
||||
ClobberMemory();
|
||||
}
|
||||
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
|
||||
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
|
||||
ClobberMemory();
|
||||
}
|
||||
#else
|
||||
template <class Tp>
|
||||
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
|
||||
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG
|
||||
|
||||
} // end namespace benchmark
|
||||
|
||||
#endif // BENCHMARK_UTILS_H_
|
||||
76
thirdparty/benchmark/pyproject.toml
vendored
76
thirdparty/benchmark/pyproject.toml
vendored
@ -1,76 +0,0 @@
|
||||
[build-system]
|
||||
requires = ["setuptools"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "google_benchmark"
|
||||
description = "A library to benchmark code snippets."
|
||||
requires-python = ">=3.10"
|
||||
license = "Apache-2.0"
|
||||
keywords = ["benchmark"]
|
||||
|
||||
authors = [{ name = "Google", email = "benchmark-discuss@googlegroups.com" }]
|
||||
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: Science/Research",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Software Development :: Testing",
|
||||
"Topic :: System :: Benchmark",
|
||||
]
|
||||
|
||||
dynamic = ["readme", "version"]
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["pre-commit>=3.3.3"]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/google/benchmark"
|
||||
Documentation = "https://github.com/google/benchmark/tree/main/docs"
|
||||
Repository = "https://github.com/google/benchmark.git"
|
||||
Discord = "https://discord.gg/cz7UX7wKC2"
|
||||
|
||||
[tool.setuptools]
|
||||
package-dir = { "" = "bindings/python" }
|
||||
zip-safe = false
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["bindings/python"]
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
readme = { file = "README.md", content-type = "text/markdown" }
|
||||
version = { attr = "google_benchmark.__version__" }
|
||||
|
||||
[tool.mypy]
|
||||
check_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
pretty = true
|
||||
python_version = "3.11"
|
||||
strict_optional = false
|
||||
warn_unreachable = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = ["yaml"]
|
||||
ignore_missing_imports = true
|
||||
|
||||
[tool.ruff]
|
||||
# explicitly tell ruff the source directory to correctly identify first-party package.
|
||||
src = ["bindings/python"]
|
||||
|
||||
line-length = 80
|
||||
target-version = "py311"
|
||||
|
||||
[tool.ruff.lint]
|
||||
# Enable pycodestyle (`E`, `W`), Pyflakes (`F`), and isort (`I`) codes by default.
|
||||
select = ["ASYNC", "B", "C4", "C90", "E", "F", "I", "PERF", "PIE", "PT018", "RUF", "SIM", "UP", "W"]
|
||||
ignore = [
|
||||
"PLW2901", # redefined-loop-name
|
||||
"UP031", # printf-string-formatting
|
||||
]
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
combine-as-imports = true
|
||||
171
thirdparty/benchmark/setup.py
vendored
171
thirdparty/benchmark/setup.py
vendored
@ -1,171 +0,0 @@
|
||||
import contextlib
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import setuptools
|
||||
from setuptools.command import build_ext
|
||||
|
||||
IS_WINDOWS = platform.system() == "Windows"
|
||||
IS_MAC = platform.system() == "Darwin"
|
||||
IS_LINUX = platform.system() == "Linux"
|
||||
|
||||
# hardcoded SABI-related options. Requires that each Python interpreter
|
||||
# (hermetic or not) participating is of the same major-minor version.
|
||||
py_limited_api = sys.version_info >= (3, 12)
|
||||
options = {"bdist_wheel": {"py_limited_api": "cp312"}} if py_limited_api else {}
|
||||
|
||||
|
||||
def is_cibuildwheel() -> bool:
|
||||
return os.getenv("CIBUILDWHEEL") is not None
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _maybe_patch_toolchains() -> Generator[None, None, None]:
|
||||
"""
|
||||
Patch rules_python toolchains to ignore root user error
|
||||
when run in a Docker container on Linux in cibuildwheel.
|
||||
"""
|
||||
|
||||
def fmt_toolchain_args(matchobj):
|
||||
suffix = "ignore_root_user_error = True"
|
||||
callargs = matchobj.group(1)
|
||||
# toolchain def is broken over multiple lines
|
||||
if callargs.endswith("\n"):
|
||||
callargs = callargs + " " + suffix + ",\n"
|
||||
# toolchain def is on one line.
|
||||
else:
|
||||
callargs = callargs + ", " + suffix
|
||||
return "python.toolchain(" + callargs + ")"
|
||||
|
||||
CIBW_LINUX = is_cibuildwheel() and IS_LINUX
|
||||
module_bazel = Path("MODULE.bazel")
|
||||
content: str = module_bazel.read_text()
|
||||
try:
|
||||
if CIBW_LINUX:
|
||||
module_bazel.write_text(
|
||||
re.sub(
|
||||
r"python.toolchain\(([\w\"\s,.=]*)\)",
|
||||
fmt_toolchain_args,
|
||||
content,
|
||||
)
|
||||
)
|
||||
yield
|
||||
finally:
|
||||
if CIBW_LINUX:
|
||||
module_bazel.write_text(content)
|
||||
|
||||
|
||||
class BazelExtension(setuptools.Extension):
|
||||
"""A C/C++ extension that is defined as a Bazel BUILD target."""
|
||||
|
||||
def __init__(self, name: str, bazel_target: str, **kwargs: Any):
|
||||
super().__init__(name=name, sources=[], **kwargs)
|
||||
|
||||
self.bazel_target = bazel_target
|
||||
stripped_target = bazel_target.split("//")[-1]
|
||||
self.relpath, self.target_name = stripped_target.split(":")
|
||||
|
||||
|
||||
class BuildBazelExtension(build_ext.build_ext):
|
||||
"""A command that runs Bazel to build a C/C++ extension."""
|
||||
|
||||
def run(self):
|
||||
for ext in self.extensions:
|
||||
self.bazel_build(ext)
|
||||
# explicitly call `bazel shutdown` for graceful exit
|
||||
self.spawn(["bazel", "shutdown"])
|
||||
|
||||
def copy_extensions_to_source(self):
|
||||
"""
|
||||
Copy generated extensions into the source tree.
|
||||
This is done in the ``bazel_build`` method, so it's not necessary to
|
||||
do again in the `build_ext` base class.
|
||||
"""
|
||||
|
||||
def bazel_build(self, ext: BazelExtension) -> None: # noqa: C901
|
||||
"""Runs the bazel build to create the package."""
|
||||
temp_path = Path(self.build_temp)
|
||||
|
||||
# We round to the minor version, which makes rules_python
|
||||
# look up the latest available patch version internally.
|
||||
python_version = "{}.{}".format(*sys.version_info[:2])
|
||||
|
||||
bazel_argv = [
|
||||
"bazel",
|
||||
"run",
|
||||
ext.bazel_target,
|
||||
f"--symlink_prefix={temp_path / 'bazel-'}",
|
||||
f"--compilation_mode={'dbg' if self.debug else 'opt'}",
|
||||
# C++17 is required by nanobind
|
||||
f"--cxxopt={'/std:c++17' if IS_WINDOWS else '-std=c++17'}",
|
||||
f"--@rules_python//python/config_settings:python_version={python_version}",
|
||||
]
|
||||
|
||||
if ext.py_limited_api:
|
||||
bazel_argv += ["--@nanobind_bazel//:py-limited-api=cp312"]
|
||||
|
||||
if IS_WINDOWS:
|
||||
# Link with python*.lib.
|
||||
for library_dir in self.library_dirs:
|
||||
bazel_argv.append("--linkopt=/LIBPATH:" + library_dir)
|
||||
elif IS_MAC:
|
||||
# C++17 needs macOS 10.14 at minimum
|
||||
bazel_argv.append("--macos_minimum_os=10.14")
|
||||
|
||||
with _maybe_patch_toolchains():
|
||||
self.spawn(bazel_argv)
|
||||
|
||||
if IS_WINDOWS:
|
||||
suffix = ".pyd"
|
||||
else:
|
||||
suffix = ".abi3.so" if ext.py_limited_api else ".so"
|
||||
|
||||
# copy the Bazel build artifacts into setuptools' libdir,
|
||||
# from where the wheel is built.
|
||||
pkgname = "google_benchmark"
|
||||
pythonroot = Path("bindings") / "python" / "google_benchmark"
|
||||
srcdir = temp_path / "bazel-bin" / pythonroot
|
||||
if not self.inplace:
|
||||
libdir = Path(self.build_lib) / pkgname
|
||||
else:
|
||||
build_py = self.get_finalized_command("build_py")
|
||||
libdir = Path(build_py.get_package_dir(pkgname))
|
||||
|
||||
for root, dirs, files in os.walk(srcdir, topdown=True):
|
||||
# exclude runfiles directories and children.
|
||||
dirs[:] = [d for d in dirs if "runfiles" not in d]
|
||||
|
||||
for f in files:
|
||||
fp = Path(f)
|
||||
should_copy = False
|
||||
# we do not want the bare .so file included
|
||||
# when building for ABI3, so we require a
|
||||
# full and exact match on the file extension.
|
||||
if "".join(fp.suffixes) == suffix or fp.suffix == ".pyi":
|
||||
should_copy = True
|
||||
elif Path(root) == srcdir and f == "py.typed":
|
||||
# copy py.typed, but only at the package root.
|
||||
should_copy = True
|
||||
|
||||
if should_copy:
|
||||
shutil.copyfile(root / fp, libdir / fp)
|
||||
|
||||
|
||||
setuptools.setup(
|
||||
cmdclass={"build_ext": BuildBazelExtension},
|
||||
package_data={"google_benchmark": ["py.typed", "*.pyi"]},
|
||||
ext_modules=[
|
||||
BazelExtension(
|
||||
name="google_benchmark._benchmark",
|
||||
bazel_target="//bindings/python/google_benchmark:benchmark_stubgen",
|
||||
py_limited_api=py_limited_api,
|
||||
)
|
||||
],
|
||||
options=options,
|
||||
)
|
||||
227
thirdparty/benchmark/src/CMakeLists.txt
vendored
227
thirdparty/benchmark/src/CMakeLists.txt
vendored
@ -1,227 +0,0 @@
|
||||
#Allow the source files to find headers in src /
|
||||
include(GNUInstallDirs)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
|
||||
if (DEFINED BENCHMARK_CXX_LINKER_FLAGS)
|
||||
list(APPEND CMAKE_SHARED_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
|
||||
list(APPEND CMAKE_MODULE_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
|
||||
endif()
|
||||
|
||||
file(GLOB
|
||||
SOURCE_FILES
|
||||
*.cc
|
||||
${PROJECT_SOURCE_DIR}/include/benchmark/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||
file(GLOB BENCHMARK_MAIN "benchmark_main.cc")
|
||||
foreach(item ${BENCHMARK_MAIN})
|
||||
list(REMOVE_ITEM SOURCE_FILES "${item}")
|
||||
endforeach()
|
||||
|
||||
add_library(benchmark ${SOURCE_FILES})
|
||||
add_library(benchmark::benchmark ALIAS benchmark)
|
||||
set_target_properties(benchmark PROPERTIES
|
||||
OUTPUT_NAME "benchmark"
|
||||
VERSION ${GENERIC_LIB_VERSION}
|
||||
SOVERSION ${GENERIC_LIB_SOVERSION}
|
||||
)
|
||||
target_include_directories(benchmark PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
)
|
||||
|
||||
set_property(
|
||||
SOURCE benchmark.cc
|
||||
APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
BENCHMARK_VERSION="${VERSION}"
|
||||
)
|
||||
|
||||
# libpfm, if available
|
||||
if (PFM_FOUND)
|
||||
target_link_libraries(benchmark PRIVATE PFM::libpfm)
|
||||
target_compile_definitions(benchmark PRIVATE -DHAVE_LIBPFM)
|
||||
install(
|
||||
FILES "${PROJECT_SOURCE_DIR}/cmake/Modules/FindPFM.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
# pthread affinity, if available
|
||||
if(HAVE_PTHREAD_AFFINITY)
|
||||
target_compile_definitions(benchmark PRIVATE -DBENCHMARK_HAS_PTHREAD_AFFINITY)
|
||||
endif()
|
||||
|
||||
target_link_libraries(benchmark PRIVATE ${BENCHMARK_CXX_LIBRARIES})
|
||||
|
||||
if(HAVE_LIB_RT)
|
||||
target_link_libraries(benchmark PRIVATE rt)
|
||||
endif(HAVE_LIB_RT)
|
||||
|
||||
|
||||
# We need extra libraries on Windows
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
target_link_libraries(benchmark PRIVATE shlwapi)
|
||||
endif()
|
||||
|
||||
# We need extra libraries on Solaris
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
target_link_libraries(benchmark PRIVATE kstat)
|
||||
endif()
|
||||
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(benchmark PUBLIC -DBENCHMARK_STATIC_DEFINE)
|
||||
endif()
|
||||
|
||||
# Benchmark main library
|
||||
add_library(benchmark_main "benchmark_main.cc")
|
||||
add_library(benchmark::benchmark_main ALIAS benchmark_main)
|
||||
set_target_properties(benchmark_main PROPERTIES
|
||||
OUTPUT_NAME "benchmark_main"
|
||||
VERSION ${GENERIC_LIB_VERSION}
|
||||
SOVERSION ${GENERIC_LIB_SOVERSION}
|
||||
DEFINE_SYMBOL benchmark_EXPORTS
|
||||
)
|
||||
target_link_libraries(benchmark_main PUBLIC benchmark::benchmark)
|
||||
|
||||
set(generated_dir "${PROJECT_BINARY_DIR}")
|
||||
|
||||
set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
|
||||
set(pkg_config "${generated_dir}/${PROJECT_NAME}.pc")
|
||||
set(pkg_config_main "${generated_dir}/${PROJECT_NAME}_main.pc")
|
||||
set(targets_to_export benchmark benchmark_main)
|
||||
set(targets_export_name "${PROJECT_NAME}Targets")
|
||||
|
||||
set(namespace "${PROJECT_NAME}::")
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
configure_package_config_file (
|
||||
${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in
|
||||
${project_config}
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
NO_SET_AND_CHECK_MACRO
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
)
|
||||
write_basic_package_version_file(
|
||||
"${version_config}" VERSION ${GENERIC_LIB_VERSION} COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
# Derive private link libraries from target
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
get_target_property(LINK_LIBS benchmark LINK_LIBRARIES)
|
||||
if(LINK_LIBS)
|
||||
set(BENCHMARK_PRIVATE_LINK_LIBRARIES "")
|
||||
foreach(LIB IN LISTS LINK_LIBS)
|
||||
if(NOT TARGET "${LIB}" AND LIB MATCHES "^[a-zA-Z0-9_.-]+$")
|
||||
list(APPEND BENCHMARK_PRIVATE_LINK_LIBRARIES "-l${LIB}")
|
||||
elseif(TARGET "${LIB}")
|
||||
get_target_property(_target_type "${LIB}" TYPE)
|
||||
if(_target_type MATCHES "^(UNKNOWN|STATIC|SHARED|MODULE)_LIBRARY$")
|
||||
get_target_property(_imported_loc "${LIB}" IMPORTED_LOCATION)
|
||||
if(_imported_loc)
|
||||
get_filename_component(_imported_dir "${_imported_loc}" DIRECTORY)
|
||||
get_filename_component(_imported_name "${_imported_loc}" NAME)
|
||||
string(REGEX REPLACE "^lib" "" _imported_name "${_imported_name}")
|
||||
string(REGEX REPLACE "\\.(so|a|dylib)([0-9.]*)$" "" _imported_name "${_imported_name}")
|
||||
list(APPEND BENCHMARK_PRIVATE_LINK_LIBRARIES "-L${_imported_dir}" "-l${_imported_name}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
string(JOIN " " BENCHMARK_PRIVATE_LINK_LIBRARIES ${BENCHMARK_PRIVATE_LINK_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(_cmake_path output_var install_dir path_prefix)
|
||||
if(IS_ABSOLUTE "${install_dir}")
|
||||
set("${output_var}" "${install_dir}" PARENT_SCOPE)
|
||||
else()
|
||||
# FIXME: Use cmake_path(APPEND) once the minimum CMake version is 3.20.
|
||||
set("${output_var}" "\${${path_prefix}}/${install_dir}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
_cmake_path(BENCHMARK_PKG_CONFIG_LIBDIR "${CMAKE_INSTALL_LIBDIR}" "exec_prefix")
|
||||
|
||||
_cmake_path(BENCHMARK_PKG_CONFIG_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}" "prefix")
|
||||
|
||||
configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark.pc.in" "${pkg_config}" @ONLY)
|
||||
|
||||
configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark_main.pc.in" "${pkg_config_main}" @ONLY)
|
||||
|
||||
export (
|
||||
TARGETS ${targets_to_export}
|
||||
NAMESPACE "${namespace}"
|
||||
FILE ${generated_dir}/${targets_export_name}.cmake
|
||||
)
|
||||
|
||||
if (BENCHMARK_ENABLE_INSTALL)
|
||||
# Install target (will install the library to specified CMAKE_INSTALL_PREFIX variable)
|
||||
install(
|
||||
TARGETS ${targets_to_export}
|
||||
EXPORT ${targets_export_name}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(
|
||||
DIRECTORY "${PROJECT_SOURCE_DIR}/include/benchmark"
|
||||
"${PROJECT_BINARY_DIR}/include/benchmark"
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING PATTERN "*.*h")
|
||||
|
||||
install(
|
||||
FILES "${project_config}" "${version_config}"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
|
||||
install(
|
||||
FILES "${pkg_config}" "${pkg_config_main}"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
install(
|
||||
EXPORT "${targets_export_name}"
|
||||
NAMESPACE "${namespace}"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
if (BENCHMARK_ENABLE_DOXYGEN)
|
||||
find_package(Doxygen REQUIRED)
|
||||
set(DOXYGEN_QUIET YES)
|
||||
set(DOXYGEN_RECURSIVE YES)
|
||||
set(DOXYGEN_GENERATE_HTML YES)
|
||||
set(DOXYGEN_GENERATE_MAN NO)
|
||||
set(DOXYGEN_MARKDOWN_SUPPORT YES)
|
||||
set(DOXYGEN_BUILTIN_STL_SUPPORT YES)
|
||||
set(DOXYGEN_EXTRACT_PACKAGE YES)
|
||||
set(DOXYGEN_EXTRACT_STATIC YES)
|
||||
set(DOXYGEN_SHOW_INCLUDE_FILES YES)
|
||||
set(DOXYGEN_BINARY_TOC YES)
|
||||
set(DOXYGEN_TOC_EXPAND YES)
|
||||
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "index.md")
|
||||
doxygen_add_docs(benchmark_doxygen
|
||||
docs
|
||||
include
|
||||
src
|
||||
ALL
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Building documentation with Doxygen.")
|
||||
if (BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_DOCS)
|
||||
install(
|
||||
DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html/"
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
endif()
|
||||
else()
|
||||
if (BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_DOCS)
|
||||
install(
|
||||
DIRECTORY "${PROJECT_SOURCE_DIR}/docs/"
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_INSTALL_PYTOOLSDIR "${CMAKE_INSTALL_DATADIR}/googlebenchmark/tools" CACHE PATH "")
|
||||
|
||||
if (BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_TOOLS)
|
||||
install(
|
||||
DIRECTORY "${PROJECT_SOURCE_DIR}/tools/"
|
||||
DESTINATION ${CMAKE_INSTALL_PYTOOLSDIR})
|
||||
endif()
|
||||
33
thirdparty/benchmark/src/arraysize.h
vendored
33
thirdparty/benchmark/src/arraysize.h
vendored
@ -1,33 +0,0 @@
|
||||
#ifndef BENCHMARK_ARRAYSIZE_H_
|
||||
#define BENCHMARK_ARRAYSIZE_H_
|
||||
|
||||
#include "internal_macros.h"
|
||||
|
||||
namespace benchmark {
|
||||
namespace internal {
|
||||
// The arraysize(arr) macro returns the # of elements in an array arr.
|
||||
// The expression is a compile-time constant, and therefore can be
|
||||
// used in defining new arrays, for example. If you use arraysize on
|
||||
// a pointer by mistake, you will get a compile-time error.
|
||||
//
|
||||
|
||||
// This template function declaration is used in defining arraysize.
|
||||
// Note that the function doesn't need an implementation, as we only
|
||||
// use its type.
|
||||
template <typename T, size_t N>
|
||||
char (&ArraySizeHelper(T (&array)[N]))[N];
|
||||
|
||||
// That gcc wants both of these prototypes seems mysterious. VC, for
|
||||
// its part, can't decide which to use (another mystery). Matching of
|
||||
// template overloads: the final frontier.
|
||||
#ifndef COMPILER_MSVC
|
||||
template <typename T, size_t N>
|
||||
char (&ArraySizeHelper(const T (&array)[N]))[N];
|
||||
#endif
|
||||
|
||||
#define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array)))
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace benchmark
|
||||
|
||||
#endif // BENCHMARK_ARRAYSIZE_H_
|
||||
920
thirdparty/benchmark/src/benchmark.cc
vendored
920
thirdparty/benchmark/src/benchmark.cc
vendored
@ -1,920 +0,0 @@
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "benchmark/registration.h"
|
||||
#include "benchmark/reporter.h"
|
||||
#include "benchmark/state.h"
|
||||
#include "benchmark/types.h"
|
||||
#include "benchmark_api_internal.h"
|
||||
#include "benchmark_runner.h"
|
||||
#include "internal_macros.h"
|
||||
|
||||
#ifndef BENCHMARK_OS_WINDOWS
|
||||
#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) && \
|
||||
!defined(BENCHMARK_OS_WASI)
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef BENCHMARK_OS_LINUX
|
||||
#include <sys/personality.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include "check.h"
|
||||
#include "colorprint.h"
|
||||
#include "commandlineflags.h"
|
||||
#include "complexity.h"
|
||||
#include "counter.h"
|
||||
#include "log.h"
|
||||
#include "mutex.h"
|
||||
#include "perf_counters.h"
|
||||
#include "re.h"
|
||||
#include "statistics.h"
|
||||
#include "string_util.h"
|
||||
#include "thread_manager.h"
|
||||
#include "thread_timer.h"
|
||||
|
||||
namespace benchmark {
|
||||
// Print a list of benchmarks. This option overrides all other options.
|
||||
BM_DEFINE_bool(benchmark_list_tests, false);
|
||||
|
||||
// A regular expression that specifies the set of benchmarks to execute. If
|
||||
// this flag is empty, or if this flag is the string \"all\", all benchmarks
|
||||
// linked into the binary are run.
|
||||
BM_DEFINE_string(benchmark_filter, "");
|
||||
|
||||
// Specification of how long to run the benchmark.
|
||||
//
|
||||
// It can be either an exact number of iterations (specified as `<integer>x`),
|
||||
// or a minimum number of seconds (specified as `<float>s`). If the latter
|
||||
// format (ie., min seconds) is used, the system may run the benchmark longer
|
||||
// until the results are considered significant.
|
||||
//
|
||||
// For backward compatibility, the `s` suffix may be omitted, in which case,
|
||||
// the specified number is interpreted as the number of seconds.
|
||||
//
|
||||
// For cpu-time based tests, this is the lower bound
|
||||
// on the total cpu time used by all threads that make up the test. For
|
||||
// real-time based tests, this is the lower bound on the elapsed time of the
|
||||
// benchmark execution, regardless of number of threads.
|
||||
BM_DEFINE_string(benchmark_min_time, kDefaultMinTimeStr);
|
||||
|
||||
// Minimum number of seconds a benchmark should be run before results should be
|
||||
// taken into account. This e.g can be necessary for benchmarks of code which
|
||||
// needs to fill some form of cache before performance is of interest.
|
||||
// Note: results gathered within this period are discarded and not used for
|
||||
// reported result.
|
||||
BM_DEFINE_double(benchmark_min_warmup_time, 0.0);
|
||||
|
||||
// The number of runs of each benchmark. If greater than 1, the mean and
|
||||
// standard deviation of the runs will be reported.
|
||||
BM_DEFINE_int32(benchmark_repetitions, 1);
|
||||
|
||||
// If enabled, forces each benchmark to execute exactly one iteration and one
|
||||
// repetition, bypassing any configured
|
||||
// MinTime()/MinWarmUpTime()/Iterations()/Repetitions()
|
||||
BM_DEFINE_bool(benchmark_dry_run, false);
|
||||
|
||||
// If set, enable random interleaving of repetitions of all benchmarks.
|
||||
// See http://github.com/google/benchmark/issues/1051 for details.
|
||||
BM_DEFINE_bool(benchmark_enable_random_interleaving, false);
|
||||
|
||||
// Report the result of each benchmark repetitions. When 'true' is specified
|
||||
// only the mean, standard deviation, and other statistics are reported for
|
||||
// repeated benchmarks. Affects all reporters.
|
||||
BM_DEFINE_bool(benchmark_report_aggregates_only, false);
|
||||
|
||||
// Display the result of each benchmark repetitions. When 'true' is specified
|
||||
// only the mean, standard deviation, and other statistics are displayed for
|
||||
// repeated benchmarks. Unlike benchmark_report_aggregates_only, only affects
|
||||
// the display reporter, but *NOT* file reporter, which will still contain
|
||||
// all the output.
|
||||
BM_DEFINE_bool(benchmark_display_aggregates_only, false);
|
||||
|
||||
// The format to use for console output.
|
||||
// Valid values are 'console', 'json', or 'csv'.
|
||||
BM_DEFINE_string(benchmark_format, "console");
|
||||
|
||||
// The format to use for file output.
|
||||
// Valid values are 'console', 'json', or 'csv'.
|
||||
BM_DEFINE_string(benchmark_out_format, "json");
|
||||
|
||||
// The file to write additional output to.
|
||||
BM_DEFINE_string(benchmark_out, "");
|
||||
|
||||
// Whether to use colors in the output. Valid values:
|
||||
// 'true'/'yes'/1, 'false'/'no'/0, and 'auto'. 'auto' means to use colors if
|
||||
// the output is being sent to a terminal and the TERM environment variable is
|
||||
// set to a terminal type that supports colors.
|
||||
BM_DEFINE_string(benchmark_color, "auto");
|
||||
|
||||
// Whether to use tabular format when printing user counters to the console.
|
||||
// Valid values: 'true'/'yes'/1, 'false'/'no'/0. Defaults to false.
|
||||
BM_DEFINE_bool(benchmark_counters_tabular, false);
|
||||
|
||||
// List of additional perf counters to collect, in libpfm format. For more
|
||||
// information about libpfm: https://man7.org/linux/man-pages/man3/libpfm.3.html
|
||||
BM_DEFINE_string(benchmark_perf_counters, "");
|
||||
|
||||
// Extra context to include in the output formatted as comma-separated key-value
|
||||
// pairs. Kept internal as it's only used for parsing from env/command line.
|
||||
BM_DEFINE_kvpairs(benchmark_context, {});
|
||||
|
||||
// Set the default time unit to use for reports
|
||||
// Valid values are 'ns', 'us', 'ms' or 's'
|
||||
BM_DEFINE_string(benchmark_time_unit, "");
|
||||
|
||||
// The level of verbose logging to output
|
||||
BM_DEFINE_int32(v, 0);
|
||||
|
||||
namespace internal {
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
std::map<std::string, std::string>* global_context = nullptr;
|
||||
|
||||
BENCHMARK_EXPORT std::map<std::string, std::string>*& GetGlobalContext() {
|
||||
return global_context;
|
||||
}
|
||||
|
||||
namespace {
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
void const volatile* volatile global_force_escape_pointer;
|
||||
} // namespace
|
||||
|
||||
// FIXME: Verify if LTO still messes this up?
|
||||
void UseCharPointer(char const volatile* const v) {
|
||||
// We want to escape the pointer `v` so that the compiler can not eliminate
|
||||
// computations that produced it. To do that, we escape the pointer by storing
|
||||
// it into a volatile variable, since generally, volatile store, is not
|
||||
// something the compiler is allowed to elide.
|
||||
global_force_escape_pointer = reinterpret_cast<void const volatile*>(v);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
State::State(std::string name, IterationCount max_iters,
|
||||
const std::vector<int64_t>& ranges, int thread_i, int n_threads,
|
||||
internal::ThreadTimer* timer, internal::ThreadManager* manager,
|
||||
internal::PerfCountersMeasurement* perf_counters_measurement,
|
||||
ProfilerManager* profiler_manager)
|
||||
: total_iterations_(0),
|
||||
batch_leftover_(0),
|
||||
max_iterations(max_iters),
|
||||
started_(false),
|
||||
finished_(false),
|
||||
skipped_(internal::NotSkipped),
|
||||
range_(ranges),
|
||||
complexity_n_(0),
|
||||
name_(std::move(name)),
|
||||
thread_index_(thread_i),
|
||||
threads_(n_threads),
|
||||
timer_(timer),
|
||||
manager_(manager),
|
||||
perf_counters_measurement_(perf_counters_measurement),
|
||||
profiler_manager_(profiler_manager) {
|
||||
BM_CHECK(max_iterations != 0) << "At least one iteration must be run";
|
||||
BM_CHECK_LT(thread_index_, threads_)
|
||||
<< "thread_index must be less than threads";
|
||||
|
||||
// Add counters with correct flag now. If added with `counters[name]` in
|
||||
// `PauseTiming`, a new `Counter` will be inserted the first time, which
|
||||
// won't have the flag. Inserting them now also reduces the allocations
|
||||
// during the benchmark.
|
||||
if (perf_counters_measurement_ != nullptr) {
|
||||
for (const std::string& counter_name :
|
||||
perf_counters_measurement_->names()) {
|
||||
counters[counter_name] = Counter(0.0, Counter::kAvgIterations);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: The use of offsetof below is technically undefined until C++17
|
||||
// because State is not a standard layout type. However, all compilers
|
||||
// currently provide well-defined behavior as an extension (which is
|
||||
// demonstrated since constexpr evaluation must diagnose all undefined
|
||||
// behavior). However, GCC and Clang also warn about this use of offsetof,
|
||||
// which must be suppressed.
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#pragma warning push
|
||||
#pragma warning(disable : 1875)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||
#endif
|
||||
#if defined(__NVCC__)
|
||||
#pragma nv_diagnostic push
|
||||
#pragma nv_diag_suppress 1427
|
||||
#endif
|
||||
#if defined(__NVCOMPILER)
|
||||
#pragma diagnostic push
|
||||
#pragma diag_suppress offset_in_non_POD_nonstandard
|
||||
#endif
|
||||
// Offset tests to ensure commonly accessed data is on the first cache line.
|
||||
const int cache_line_size = 64;
|
||||
static_assert(
|
||||
offsetof(State, skipped_) <= (cache_line_size - sizeof(skipped_)), "");
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#pragma warning pop
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#if defined(__NVCC__)
|
||||
#pragma nv_diagnostic pop
|
||||
#endif
|
||||
#if defined(__NVCOMPILER)
|
||||
#pragma diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
void State::PauseTiming() {
|
||||
// Add in time accumulated so far
|
||||
BM_CHECK(started_ && !finished_ && !skipped());
|
||||
timer_->StopTimer();
|
||||
if (perf_counters_measurement_ != nullptr) {
|
||||
std::vector<std::pair<std::string, double>> measurements;
|
||||
if (!perf_counters_measurement_->Stop(measurements)) {
|
||||
BM_CHECK(false) << "Perf counters read the value failed.";
|
||||
}
|
||||
for (const auto& name_and_measurement : measurements) {
|
||||
const std::string& name = name_and_measurement.first;
|
||||
const double measurement = name_and_measurement.second;
|
||||
// Counter was inserted with `kAvgIterations` flag by the constructor.
|
||||
assert(counters.find(name) != counters.end());
|
||||
counters[name].value += measurement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void State::ResumeTiming() {
|
||||
BM_CHECK(started_ && !finished_ && !skipped());
|
||||
timer_->StartTimer();
|
||||
if (perf_counters_measurement_ != nullptr) {
|
||||
perf_counters_measurement_->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void State::SkipWithMessage(const std::string& msg) {
|
||||
skipped_ = internal::SkippedWithMessage;
|
||||
{
|
||||
MutexLock l(manager_->GetBenchmarkMutex());
|
||||
if (internal::NotSkipped == manager_->results.skipped_) {
|
||||
manager_->results.skip_message_ = msg;
|
||||
manager_->results.skipped_ = skipped_;
|
||||
}
|
||||
}
|
||||
total_iterations_ = 0;
|
||||
if (timer_->running()) {
|
||||
timer_->StopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void State::SkipWithError(const std::string& msg) {
|
||||
skipped_ = internal::SkippedWithError;
|
||||
{
|
||||
MutexLock l(manager_->GetBenchmarkMutex());
|
||||
if (internal::NotSkipped == manager_->results.skipped_) {
|
||||
manager_->results.skip_message_ = msg;
|
||||
manager_->results.skipped_ = skipped_;
|
||||
}
|
||||
}
|
||||
total_iterations_ = 0;
|
||||
if (timer_->running()) {
|
||||
timer_->StopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void State::SetIterationTime(double seconds) {
|
||||
timer_->SetIterationTime(seconds);
|
||||
}
|
||||
|
||||
void State::SetLabel(const std::string& label) {
|
||||
MutexLock l(manager_->GetBenchmarkMutex());
|
||||
manager_->results.report_label_ = label;
|
||||
}
|
||||
|
||||
void State::StartKeepRunning() {
|
||||
BM_CHECK(!started_ && !finished_);
|
||||
started_ = true;
|
||||
total_iterations_ = skipped() ? 0 : max_iterations;
|
||||
if (BENCHMARK_BUILTIN_EXPECT(profiler_manager_ != nullptr, false)) {
|
||||
profiler_manager_->AfterSetupStart();
|
||||
}
|
||||
manager_->StartStopBarrier();
|
||||
if (!skipped()) {
|
||||
ResumeTiming();
|
||||
}
|
||||
}
|
||||
|
||||
void State::FinishKeepRunning() {
|
||||
BM_CHECK(started_ && (!finished_ || skipped()));
|
||||
if (!skipped()) {
|
||||
PauseTiming();
|
||||
}
|
||||
// Total iterations has now wrapped around past 0. Fix this.
|
||||
total_iterations_ = 0;
|
||||
finished_ = true;
|
||||
manager_->StartStopBarrier();
|
||||
if (BENCHMARK_BUILTIN_EXPECT(profiler_manager_ != nullptr, false)) {
|
||||
profiler_manager_->BeforeTeardownStop();
|
||||
}
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
// Flushes streams after invoking reporter methods that write to them. This
|
||||
// ensures users get timely updates even when streams are not line-buffered.
|
||||
void FlushStreams(BenchmarkReporter* reporter) {
|
||||
if (reporter == nullptr) {
|
||||
return;
|
||||
}
|
||||
std::flush(reporter->GetOutputStream());
|
||||
std::flush(reporter->GetErrorStream());
|
||||
}
|
||||
|
||||
// Reports in both display and file reporters.
|
||||
void Report(BenchmarkReporter* display_reporter,
|
||||
BenchmarkReporter* file_reporter, const RunResults& run_results) {
|
||||
auto report_one = [](BenchmarkReporter* reporter, bool aggregates_only,
|
||||
const RunResults& results) {
|
||||
assert(reporter);
|
||||
// If there are no aggregates, do output non-aggregates.
|
||||
aggregates_only &= !results.aggregates_only.empty();
|
||||
if (!aggregates_only) {
|
||||
reporter->ReportRuns(results.non_aggregates);
|
||||
}
|
||||
if (!results.aggregates_only.empty()) {
|
||||
reporter->ReportRuns(results.aggregates_only);
|
||||
}
|
||||
};
|
||||
|
||||
report_one(display_reporter, run_results.display_report_aggregates_only,
|
||||
run_results);
|
||||
if (file_reporter != nullptr) {
|
||||
report_one(file_reporter, run_results.file_report_aggregates_only,
|
||||
run_results);
|
||||
}
|
||||
|
||||
FlushStreams(display_reporter);
|
||||
FlushStreams(file_reporter);
|
||||
}
|
||||
|
||||
void RunBenchmarks(const std::vector<BenchmarkInstance>& benchmarks,
|
||||
BenchmarkReporter* display_reporter,
|
||||
BenchmarkReporter* file_reporter) {
|
||||
// Note the file_reporter can be null.
|
||||
BM_CHECK(display_reporter != nullptr);
|
||||
|
||||
// Determine the width of the name field using a minimum width of 10.
|
||||
bool might_have_aggregates = FLAGS_benchmark_repetitions > 1;
|
||||
size_t name_field_width = 10;
|
||||
size_t stat_field_width = 0;
|
||||
for (const BenchmarkInstance& benchmark : benchmarks) {
|
||||
name_field_width =
|
||||
std::max<size_t>(name_field_width, benchmark.name().str().size());
|
||||
might_have_aggregates |= benchmark.repetitions() > 1;
|
||||
|
||||
for (const auto& Stat : benchmark.statistics()) {
|
||||
stat_field_width = std::max<size_t>(stat_field_width, Stat.name_.size());
|
||||
}
|
||||
}
|
||||
if (might_have_aggregates) {
|
||||
name_field_width += 1 + stat_field_width;
|
||||
}
|
||||
|
||||
// Print header here
|
||||
BenchmarkReporter::Context context;
|
||||
context.name_field_width = name_field_width;
|
||||
|
||||
// Keep track of running times of all instances of each benchmark family.
|
||||
std::map<int /*family_index*/, BenchmarkReporter::PerFamilyRunReports>
|
||||
per_family_reports;
|
||||
|
||||
if (display_reporter->ReportContext(context) &&
|
||||
((file_reporter == nullptr) || file_reporter->ReportContext(context))) {
|
||||
FlushStreams(display_reporter);
|
||||
FlushStreams(file_reporter);
|
||||
|
||||
size_t num_repetitions_total = 0;
|
||||
|
||||
// This perfcounters object needs to be created before the runners vector
|
||||
// below so it outlasts their lifetime.
|
||||
PerfCountersMeasurement perfcounters(
|
||||
StrSplit(FLAGS_benchmark_perf_counters, ','));
|
||||
|
||||
// Vector of benchmarks to run
|
||||
std::vector<internal::BenchmarkRunner> runners;
|
||||
runners.reserve(benchmarks.size());
|
||||
|
||||
// Count the number of benchmarks with threads to warn the user in case
|
||||
// performance counters are used.
|
||||
int benchmarks_with_threads = 0;
|
||||
|
||||
// Loop through all benchmarks
|
||||
for (const BenchmarkInstance& benchmark : benchmarks) {
|
||||
BenchmarkReporter::PerFamilyRunReports* reports_for_family = nullptr;
|
||||
if (benchmark.complexity() != oNone) {
|
||||
reports_for_family = &per_family_reports[benchmark.family_index()];
|
||||
}
|
||||
benchmarks_with_threads += static_cast<int>(benchmark.threads() > 1);
|
||||
runners.emplace_back(benchmark, &perfcounters, reports_for_family);
|
||||
int num_repeats_of_this_instance = runners.back().GetNumRepeats();
|
||||
num_repetitions_total +=
|
||||
static_cast<size_t>(num_repeats_of_this_instance);
|
||||
if (reports_for_family != nullptr) {
|
||||
reports_for_family->num_runs_total += num_repeats_of_this_instance;
|
||||
}
|
||||
}
|
||||
assert(runners.size() == benchmarks.size() && "Unexpected runner count.");
|
||||
|
||||
// The use of performance counters with threads would be unintuitive for
|
||||
// the average user so we need to warn them about this case
|
||||
if ((benchmarks_with_threads > 0) && (perfcounters.num_counters() > 0)) {
|
||||
GetErrorLogInstance()
|
||||
<< "***WARNING*** There are " << benchmarks_with_threads
|
||||
<< " benchmarks with threads and " << perfcounters.num_counters()
|
||||
<< " performance counters were requested. Beware counters will "
|
||||
"reflect the combined usage across all "
|
||||
"threads.\n";
|
||||
}
|
||||
|
||||
std::vector<size_t> repetition_indices;
|
||||
repetition_indices.reserve(num_repetitions_total);
|
||||
for (size_t runner_index = 0, num_runners = runners.size();
|
||||
runner_index != num_runners; ++runner_index) {
|
||||
const internal::BenchmarkRunner& runner = runners[runner_index];
|
||||
std::fill_n(std::back_inserter(repetition_indices),
|
||||
runner.GetNumRepeats(), runner_index);
|
||||
}
|
||||
assert(repetition_indices.size() == num_repetitions_total &&
|
||||
"Unexpected number of repetition indexes.");
|
||||
|
||||
if (FLAGS_benchmark_enable_random_interleaving) {
|
||||
std::random_device rd;
|
||||
std::mt19937 g(rd());
|
||||
std::shuffle(repetition_indices.begin(), repetition_indices.end(), g);
|
||||
}
|
||||
|
||||
for (size_t repetition_index : repetition_indices) {
|
||||
internal::BenchmarkRunner& runner = runners[repetition_index];
|
||||
runner.DoOneRepetition();
|
||||
if (runner.HasRepeatsRemaining()) {
|
||||
continue;
|
||||
}
|
||||
// FIXME: report each repetition separately, not all of them in bulk.
|
||||
|
||||
display_reporter->ReportRunsConfig(
|
||||
runner.GetMinTime(), runner.HasExplicitIters(), runner.GetIters());
|
||||
if (file_reporter != nullptr) {
|
||||
file_reporter->ReportRunsConfig(
|
||||
runner.GetMinTime(), runner.HasExplicitIters(), runner.GetIters());
|
||||
}
|
||||
|
||||
RunResults run_results = runner.GetResults();
|
||||
|
||||
// Maybe calculate complexity report
|
||||
if (const auto* reports_for_family = runner.GetReportsForFamily()) {
|
||||
if (reports_for_family->num_runs_done ==
|
||||
reports_for_family->num_runs_total) {
|
||||
auto additional_run_stats = ComputeBigO(reports_for_family->Runs);
|
||||
run_results.aggregates_only.insert(run_results.aggregates_only.end(),
|
||||
additional_run_stats.begin(),
|
||||
additional_run_stats.end());
|
||||
per_family_reports.erase(
|
||||
static_cast<int>(reports_for_family->Runs.front().family_index));
|
||||
}
|
||||
}
|
||||
|
||||
Report(display_reporter, file_reporter, run_results);
|
||||
}
|
||||
}
|
||||
display_reporter->Finalize();
|
||||
if (file_reporter != nullptr) {
|
||||
file_reporter->Finalize();
|
||||
}
|
||||
FlushStreams(display_reporter);
|
||||
FlushStreams(file_reporter);
|
||||
}
|
||||
|
||||
// Disable deprecated warnings temporarily because we need to reference
|
||||
// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations
|
||||
BENCHMARK_DISABLE_DEPRECATED_WARNING
|
||||
|
||||
std::unique_ptr<BenchmarkReporter> CreateReporter(
|
||||
std::string const& name, ConsoleReporter::OutputOptions output_opts) {
|
||||
typedef std::unique_ptr<BenchmarkReporter> PtrType;
|
||||
if (name == "console") {
|
||||
return PtrType(new ConsoleReporter(output_opts));
|
||||
}
|
||||
if (name == "json") {
|
||||
return PtrType(new JSONReporter());
|
||||
}
|
||||
if (name == "csv") {
|
||||
return PtrType(new CSVReporter());
|
||||
}
|
||||
std::cerr << "Unexpected format: '" << name << "'\n";
|
||||
std::flush(std::cerr);
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
BENCHMARK_RESTORE_DEPRECATED_WARNING
|
||||
|
||||
} // end namespace
|
||||
|
||||
bool IsZero(double n) {
|
||||
return std::abs(n) < std::numeric_limits<double>::epsilon();
|
||||
}
|
||||
|
||||
ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) {
|
||||
int output_opts = ConsoleReporter::OO_Defaults;
|
||||
auto is_benchmark_color = [force_no_color]() -> bool {
|
||||
if (force_no_color) {
|
||||
return false;
|
||||
}
|
||||
if (FLAGS_benchmark_color == "auto") {
|
||||
return IsColorTerminal();
|
||||
}
|
||||
return IsTruthyFlagValue(FLAGS_benchmark_color);
|
||||
};
|
||||
if (is_benchmark_color()) {
|
||||
output_opts |= ConsoleReporter::OO_Color;
|
||||
} else {
|
||||
output_opts &= ~ConsoleReporter::OO_Color;
|
||||
}
|
||||
if (FLAGS_benchmark_counters_tabular) {
|
||||
output_opts |= ConsoleReporter::OO_Tabular;
|
||||
} else {
|
||||
output_opts &= ~ConsoleReporter::OO_Tabular;
|
||||
}
|
||||
return static_cast<ConsoleReporter::OutputOptions>(output_opts);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
BenchmarkReporter* CreateDefaultDisplayReporter() {
|
||||
static auto* default_display_reporter =
|
||||
internal::CreateReporter(FLAGS_benchmark_format,
|
||||
internal::GetOutputOptions())
|
||||
.release();
|
||||
return default_display_reporter;
|
||||
}
|
||||
|
||||
size_t RunSpecifiedBenchmarks() {
|
||||
return RunSpecifiedBenchmarks(nullptr, nullptr, FLAGS_benchmark_filter);
|
||||
}
|
||||
|
||||
size_t RunSpecifiedBenchmarks(std::string spec) {
|
||||
return RunSpecifiedBenchmarks(nullptr, nullptr, std::move(spec));
|
||||
}
|
||||
|
||||
size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter) {
|
||||
return RunSpecifiedBenchmarks(display_reporter, nullptr,
|
||||
FLAGS_benchmark_filter);
|
||||
}
|
||||
|
||||
size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
|
||||
std::string spec) {
|
||||
return RunSpecifiedBenchmarks(display_reporter, nullptr, std::move(spec));
|
||||
}
|
||||
|
||||
size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
|
||||
BenchmarkReporter* file_reporter) {
|
||||
return RunSpecifiedBenchmarks(display_reporter, file_reporter,
|
||||
FLAGS_benchmark_filter);
|
||||
}
|
||||
|
||||
size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
|
||||
BenchmarkReporter* file_reporter,
|
||||
std::string spec) {
|
||||
if (spec.empty() || spec == "all") {
|
||||
spec = "."; // Regexp that matches all benchmarks
|
||||
}
|
||||
|
||||
// Setup the reporters
|
||||
std::ofstream output_file;
|
||||
std::unique_ptr<BenchmarkReporter> default_display_reporter;
|
||||
std::unique_ptr<BenchmarkReporter> default_file_reporter;
|
||||
if (display_reporter == nullptr) {
|
||||
default_display_reporter.reset(CreateDefaultDisplayReporter());
|
||||
display_reporter = default_display_reporter.get();
|
||||
}
|
||||
auto& Out = display_reporter->GetOutputStream();
|
||||
auto& Err = display_reporter->GetErrorStream();
|
||||
|
||||
std::string const& fname = FLAGS_benchmark_out;
|
||||
if (fname.empty() && (file_reporter != nullptr)) {
|
||||
Err << "A custom file reporter was provided but "
|
||||
"--benchmark_out=<file> was not specified.\n";
|
||||
Out.flush();
|
||||
Err.flush();
|
||||
std::exit(1);
|
||||
}
|
||||
if (!fname.empty()) {
|
||||
output_file.open(fname);
|
||||
if (!output_file.is_open()) {
|
||||
Err << "invalid file name: '" << fname << "'\n";
|
||||
Out.flush();
|
||||
Err.flush();
|
||||
std::exit(1);
|
||||
}
|
||||
if (file_reporter == nullptr) {
|
||||
default_file_reporter = internal::CreateReporter(
|
||||
FLAGS_benchmark_out_format, FLAGS_benchmark_counters_tabular
|
||||
? ConsoleReporter::OO_Tabular
|
||||
: ConsoleReporter::OO_None);
|
||||
file_reporter = default_file_reporter.get();
|
||||
}
|
||||
file_reporter->SetOutputStream(&output_file);
|
||||
file_reporter->SetErrorStream(&output_file);
|
||||
}
|
||||
|
||||
std::vector<internal::BenchmarkInstance> benchmarks;
|
||||
if (!FindBenchmarksInternal(spec, &benchmarks, &Err)) {
|
||||
Out.flush();
|
||||
Err.flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (benchmarks.empty()) {
|
||||
Err << "Failed to match any benchmarks against regex: " << spec << "\n";
|
||||
Out.flush();
|
||||
Err.flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FLAGS_benchmark_list_tests) {
|
||||
for (auto const& benchmark : benchmarks) {
|
||||
Out << benchmark.name().str() << "\n";
|
||||
}
|
||||
} else {
|
||||
internal::RunBenchmarks(benchmarks, display_reporter, file_reporter);
|
||||
}
|
||||
|
||||
Out.flush();
|
||||
Err.flush();
|
||||
return benchmarks.size();
|
||||
}
|
||||
|
||||
namespace {
|
||||
// stores the time unit benchmarks use by default
|
||||
TimeUnit default_time_unit = kNanosecond;
|
||||
} // namespace
|
||||
|
||||
TimeUnit GetDefaultTimeUnit() { return default_time_unit; }
|
||||
|
||||
void SetDefaultTimeUnit(TimeUnit unit) { default_time_unit = unit; }
|
||||
|
||||
std::string GetBenchmarkFilter() { return FLAGS_benchmark_filter; }
|
||||
|
||||
void SetBenchmarkFilter(std::string value) {
|
||||
FLAGS_benchmark_filter = std::move(value);
|
||||
}
|
||||
|
||||
int32_t GetBenchmarkVerbosity() { return FLAGS_v; }
|
||||
|
||||
void RegisterMemoryManager(MemoryManager* manager) {
|
||||
internal::memory_manager = manager;
|
||||
}
|
||||
|
||||
void RegisterProfilerManager(ProfilerManager* manager) {
|
||||
// Don't allow overwriting an existing manager.
|
||||
if (manager != nullptr) {
|
||||
BM_CHECK_EQ(internal::profiler_manager, nullptr);
|
||||
}
|
||||
internal::profiler_manager = manager;
|
||||
}
|
||||
|
||||
void AddCustomContext(std::string key, std::string value) {
|
||||
if (internal::global_context == nullptr) {
|
||||
internal::global_context = new std::map<std::string, std::string>();
|
||||
}
|
||||
if (!internal::global_context->emplace(std::move(key), std::move(value))
|
||||
.second) {
|
||||
std::cerr << "Failed to add custom context \"" << key << "\" as it already "
|
||||
<< "exists with value \"" << value << "\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
void (*HelperPrintf)();
|
||||
|
||||
namespace {
|
||||
void PrintUsageAndExit() {
|
||||
HelperPrintf();
|
||||
std::flush(std::cout);
|
||||
std::flush(std::cerr);
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
void SetDefaultTimeUnitFromFlag(const std::string& time_unit_flag) {
|
||||
if (time_unit_flag == "s") {
|
||||
return SetDefaultTimeUnit(kSecond);
|
||||
}
|
||||
if (time_unit_flag == "ms") {
|
||||
return SetDefaultTimeUnit(kMillisecond);
|
||||
}
|
||||
if (time_unit_flag == "us") {
|
||||
return SetDefaultTimeUnit(kMicrosecond);
|
||||
}
|
||||
if (time_unit_flag == "ns") {
|
||||
return SetDefaultTimeUnit(kNanosecond);
|
||||
}
|
||||
if (!time_unit_flag.empty()) {
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
}
|
||||
|
||||
void ParseCommandLineFlags(int* argc, char** argv) {
|
||||
using namespace benchmark;
|
||||
BenchmarkReporter::Context::executable_name =
|
||||
((argc != nullptr) && *argc > 0) ? argv[0] : "unknown";
|
||||
for (int i = 1; (argc != nullptr) && i < *argc; ++i) {
|
||||
if (ParseBoolFlag(argv[i], "benchmark_list_tests",
|
||||
&FLAGS_benchmark_list_tests) ||
|
||||
ParseStringFlag(argv[i], "benchmark_filter", &FLAGS_benchmark_filter) ||
|
||||
ParseStringFlag(argv[i], "benchmark_min_time",
|
||||
&FLAGS_benchmark_min_time) ||
|
||||
ParseDoubleFlag(argv[i], "benchmark_min_warmup_time",
|
||||
&FLAGS_benchmark_min_warmup_time) ||
|
||||
ParseInt32Flag(argv[i], "benchmark_repetitions",
|
||||
&FLAGS_benchmark_repetitions) ||
|
||||
ParseBoolFlag(argv[i], "benchmark_dry_run", &FLAGS_benchmark_dry_run) ||
|
||||
ParseBoolFlag(argv[i], "benchmark_enable_random_interleaving",
|
||||
&FLAGS_benchmark_enable_random_interleaving) ||
|
||||
ParseBoolFlag(argv[i], "benchmark_report_aggregates_only",
|
||||
&FLAGS_benchmark_report_aggregates_only) ||
|
||||
ParseBoolFlag(argv[i], "benchmark_display_aggregates_only",
|
||||
&FLAGS_benchmark_display_aggregates_only) ||
|
||||
ParseStringFlag(argv[i], "benchmark_format", &FLAGS_benchmark_format) ||
|
||||
ParseStringFlag(argv[i], "benchmark_out", &FLAGS_benchmark_out) ||
|
||||
ParseStringFlag(argv[i], "benchmark_out_format",
|
||||
&FLAGS_benchmark_out_format) ||
|
||||
ParseStringFlag(argv[i], "benchmark_color", &FLAGS_benchmark_color) ||
|
||||
ParseBoolFlag(argv[i], "benchmark_counters_tabular",
|
||||
&FLAGS_benchmark_counters_tabular) ||
|
||||
ParseStringFlag(argv[i], "benchmark_perf_counters",
|
||||
&FLAGS_benchmark_perf_counters) ||
|
||||
ParseKeyValueFlag(argv[i], "benchmark_context",
|
||||
&FLAGS_benchmark_context) ||
|
||||
ParseStringFlag(argv[i], "benchmark_time_unit",
|
||||
&FLAGS_benchmark_time_unit) ||
|
||||
ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
|
||||
for (int j = i; j != *argc - 1; ++j) {
|
||||
argv[j] = argv[j + 1];
|
||||
}
|
||||
|
||||
--(*argc);
|
||||
--i;
|
||||
} else if (IsFlag(argv[i], "help")) {
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
}
|
||||
for (auto const* flag :
|
||||
{&FLAGS_benchmark_format, &FLAGS_benchmark_out_format}) {
|
||||
if (*flag != "console" && *flag != "json" && *flag != "csv") {
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
}
|
||||
SetDefaultTimeUnitFromFlag(FLAGS_benchmark_time_unit);
|
||||
if (FLAGS_benchmark_color.empty()) {
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
if (FLAGS_benchmark_dry_run) {
|
||||
AddCustomContext("dry_run", "true");
|
||||
}
|
||||
for (const auto& kv : FLAGS_benchmark_context) {
|
||||
AddCustomContext(kv.first, kv.second);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
int InitializeStreams() {
|
||||
static std::ios_base::Init init;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::make_unsigned_t<T> get_as_unsigned(T v) {
|
||||
using UnsignedT = std::make_unsigned_t<T>;
|
||||
return static_cast<UnsignedT>(v);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
void MaybeReenterWithoutASLR(int /*argc*/, char** argv) {
|
||||
// On e.g. Hexagon simulator, argv may be NULL.
|
||||
if (!argv) return;
|
||||
|
||||
#ifdef BENCHMARK_OS_LINUX
|
||||
const auto curr_personality = personality(0xffffffff);
|
||||
|
||||
// We should never fail to read-only query the current personality,
|
||||
// but let's be cautious.
|
||||
if (curr_personality == -1) return;
|
||||
|
||||
// If ASLR is already disabled, we have nothing more to do.
|
||||
if (internal::get_as_unsigned(curr_personality) & ADDR_NO_RANDOMIZE) return;
|
||||
|
||||
// Try to change the personality to disable ASLR.
|
||||
const auto proposed_personality =
|
||||
internal::get_as_unsigned(curr_personality) | ADDR_NO_RANDOMIZE;
|
||||
const auto prev_personality = personality(proposed_personality);
|
||||
|
||||
// Have we failed to change the personality? That may happen.
|
||||
if (prev_personality == -1) return;
|
||||
|
||||
// Make sure the parsona has been updated with the no-ASLR flag,
|
||||
// otherwise we will try to reenter infinitely.
|
||||
// This seems impossible, but can happen in some docker configurations.
|
||||
const auto new_personality = personality(0xffffffff);
|
||||
if ((internal::get_as_unsigned(new_personality) & ADDR_NO_RANDOMIZE) == 0)
|
||||
return;
|
||||
|
||||
execv(argv[0], argv);
|
||||
// The exec() functions return only if an error has occurred,
|
||||
// in which case we want to just continue as-is.
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string GetBenchmarkVersion() {
|
||||
#ifdef BENCHMARK_VERSION
|
||||
return {BENCHMARK_VERSION};
|
||||
#else
|
||||
return {""};
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintDefaultHelp() {
|
||||
fprintf(stdout,
|
||||
"benchmark"
|
||||
" [--benchmark_list_tests={true|false}]\n"
|
||||
" [--benchmark_filter=<regex>]\n"
|
||||
" [--benchmark_min_time=`<integer>x` OR `<float>s` ]\n"
|
||||
" [--benchmark_min_warmup_time=<min_warmup_time>]\n"
|
||||
" [--benchmark_repetitions=<num_repetitions>]\n"
|
||||
" [--benchmark_dry_run={true|false}]\n"
|
||||
" [--benchmark_enable_random_interleaving={true|false}]\n"
|
||||
" [--benchmark_report_aggregates_only={true|false}]\n"
|
||||
" [--benchmark_display_aggregates_only={true|false}]\n"
|
||||
" [--benchmark_format=<console|json|csv>]\n"
|
||||
" [--benchmark_out=<filename>]\n"
|
||||
" [--benchmark_out_format=<json|console|csv>]\n"
|
||||
" [--benchmark_color={auto|true|false}]\n"
|
||||
" [--benchmark_counters_tabular={true|false}]\n"
|
||||
#if defined HAVE_LIBPFM
|
||||
" [--benchmark_perf_counters=<counter>,...]\n"
|
||||
#endif
|
||||
" [--benchmark_context=<key>=<value>,...]\n"
|
||||
" [--benchmark_time_unit={ns|us|ms|s}]\n"
|
||||
" [--v=<verbosity>]\n");
|
||||
}
|
||||
|
||||
void Initialize(int* argc, char** argv, void (*HelperPrintf)()) {
|
||||
internal::HelperPrintf = HelperPrintf;
|
||||
internal::ParseCommandLineFlags(argc, argv);
|
||||
internal::LogLevel() = FLAGS_v;
|
||||
}
|
||||
|
||||
void Shutdown() { delete internal::global_context; }
|
||||
|
||||
bool ReportUnrecognizedArguments(int argc, char** argv) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0],
|
||||
argv[i]);
|
||||
}
|
||||
return argc > 1;
|
||||
}
|
||||
|
||||
} // end namespace benchmark
|
||||
119
thirdparty/benchmark/src/benchmark_api_internal.cc
vendored
119
thirdparty/benchmark/src/benchmark_api_internal.cc
vendored
@ -1,119 +0,0 @@
|
||||
#include "benchmark_api_internal.h"
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
#include "string_util.h"
|
||||
|
||||
namespace benchmark {
|
||||
namespace internal {
|
||||
|
||||
BenchmarkInstance::BenchmarkInstance(benchmark::Benchmark* benchmark,
|
||||
int family_idx,
|
||||
int per_family_instance_idx,
|
||||
const std::vector<int64_t>& args,
|
||||
int thread_count)
|
||||
: benchmark_(*benchmark),
|
||||
family_index_(family_idx),
|
||||
per_family_instance_index_(per_family_instance_idx),
|
||||
aggregation_report_mode_(benchmark_.aggregation_report_mode_),
|
||||
args_(args),
|
||||
time_unit_(benchmark_.GetTimeUnit()),
|
||||
measure_process_cpu_time_(benchmark_.measure_process_cpu_time_),
|
||||
use_real_time_(benchmark_.use_real_time_),
|
||||
use_manual_time_(benchmark_.use_manual_time_),
|
||||
complexity_(benchmark_.complexity_),
|
||||
complexity_lambda_(benchmark_.complexity_lambda_),
|
||||
statistics_(benchmark_.statistics_),
|
||||
repetitions_(benchmark_.repetitions_),
|
||||
min_time_(benchmark_.min_time_),
|
||||
min_warmup_time_(benchmark_.min_warmup_time_),
|
||||
iterations_(benchmark_.iterations_),
|
||||
threads_(thread_count),
|
||||
setup_(benchmark_.setup_),
|
||||
teardown_(benchmark_.teardown_) {
|
||||
name_.function_name = benchmark_.name_;
|
||||
|
||||
size_t arg_i = 0;
|
||||
for (const auto& arg : args) {
|
||||
if (!name_.args.empty()) {
|
||||
name_.args += '/';
|
||||
}
|
||||
|
||||
if (arg_i < benchmark->arg_names_.size()) {
|
||||
const auto& arg_name = benchmark_.arg_names_[arg_i];
|
||||
if (!arg_name.empty()) {
|
||||
name_.args += StrFormat("%s:", arg_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
name_.args += StrFormat("%" PRId64, arg);
|
||||
++arg_i;
|
||||
}
|
||||
|
||||
if (!IsZero(benchmark->min_time_)) {
|
||||
name_.min_time = StrFormat("min_time:%0.3f", benchmark_.min_time_);
|
||||
}
|
||||
|
||||
if (!IsZero(benchmark->min_warmup_time_)) {
|
||||
name_.min_warmup_time =
|
||||
StrFormat("min_warmup_time:%0.3f", benchmark_.min_warmup_time_);
|
||||
}
|
||||
|
||||
if (benchmark_.iterations_ != 0) {
|
||||
name_.iterations = StrFormat(
|
||||
"iterations:%lu", static_cast<unsigned long>(benchmark_.iterations_));
|
||||
}
|
||||
|
||||
if (benchmark_.repetitions_ != 0) {
|
||||
name_.repetitions = StrFormat("repeats:%d", benchmark_.repetitions_);
|
||||
}
|
||||
|
||||
if (benchmark_.measure_process_cpu_time_) {
|
||||
name_.time_type = "process_time";
|
||||
}
|
||||
|
||||
if (benchmark_.use_manual_time_) {
|
||||
if (!name_.time_type.empty()) {
|
||||
name_.time_type += '/';
|
||||
}
|
||||
name_.time_type += "manual_time";
|
||||
} else if (benchmark_.use_real_time_) {
|
||||
if (!name_.time_type.empty()) {
|
||||
name_.time_type += '/';
|
||||
}
|
||||
name_.time_type += "real_time";
|
||||
}
|
||||
|
||||
if (!benchmark_.thread_counts_.empty()) {
|
||||
name_.threads = StrFormat("threads:%d", threads_);
|
||||
}
|
||||
}
|
||||
|
||||
State BenchmarkInstance::Run(
|
||||
IterationCount iters, int thread_id, internal::ThreadTimer* timer,
|
||||
internal::ThreadManager* manager,
|
||||
internal::PerfCountersMeasurement* perf_counters_measurement,
|
||||
ProfilerManager* profiler_manager) const {
|
||||
State st(name_.function_name, iters, args_, thread_id, threads_, timer,
|
||||
manager, perf_counters_measurement, profiler_manager);
|
||||
benchmark_.Run(st);
|
||||
return st;
|
||||
}
|
||||
|
||||
void BenchmarkInstance::Setup() const {
|
||||
if (setup_ != nullptr) {
|
||||
State st(name_.function_name, /*iters*/ 1, args_, /*thread_id*/ 0, threads_,
|
||||
nullptr, nullptr, nullptr, nullptr);
|
||||
setup_(st);
|
||||
}
|
||||
}
|
||||
|
||||
void BenchmarkInstance::Teardown() const {
|
||||
if (teardown_ != nullptr) {
|
||||
State st(name_.function_name, /*iters*/ 1, args_, /*thread_id*/ 0, threads_,
|
||||
nullptr, nullptr, nullptr, nullptr);
|
||||
teardown_(st);
|
||||
}
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace benchmark
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user