Switch bionic over to google-benchmark.
Also removes the old benchmarking library.
Change-Id: I4791ae69fa5dea03644d3d411c60b7c6d1fceae3
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index 20742bd..6f2651e 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -16,10 +16,6 @@
LOCAL_PATH := $(call my-dir)
-# -----------------------------------------------------------------------------
-# Benchmarks library, usable by projects outside this directory.
-# -----------------------------------------------------------------------------
-
benchmark_cflags := \
-O2 \
-fno-builtin \
@@ -30,38 +26,6 @@
benchmark_cppflags := \
-benchmarklib_src_files := \
- Benchmark.cpp \
- utils.cpp \
- main.cpp \
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libbenchmark
-LOCAL_CFLAGS := $(benchmark_cflags)
-LOCAL_CPPFLAGS := $(benchmark_cppflags)
-LOCAL_SRC_FILES := $(benchmarklib_src_files)
-LOCAL_C_INCLUDES := $(benchmark_c_includes)
-LOCAL_STATIC_LIBRARIES := libbase
-include $(BUILD_STATIC_LIBRARY)
-
-# Only supported on linux systems.
-ifeq ($(HOST_OS),linux)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libbenchmark
-LOCAL_CFLAGS := $(benchmark_cflags)
-LOCAL_CPPFLAGS := $(benchmark_cppflags)
-LOCAL_SRC_FILES := $(benchmarklib_src_files)
-LOCAL_C_INCLUDES := $(benchmark_c_includes)
-LOCAL_MULTILIB := both
-LOCAL_STATIC_LIBRARIES := libbase
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-endif
-
-# -----------------------------------------------------------------------------
-# Benchmarks.
-# -----------------------------------------------------------------------------
benchmark_src_files := \
math_benchmark.cpp \
property_benchmark.cpp \
@@ -83,8 +47,7 @@
LOCAL_CFLAGS := $(benchmark_cflags)
LOCAL_CPPFLAGS := $(benchmark_cppflags)
LOCAL_SRC_FILES := $(benchmark_src_files)
-LOCAL_STATIC_LIBRARIES := libbenchmark libbase
-include $(BUILD_EXECUTABLE)
+include $(BUILD_NATIVE_BENCHMARK)
# We don't build a static benchmark executable because it's not usually
# useful. If you're trying to run the current benchmarks on an older
@@ -105,7 +68,8 @@
LOCAL_CPPFLAGS := $(benchmark_cppflags)
LOCAL_LDFLAGS := -lrt
LOCAL_SRC_FILES := $(benchmark_src_files)
-LOCAL_STATIC_LIBRARIES := libbenchmark libbase
+LOCAL_STATIC_LIBRARIES := libgoogle-benchmark
+# TODO: BUILD_HOST_NATIVE_BENCHMARK
include $(BUILD_HOST_EXECUTABLE)
endif
diff --git a/benchmarks/Benchmark.cpp b/benchmarks/Benchmark.cpp
deleted file mode 100644
index a7ab682..0000000
--- a/benchmarks/Benchmark.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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 <inttypes.h>
-#include <regex.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include <string>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-
-#include <benchmark/Benchmark.h>
-
-#include "utils.h"
-
-namespace testing {
-
-static uint64_t NanoTime() {
- struct timespec t;
- t.tv_sec = t.tv_nsec = 0;
- clock_gettime(CLOCK_MONOTONIC, &t);
- return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
-}
-
-bool Benchmark::header_printed_;
-
-std::vector<Benchmark*>& Benchmark::List() {
- static std::vector<Benchmark*> list;
- return list;
-}
-
-int Benchmark::MaxNameColumnWidth() {
- size_t max = 20;
- for (auto& benchmark : List()) {
- max = std::max(max, benchmark->NameColumnWidth());
- }
- return static_cast<int>(max);
-}
-
-size_t Benchmark::RunAll(std::vector<regex_t*>& regs) {
- size_t benchmarks_run = 0;
- header_printed_ = false;
- for (auto& benchmark : List()) {
- benchmarks_run += benchmark->RunAllArgs(regs);
- }
- return benchmarks_run;
-}
-
-void Benchmark::PrintHeader() {
- if (!header_printed_) {
- printf("%-*s %10s %10s\n", MaxNameColumnWidth(), "", "iterations", "ns/op");
- header_printed_ = true;
- }
-}
-
-template <typename T>
-bool BenchmarkT<T>::ShouldRun(std::vector<regex_t*>& regs, T arg) {
- if (regs.empty()) {
- return true;
- }
-
- for (const auto& re : regs) {
- if (regexec(re, GetNameStr(arg).c_str(), 0, NULL, 0) != REG_NOMATCH) {
- return true;
- }
- }
- return false;
-}
-
-void Benchmark::StopBenchmarkTiming() {
- if (start_time_ns_ != 0) {
- total_time_ns_ += NanoTime() - start_time_ns_;
- }
- start_time_ns_ = 0;
-}
-
-void Benchmark::StartBenchmarkTiming() {
- if (start_time_ns_ == 0) {
- start_time_ns_ = NanoTime();
- }
-}
-
-std::string BenchmarkWithoutArg::GetNameStr(void*) {
- return Name();
-}
-
-template <>
-std::string BenchmarkWithArg<int>::GetNameStr(int arg) {
- return Name() + "/" + PrettyInt(arg, 2);
-}
-
-template <>
-std::string BenchmarkWithArg<double>::GetNameStr(double arg) {
- return Name() + "/" + android::base::StringPrintf("%0.6f", arg);
-}
-
-template<typename T>
-void BenchmarkT<T>::RunWithArg(T arg) {
- int new_iterations = 1;
- int iterations;
- while (new_iterations < 1e8) {
- bytes_processed_ = 0;
- total_time_ns_ = 0;
- start_time_ns_ = 0;
-
- iterations = new_iterations;
- RunIterations(iterations, arg);
- if (total_time_ns_ >= 1e9) {
- break;
- }
-
- if (total_time_ns_/iterations == 0) {
- new_iterations = 1e9;
- } else {
- new_iterations = 1e9/ (total_time_ns_/iterations);
- }
- new_iterations = std::max(iterations + 1,
- std::min(new_iterations + new_iterations/2, 100*iterations));
-
- new_iterations = Round(new_iterations);
- }
-
- printf("%-*s %10s %10" PRId64, MaxNameColumnWidth(), GetNameStr(arg).c_str(),
- PrettyInt(iterations, 10).c_str(), total_time_ns_/iterations);
-
- if (total_time_ns_ > 0 && bytes_processed_ > 0) {
- double gib_processed = static_cast<double>(bytes_processed_)/1e9;
- double seconds = static_cast<double>(total_time_ns_)/1e9;
- printf(" %8.3f GiB/s", gib_processed/seconds);
- }
- printf("\n");
- fflush(stdout);
-}
-
-template class BenchmarkT<int>;
-template class BenchmarkT<double>;
-template class BenchmarkT<void*>;
-
-template class BenchmarkWithArg<int>;
-template class BenchmarkWithArg<double>;
-
-} // namespace testing
diff --git a/benchmarks/benchmark/Benchmark.h b/benchmarks/benchmark/Benchmark.h
deleted file mode 100644
index ae5c1a2..0000000
--- a/benchmarks/benchmark/Benchmark.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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 BENCHMARKS_BENCHMARK_H_
-#define BENCHMARKS_BENCHMARK_H_
-
-#include <regex.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-namespace testing {
-
-class Benchmark {
-public:
- Benchmark() {
- List().push_back(this);
- }
- virtual ~Benchmark() {}
-
- virtual std::string Name() = 0;
-
- virtual size_t RunAllArgs(std::vector<regex_t*>&) = 0;
-
- void SetBenchmarkBytesProcessed(uint64_t bytes) { bytes_processed_ += bytes; }
- void StopBenchmarkTiming();
- void StartBenchmarkTiming();
-
- // Run all of the benchmarks that have registered.
- static size_t RunAll(std::vector<regex_t*>&);
-
- static std::vector<Benchmark*>& List();
-
- static int MaxNameColumnWidth();
-
-protected:
- virtual size_t NameColumnWidth() = 0;
-
- uint64_t bytes_processed_;
- uint64_t total_time_ns_;
- uint64_t start_time_ns_;
-
- static bool header_printed_;
-
- static void PrintHeader();
-};
-
-template <typename T>
-class BenchmarkT : public Benchmark {
-public:
- BenchmarkT() {}
- virtual ~BenchmarkT() {}
-
-protected:
- bool ShouldRun(std::vector<regex_t*>&, T arg);
- void RunWithArg(T arg);
- virtual void RunIterations(int, T) = 0;
- virtual std::string GetNameStr(T) = 0;
-};
-
-class BenchmarkWithoutArg : public BenchmarkT<void*> {
-public:
- BenchmarkWithoutArg() {}
- virtual ~BenchmarkWithoutArg() {}
-
-protected:
- virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
- size_t benchmarks_run = 0;
- if (BenchmarkT<void*>::ShouldRun(regs, nullptr)) {
- PrintHeader();
- RunWithArg(nullptr);
- benchmarks_run++;
- }
- return benchmarks_run;
- }
-
- virtual void RunIterations(int iters, void*) override {
- Run(iters);
- }
-
- virtual void Run(int) = 0;
-
- virtual size_t NameColumnWidth() override {
- return Name().size();
- }
-
- virtual std::string GetNameStr(void *) override;
-};
-
-template<typename T>
-class BenchmarkWithArg : public BenchmarkT<T> {
-public:
- BenchmarkWithArg() {}
- virtual ~BenchmarkWithArg() {}
-
- BenchmarkWithArg* Arg(T arg) {
- args_.push_back(arg);
- return this;
- }
-
-protected:
- virtual size_t NameColumnWidth() override {
- size_t max = 0;
- for (const auto& arg : args_) {
- max = std::max(max, GetNameStr(arg).size());
- }
- return max;
- }
-
- std::string GetNameStr(T arg) override;
-
- virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
- size_t benchmarks_run = 0;
- for (T& arg : args_) {
- if (BenchmarkT<T>::ShouldRun(regs, arg)) {
- Benchmark::PrintHeader();
- BenchmarkT<T>::RunWithArg(arg);
- benchmarks_run++;
- }
- }
- return benchmarks_run;
- }
-
- virtual void RunIterations(int iters, T arg) override {
- Run(iters, arg);
- }
-
- virtual void Run(int iters, T arg) = 0;
-
-private:
- std::vector<T> args_;
-};
-
-} // namespace testing
-
-#define BENCHMARK_START(f, super_class) \
- class f : public super_class { \
- public: \
- f() {} \
- virtual ~f() {} \
- virtual std::string Name() override { return #f; } \
-
-#define BENCHMARK_NO_ARG(f) \
- BENCHMARK_START(f, ::testing::BenchmarkWithoutArg) \
- virtual void Run(int) override; \
- }; \
- static ::testing::Benchmark* __benchmark_##f = new f()
-
-#define BENCHMARK_WITH_ARG(f, arg_type) \
- BENCHMARK_START(f, ::testing::BenchmarkWithArg<arg_type>) \
- virtual void Run(int, arg_type) override; \
- }; \
- static ::testing::BenchmarkWithArg<arg_type>* __benchmark_##f = (new f())
-
-#endif // BENCHMARKS_BENCHMARK_H_
diff --git a/benchmarks/main.cpp b/benchmarks/main.cpp
deleted file mode 100644
index 5bce479..0000000
--- a/benchmarks/main.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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 <regex.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <vector>
-
-#include <benchmark/Benchmark.h>
-
-int main(int argc, char* argv[]) {
- if (::testing::Benchmark::List().empty()) {
- fprintf(stderr, "No benchmarks registered!\n");
- exit(EXIT_FAILURE);
- }
-
- std::vector<regex_t*> regs;
- for (int i = 1; i < argc; i++) {
- regex_t* re = new regex_t;
- int errcode = regcomp(re, argv[i], 0);
- if (errcode != 0) {
- size_t errbuf_size = regerror(errcode, re, NULL, 0);
- if (errbuf_size > 0) {
- char* errbuf = new char[errbuf_size];
- regerror(errcode, re, errbuf, errbuf_size);
- fprintf(stderr, "Couldn't compile \"%s\" as a regular expression: %s\n",
- argv[i], errbuf);
- } else {
- fprintf(stderr, "Unknown compile error for \"%s\" as a regular expression!\n", argv[i]);
- }
- exit(EXIT_FAILURE);
- }
- regs.push_back(re);
- }
-
- if (::testing::Benchmark::RunAll(regs) == 0) {
- fprintf(stderr, "No matching benchmarks!\n");
- fprintf(stderr, "Available benchmarks:\n");
- for (const auto& benchmark : ::testing::Benchmark::List()) {
- fprintf(stderr, " %s\n", benchmark->Name().c_str());
- }
- exit(EXIT_FAILURE);
- }
-
- return 0;
-}
diff --git a/benchmarks/math_benchmark.cpp b/benchmarks/math_benchmark.cpp
index ed5b56c..36ac301 100644
--- a/benchmarks/math_benchmark.cpp
+++ b/benchmarks/math_benchmark.cpp
@@ -17,270 +17,213 @@
#include <fenv.h>
#include <math.h>
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
-#define AT_COMMON_VALS \
- Arg(1234.0)->Arg(nan(""))->Arg(HUGE_VAL)->Arg(0.0)
+static const double values[] = { 1234.0, nan(""), HUGE_VAL, 0.0 };
+static const char* names[] = { "1234.0", "nan", "HUGE_VAL", "0.0" };
+
+#define BENCHMARK_COMMON_VALS(name) BENCHMARK(name)->Arg(0)->Arg(1)->Arg(2)->Arg(3)
+
+static void SetLabel(benchmark::State& state) {
+ state.SetLabel(names[state.range_x()]);
+}
// Avoid optimization.
volatile double d;
volatile double v;
-BENCHMARK_NO_ARG(BM_math_sqrt);
-void BM_math_sqrt::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_math_sqrt(benchmark::State& state) {
d = 0.0;
v = 2.0;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
d += sqrt(v);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_math_sqrt);
-BENCHMARK_NO_ARG(BM_math_log10);
-void BM_math_log10::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_math_log10(benchmark::State& state) {
d = 0.0;
v = 1234.0;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
d += log10(v);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_math_log10);
-BENCHMARK_NO_ARG(BM_math_logb);
-void BM_math_logb::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_math_logb(benchmark::State& state) {
d = 0.0;
v = 1234.0;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
d += logb(v);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_math_logb);
-BENCHMARK_WITH_ARG(BM_math_isfinite_macro, double)->AT_COMMON_VALS;
-void BM_math_isfinite_macro::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_isfinite_macro(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += isfinite(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_isfinite_macro);
#if defined(__BIONIC__)
#define test_isfinite __isfinite
#else
#define test_isfinite __finite
#endif
-BENCHMARK_WITH_ARG(BM_math_isfinite, double)->AT_COMMON_VALS;
-void BM_math_isfinite::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_isfinite(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += test_isfinite(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_isfinite);
-BENCHMARK_WITH_ARG(BM_math_isinf_macro, double)->AT_COMMON_VALS;
-void BM_math_isinf_macro::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_isinf_macro(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += isinf(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_isinf_macro);
-BENCHMARK_WITH_ARG(BM_math_isinf, double)->AT_COMMON_VALS;
-void BM_math_isinf::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_isinf(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += (isinf)(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_isinf);
-BENCHMARK_WITH_ARG(BM_math_isnan_macro, double)->AT_COMMON_VALS;
-void BM_math_isnan_macro::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_isnan_macro(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += isnan(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_isnan_macro);
-BENCHMARK_WITH_ARG(BM_math_isnan, double)->AT_COMMON_VALS;
-void BM_math_isnan::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_isnan(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += (isnan)(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_isnan);
-BENCHMARK_WITH_ARG(BM_math_isnormal_macro, double)->AT_COMMON_VALS;
-void BM_math_isnormal_macro::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_isnormal_macro(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += isnormal(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_isnormal_macro);
#if defined(__BIONIC__)
-BENCHMARK_WITH_ARG(BM_math_isnormal, double)->AT_COMMON_VALS;
-void BM_math_isnormal::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_isnormal(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += (__isnormal)(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_isnormal);
#endif
-BENCHMARK_NO_ARG(BM_math_sin_fast);
-void BM_math_sin_fast::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_math_sin_fast(benchmark::State& state) {
d = 1.0;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
d += sin(d);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_math_sin_fast);
-BENCHMARK_NO_ARG(BM_math_sin_feupdateenv);
-void BM_math_sin_feupdateenv::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_math_sin_feupdateenv(benchmark::State& state) {
d = 1.0;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
fenv_t __libc_save_rm;
feholdexcept(&__libc_save_rm);
fesetround(FE_TONEAREST);
d += sin(d);
feupdateenv(&__libc_save_rm);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_math_sin_feupdateenv);
-BENCHMARK_NO_ARG(BM_math_sin_fesetenv);
-void BM_math_sin_fesetenv::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_math_sin_fesetenv(benchmark::State& state) {
d = 1.0;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
fenv_t __libc_save_rm;
feholdexcept(&__libc_save_rm);
fesetround(FE_TONEAREST);
d += sin(d);
fesetenv(&__libc_save_rm);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_math_sin_fesetenv);
-BENCHMARK_WITH_ARG(BM_math_fpclassify, double)->AT_COMMON_VALS;
-void BM_math_fpclassify::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_fpclassify(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += fpclassify(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_fpclassify);
-BENCHMARK_WITH_ARG(BM_math_signbit_macro, double)->AT_COMMON_VALS;
-void BM_math_signbit_macro::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_signbit_macro(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += signbit(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_signbit_macro);
-BENCHMARK_WITH_ARG(BM_math_signbit, double)->AT_COMMON_VALS;
-void BM_math_signbit::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_signbit(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += (__signbit)(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_signbit);
-BENCHMARK_WITH_ARG(BM_math_fabs_macro, double)->AT_COMMON_VALS;
-void BM_math_fabs_macro::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_fabs_macro(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += fabs(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_fabs_macro);
-BENCHMARK_WITH_ARG(BM_math_fabs, double)->AT_COMMON_VALS;
-void BM_math_fabs::Run(int iters, double value) {
- StartBenchmarkTiming();
-
+static void BM_math_fabs(benchmark::State& state) {
d = 0.0;
- v = value;
- for (int i = 0; i < iters; ++i) {
+ v = values[state.range_x()];
+ while (state.KeepRunning()) {
d += (fabs)(v);
}
-
- StopBenchmarkTiming();
+ SetLabel(state);
}
+BENCHMARK_COMMON_VALS(BM_math_fabs);
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 944cd68..2f72d60 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -26,7 +26,7 @@
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
extern void* __system_property_area__;
@@ -126,7 +126,8 @@
delete[] values;
delete[] value_lens;
}
-public:
+
+ public:
const int nprops;
char** names;
int* name_lens;
@@ -134,100 +135,79 @@
int* value_lens;
bool valid;
-private:
+ private:
std::string pa_dirname;
std::string pa_filename;
void* old_pa;
};
-BENCHMARK_WITH_ARG(BM_property_get, int)->TEST_NUM_PROPS;
-void BM_property_get::Run(int iters, int nprops) {
- StopBenchmarkTiming();
+static void BM_property_get(benchmark::State& state) {
+ const size_t nprops = state.range_x();
LocalPropertyTestState pa(nprops);
- char value[PROP_VALUE_MAX];
+ if (!pa.valid) return;
- if (!pa.valid)
- return;
-
- srandom(iters * nprops);
-
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; i++) {
+ while (state.KeepRunning()) {
+ char value[PROP_VALUE_MAX];
__system_property_get(pa.names[random() % nprops], value);
}
- StopBenchmarkTiming();
}
+BENCHMARK(BM_property_get)->TEST_NUM_PROPS;
-BENCHMARK_WITH_ARG(BM_property_find, int)->TEST_NUM_PROPS;
-void BM_property_find::Run(int iters, int nprops) {
- StopBenchmarkTiming();
+static void BM_property_find(benchmark::State& state) {
+ const size_t nprops = state.range_x();
LocalPropertyTestState pa(nprops);
+ if (!pa.valid) return;
- if (!pa.valid)
- return;
-
- srandom(iters * nprops);
-
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; i++) {
+ while (state.KeepRunning()) {
__system_property_find(pa.names[random() % nprops]);
}
- StopBenchmarkTiming();
}
+BENCHMARK(BM_property_find)->TEST_NUM_PROPS;
-BENCHMARK_WITH_ARG(BM_property_read, int)->TEST_NUM_PROPS;
-void BM_property_read::Run(int iters, int nprops) {
- StopBenchmarkTiming();
+static void BM_property_read(benchmark::State& state) {
+ const size_t nprops = state.range_x();
LocalPropertyTestState pa(nprops);
+ if (!pa.valid) return;
- if (!pa.valid)
- return;
-
- srandom(iters * nprops);
- const prop_info** pinfo = new const prop_info*[iters];
+ const prop_info** pinfo = new const prop_info*[nprops];
char propvalue[PROP_VALUE_MAX];
- for (int i = 0; i < iters; i++) {
+ for (size_t i = 0; i < nprops; ++i) {
pinfo[i] = __system_property_find(pa.names[random() % nprops]);
}
- StartBenchmarkTiming();
- for (int i = 0; i < iters; i++) {
+ size_t i = 0;
+ while (state.KeepRunning()) {
__system_property_read(pinfo[i], 0, propvalue);
+ i = (i + 1) % nprops;
}
- StopBenchmarkTiming();
delete[] pinfo;
}
+BENCHMARK(BM_property_read)->TEST_NUM_PROPS;
-BENCHMARK_WITH_ARG(BM_property_serial, int)->TEST_NUM_PROPS;
-void BM_property_serial::Run(int iters, int nprops) {
- StopBenchmarkTiming();
+static void BM_property_serial(benchmark::State& state) {
+ const size_t nprops = state.range_x();
LocalPropertyTestState pa(nprops);
+ if (!pa.valid) return;
- if (!pa.valid)
- return;
-
- srandom(iters * nprops);
- const prop_info** pinfo = new const prop_info*[iters];
-
- for (int i = 0; i < iters; i++) {
+ const prop_info** pinfo = new const prop_info*[nprops];
+ for (size_t i = 0; i < nprops; ++i) {
pinfo[i] = __system_property_find(pa.names[random() % nprops]);
}
- StartBenchmarkTiming();
- for (int i = 0; i < iters; i++) {
+ size_t i = 0;
+ while (state.KeepRunning()) {
__system_property_serial(pinfo[i]);
+ i = (i + 1) % nprops;
}
- StopBenchmarkTiming();
delete[] pinfo;
}
+BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;
#endif // __BIONIC__
diff --git a/benchmarks/pthread_benchmark.cpp b/benchmarks/pthread_benchmark.cpp
index ad31e7e..bf4d6cb 100644
--- a/benchmarks/pthread_benchmark.cpp
+++ b/benchmarks/pthread_benchmark.cpp
@@ -16,218 +16,178 @@
#include <pthread.h>
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
// Stop GCC optimizing out our pure function.
/* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
-BENCHMARK_NO_ARG(BM_pthread_self);
-void BM_pthread_self::Run(int iters) {
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; ++i) {
+static void BM_pthread_self(benchmark::State& state) {
+ while (state.KeepRunning()) {
pthread_self_fp();
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_pthread_self);
-BENCHMARK_NO_ARG(BM_pthread_getspecific);
-void BM_pthread_getspecific::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_pthread_getspecific(benchmark::State& state) {
pthread_key_t key;
pthread_key_create(&key, NULL);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
pthread_getspecific(key);
}
- StopBenchmarkTiming();
pthread_key_delete(key);
}
+BENCHMARK(BM_pthread_getspecific);
-BENCHMARK_NO_ARG(BM_pthread_setspecific);
-void BM_pthread_setspecific::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_pthread_setspecific(benchmark::State& state) {
pthread_key_t key;
pthread_key_create(&key, NULL);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
pthread_setspecific(key, NULL);
}
- StopBenchmarkTiming();
pthread_key_delete(key);
}
+BENCHMARK(BM_pthread_setspecific);
static void DummyPthreadOnceInitFunction() {
}
-BENCHMARK_NO_ARG(BM_pthread_once);
-void BM_pthread_once::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_pthread_once(benchmark::State& state) {
pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, DummyPthreadOnceInitFunction);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
pthread_once(&once, DummyPthreadOnceInitFunction);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_pthread_once);
-BENCHMARK_NO_ARG(BM_pthread_mutex_lock);
-void BM_pthread_mutex_lock::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_pthread_mutex_lock(benchmark::State& state) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_pthread_mutex_lock);
-BENCHMARK_NO_ARG(BM_pthread_mutex_lock_ERRORCHECK);
-void BM_pthread_mutex_lock_ERRORCHECK::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_pthread_mutex_lock_ERRORCHECK(benchmark::State& state) {
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
-BENCHMARK_NO_ARG(BM_pthread_mutex_lock_RECURSIVE);
-void BM_pthread_mutex_lock_RECURSIVE::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_pthread_mutex_lock_RECURSIVE(benchmark::State& state) {
pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
-BENCHMARK_NO_ARG(BM_pthread_rwlock_read);
-void BM_pthread_rwlock_read::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_pthread_rwlock_read(benchmark::State& state) {
pthread_rwlock_t lock;
pthread_rwlock_init(&lock, NULL);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
pthread_rwlock_rdlock(&lock);
pthread_rwlock_unlock(&lock);
}
- StopBenchmarkTiming();
pthread_rwlock_destroy(&lock);
}
+BENCHMARK(BM_pthread_rwlock_read);
-BENCHMARK_NO_ARG(BM_pthread_rwlock_write);
-void BM_pthread_rwlock_write::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_pthread_rwlock_write(benchmark::State& state) {
pthread_rwlock_t lock;
pthread_rwlock_init(&lock, NULL);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
pthread_rwlock_wrlock(&lock);
pthread_rwlock_unlock(&lock);
}
- StopBenchmarkTiming();
pthread_rwlock_destroy(&lock);
}
+BENCHMARK(BM_pthread_rwlock_write);
static void* IdleThread(void*) {
return NULL;
}
-BENCHMARK_NO_ARG(BM_pthread_create);
-void BM_pthread_create::Run(int iters) {
- StopBenchmarkTiming();
- pthread_t thread;
-
- for (int i = 0; i < iters; ++i) {
- StartBenchmarkTiming();
+static void BM_pthread_create(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ pthread_t thread;
pthread_create(&thread, NULL, IdleThread, NULL);
- StopBenchmarkTiming();
+ state.PauseTiming();
pthread_join(thread, NULL);
+ state.ResumeTiming();
}
}
+BENCHMARK(BM_pthread_create);
static void* RunThread(void* arg) {
- ::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
- benchmark->StopBenchmarkTiming();
+ benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
+ state.PauseTiming();
return NULL;
}
-BENCHMARK_NO_ARG(BM_pthread_create_and_run);
-void BM_pthread_create_and_run::Run(int iters) {
- StopBenchmarkTiming();
- pthread_t thread;
-
- for (int i = 0; i < iters; ++i) {
- StartBenchmarkTiming();
- pthread_create(&thread, NULL, RunThread, this);
+static void BM_pthread_create_and_run(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ pthread_t thread;
+ pthread_create(&thread, NULL, RunThread, &state);
pthread_join(thread, NULL);
+ state.ResumeTiming();
}
}
+BENCHMARK(BM_pthread_create_and_run);
static void* ExitThread(void* arg) {
- ::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
- benchmark->StartBenchmarkTiming();
+ benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
+ state.ResumeTiming();
pthread_exit(NULL);
}
-BENCHMARK_NO_ARG(BM_pthread_exit_and_join);
-void BM_pthread_exit_and_join::Run(int iters) {
- StopBenchmarkTiming();
- pthread_t thread;
-
- for (int i = 0; i < iters; ++i) {
- pthread_create(&thread, NULL, ExitThread, this);
+static void BM_pthread_exit_and_join(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ state.PauseTiming();
+ pthread_t thread;
+ pthread_create(&thread, NULL, ExitThread, &state);
pthread_join(thread, NULL);
- StopBenchmarkTiming();
}
}
+BENCHMARK(BM_pthread_exit_and_join);
-BENCHMARK_NO_ARG(BM_pthread_key_create);
-void BM_pthread_key_create::Run(int iters) {
- StopBenchmarkTiming();
- pthread_key_t key;
-
- for (int i = 0; i < iters; ++i) {
- StartBenchmarkTiming();
+static void BM_pthread_key_create(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ pthread_key_t key;
pthread_key_create(&key, NULL);
- StopBenchmarkTiming();
+
+ state.PauseTiming();
+ pthread_key_delete(key);
+ state.ResumeTiming();
+ }
+}
+BENCHMARK(BM_pthread_key_create);
+
+static void BM_pthread_key_delete(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ state.PauseTiming();
+ pthread_key_t key;
+ pthread_key_create(&key, NULL);
+ state.ResumeTiming();
+
pthread_key_delete(key);
}
}
-
-BENCHMARK_NO_ARG(BM_pthread_key_delete);
-void BM_pthread_key_delete::Run(int iters) {
- StopBenchmarkTiming();
- pthread_key_t key;
-
- for (int i = 0; i < iters; ++i) {
- pthread_key_create(&key, NULL);
- StartBenchmarkTiming();
- pthread_key_delete(key);
- StopBenchmarkTiming();
- }
-}
+BENCHMARK(BM_pthread_key_delete);
diff --git a/benchmarks/semaphore_benchmark.cpp b/benchmarks/semaphore_benchmark.cpp
index 8dd5684..d260803 100644
--- a/benchmarks/semaphore_benchmark.cpp
+++ b/benchmarks/semaphore_benchmark.cpp
@@ -18,101 +18,112 @@
#include <semaphore.h>
#include <stdatomic.h>
#include <stdio.h>
+#include <stdlib.h>
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
-BENCHMARK_NO_ARG(BM_semaphore_sem_getvalue);
-void BM_semaphore_sem_getvalue::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_semaphore_sem_getvalue(benchmark::State& state) {
sem_t semaphore;
sem_init(&semaphore, 1, 1);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
int dummy;
sem_getvalue(&semaphore, &dummy);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_semaphore_sem_getvalue);
-BENCHMARK_NO_ARG(BM_semaphore_sem_wait_sem_post);
-void BM_semaphore_sem_wait_sem_post::Run(int iters) {
- StopBenchmarkTiming();
+static void BM_semaphore_sem_wait_sem_post(benchmark::State& state) {
sem_t semaphore;
sem_init(&semaphore, 1, 1);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
sem_wait(&semaphore);
sem_post(&semaphore);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_semaphore_sem_wait_sem_post);
-/*
- * This test reports the overhead of the underlying futex wake syscall on
- * the producer. It does not report the overhead from issuing the wake to the
- * point where the posted consumer thread wakes up. It suffers from
- * clock_gettime syscall overhead. Lock the CPU speed for consistent results
- * as we may not reach >50% cpu utilization.
- *
- * We will run a background thread that catches the sem_post wakeup and
- * loops immediately returning back to sleep in sem_wait for the next one. This
- * thread is run with policy SCHED_OTHER (normal policy), a middle policy.
- *
- * The primary thread will run at SCHED_IDLE (lowest priority policy) when
- * monitoring the background thread to detect when it hits sem_wait sleep. It
- * will do so with no clock running. Once we are ready, we will switch to
- * SCHED_FIFO (highest priority policy) to time the act of running sem_post
- * with the benchmark clock running. This ensures nothing else in the system
- * can preempt our timed activity, including the background thread. We are
- * also protected with the scheduling policy of letting a process hit a
- * resource limit rather than get hit with a context switch.
- *
- * The background thread will start executing either on another CPU, or
- * after we back down from SCHED_FIFO, but certainly not in the context of
- * the timing of the sem_post.
- */
+// This test reports the overhead of the underlying futex wake syscall on
+// the producer. It does not report the overhead from issuing the wake to the
+// point where the posted consumer thread wakes up. It suffers from
+// clock_gettime syscall overhead. Lock the CPU speed for consistent results
+// as we may not reach >50% cpu utilization.
+//
+// We will run a background thread that catches the sem_post wakeup and
+// loops immediately returning back to sleep in sem_wait for the next one. This
+// thread is run with policy SCHED_OTHER (normal policy), a middle policy.
+//
+// The primary thread will run at SCHED_IDLE (lowest priority policy) when
+// monitoring the background thread to detect when it hits sem_wait sleep. It
+// will do so with no clock running. Once we are ready, we will switch to
+// SCHED_FIFO (highest priority policy) to time the act of running sem_post
+// with the benchmark clock running. This ensures nothing else in the system
+// can preempt our timed activity, including the background thread. We are
+// also protected with the scheduling policy of letting a process hit a
+// resource limit rather than get hit with a context switch.
+//
+// The background thread will start executing either on another CPU, or
+// after we back down from SCHED_FIFO, but certainly not in the context of
+// the timing of the sem_post.
+
static atomic_int BM_semaphore_sem_post_running;
-static void *BM_semaphore_sem_post_start_thread(void *obj) {
- sem_t *semaphore = reinterpret_cast<sem_t *>(obj);
-
- while ((BM_semaphore_sem_post_running > 0) && !sem_wait(semaphore)) {
- ;
- }
- BM_semaphore_sem_post_running = -1;
- return NULL;
+static void* BM_semaphore_sem_post_start_thread(void* arg) {
+ sem_t* semaphore = reinterpret_cast<sem_t*>(arg);
+ while ((BM_semaphore_sem_post_running > 0) && !sem_wait(semaphore)) {
+ }
+ BM_semaphore_sem_post_running = -1;
+ return NULL;
}
-BENCHMARK_NO_ARG(BM_semaphore_sem_post);
-void BM_semaphore_sem_post::Run(int iters) {
- StopBenchmarkTiming();
+class SemaphoreFixture : public benchmark::Fixture {
+ public:
+ void SetUp(const benchmark::State&) {
+ sem_init(&semaphore, 0, 0);
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+
+ memset(¶m, 0, sizeof(param));
+ pthread_attr_setschedparam(&attr, ¶m);
+ pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_t pthread;
+ pthread_create(&pthread, &attr, BM_semaphore_sem_post_start_thread, &semaphore);
+ pthread_attr_destroy(&attr);
+
+ sched_setscheduler(0, SCHED_IDLE, ¶m);
+
+ BM_semaphore_sem_post_running = 1;
+ }
+
+ ~SemaphoreFixture() {
+ sched_setscheduler(0, SCHED_OTHER, ¶m);
+
+ if (BM_semaphore_sem_post_running > 0) {
+ BM_semaphore_sem_post_running = 0;
+ }
+ do {
+ sem_post(&semaphore);
+ sched_yield();
+ } while (BM_semaphore_sem_post_running != -1);
+ }
sem_t semaphore;
- sem_init(&semaphore, 0, 0);
+ sched_param param;
+};
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- BM_semaphore_sem_post_running = 1;
- struct sched_param param = { 0, };
- pthread_attr_setschedparam(&attr, ¶m);
- pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_t pthread;
- pthread_create(&pthread, &attr, BM_semaphore_sem_post_start_thread, &semaphore);
- pthread_attr_destroy(&attr);
+BENCHMARK_F(SemaphoreFixture, semaphore_sem_post)(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ state.PauseTiming();
- sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
- for (int i = 0; i < iters; ++i) {
int trys = 3, dummy = 0;
do {
if (BM_semaphore_sem_post_running < 0) {
- sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
+ sched_setscheduler(0, SCHED_OTHER, ¶m);
fprintf(stderr, "BM_semaphore_sem_post: start_thread died unexpectedly\n");
- return;
+ abort();
}
sched_yield();
sem_getvalue(&semaphore, &dummy);
@@ -123,21 +134,14 @@
--trys;
}
} while (trys);
- param.sched_priority = 1;
- sched_setscheduler((pid_t)0, SCHED_FIFO, ¶m);
- StartBenchmarkTiming();
- sem_post(&semaphore);
- StopBenchmarkTiming(); // Remember to subtract clock syscall overhead
- param.sched_priority = 0;
- sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
- }
- sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
- if (BM_semaphore_sem_post_running > 0) {
- BM_semaphore_sem_post_running = 0;
- }
- do {
+ param.sched_priority = 1;
+ sched_setscheduler(0, SCHED_FIFO, ¶m);
+
+ state.ResumeTiming();
sem_post(&semaphore);
- sched_yield();
- } while (!BM_semaphore_sem_post_running);
+
+ param.sched_priority = 0;
+ sched_setscheduler(0, SCHED_IDLE, ¶m);
+ }
}
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp
index 69e01a9..cc07128 100644
--- a/benchmarks/stdio_benchmark.cpp
+++ b/benchmarks/stdio_benchmark.cpp
@@ -18,7 +18,7 @@
#include <stdio_ext.h>
#include <stdlib.h>
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
#define KB 1024
#define MB 1024*KB
@@ -28,50 +28,49 @@
Arg(1*KB)->Arg(4*KB)->Arg(8*KB)->Arg(16*KB)->Arg(64*KB)
template <typename Fn>
-void ReadWriteTest(::testing::Benchmark* benchmark, int iters, int chunk_size, Fn f, bool buffered) {
- benchmark->StopBenchmarkTiming();
+void ReadWriteTest(benchmark::State& state, Fn f, bool buffered) {
+ size_t chunk_size = state.range_x();
+
FILE* fp = fopen("/dev/zero", "rw");
__fsetlocking(fp, FSETLOCKING_BYCALLER);
char* buf = new char[chunk_size];
- benchmark->StartBenchmarkTiming();
if (!buffered) {
setvbuf(fp, 0, _IONBF, 0);
}
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
f(buf, chunk_size, 1, fp);
}
- benchmark->StopBenchmarkTiming();
- benchmark->SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
+ state.SetBytesProcessed(int64_t(state.iterations()) * int64_t(chunk_size));
delete[] buf;
fclose(fp);
}
-BENCHMARK_WITH_ARG(BM_stdio_fread, int)->AT_COMMON_SIZES;
-void BM_stdio_fread::Run(int iters, int chunk_size) {
- ReadWriteTest(this, iters, chunk_size, fread, true);
+void BM_stdio_fread(benchmark::State& state) {
+ ReadWriteTest(state, fread, true);
}
+BENCHMARK(BM_stdio_fread)->AT_COMMON_SIZES;
-BENCHMARK_WITH_ARG(BM_stdio_fwrite, int)->AT_COMMON_SIZES;
-void BM_stdio_fwrite::Run(int iters, int chunk_size) {
- ReadWriteTest(this, iters, chunk_size, fwrite, true);
+void BM_stdio_fwrite(benchmark::State& state) {
+ ReadWriteTest(state, fwrite, true);
}
+BENCHMARK(BM_stdio_fwrite)->AT_COMMON_SIZES;
-BENCHMARK_WITH_ARG(BM_stdio_fread_unbuffered, int)->AT_COMMON_SIZES;
-void BM_stdio_fread_unbuffered::Run(int iters, int chunk_size) {
- ReadWriteTest(this, iters, chunk_size, fread, false);
+void BM_stdio_fread_unbuffered(benchmark::State& state) {
+ ReadWriteTest(state, fread, false);
}
+BENCHMARK(BM_stdio_fread_unbuffered)->AT_COMMON_SIZES;
-BENCHMARK_WITH_ARG(BM_stdio_fwrite_unbuffered, int)->AT_COMMON_SIZES;
-void BM_stdio_fwrite_unbuffered::Run(int iters, int chunk_size) {
- ReadWriteTest(this, iters, chunk_size, fwrite, false);
+void BM_stdio_fwrite_unbuffered(benchmark::State& state) {
+ ReadWriteTest(state, fwrite, false);
}
+BENCHMARK(BM_stdio_fwrite_unbuffered)->AT_COMMON_SIZES;
-static void FopenFgetsFclose(int iters, bool no_locking) {
+static void FopenFgetsFclose(benchmark::State& state, bool no_locking) {
char buf[1024];
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
FILE* fp = fopen("/proc/version", "re");
if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
@@ -79,16 +78,12 @@
}
}
-BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_locking);
-void BM_stdio_fopen_fgets_fclose_locking::Run(int iters) {
- StartBenchmarkTiming();
- FopenFgetsFclose(iters, false);
- StopBenchmarkTiming();
+static void BM_stdio_fopen_fgets_fclose_locking(benchmark::State& state) {
+ FopenFgetsFclose(state, false);
}
+BENCHMARK(BM_stdio_fopen_fgets_fclose_locking);
-BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_no_locking);
-void BM_stdio_fopen_fgets_fclose_no_locking::Run(int iters) {
- StartBenchmarkTiming();
- FopenFgetsFclose(iters, true);
- StopBenchmarkTiming();
+void BM_stdio_fopen_fgets_fclose_no_locking(benchmark::State& state) {
+ FopenFgetsFclose(state, true);
}
+BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking);
diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp
index 866aa00..c04409d 100644
--- a/benchmarks/string_benchmark.cpp
+++ b/benchmarks/string_benchmark.cpp
@@ -17,7 +17,7 @@
#include <stdint.h>
#include <string.h>
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
#define KB 1024
#define MB 1024*KB
@@ -27,87 +27,77 @@
// TODO: test unaligned operation too? (currently everything will be 8-byte aligned by malloc.)
-BENCHMARK_WITH_ARG(BM_string_memcmp, int)->AT_COMMON_SIZES;
-void BM_string_memcmp::Run(int iters, int nbytes) {
- StopBenchmarkTiming();
+static void BM_string_memcmp(benchmark::State& state) {
+ const size_t nbytes = state.range_x();
char* src = new char[nbytes]; char* dst = new char[nbytes];
memset(src, 'x', nbytes);
memset(dst, 'x', nbytes);
- StartBenchmarkTiming();
volatile int c __attribute__((unused)) = 0;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
c += memcmp(dst, src, nbytes);
}
- StopBenchmarkTiming();
- SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
+ state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
delete[] src;
delete[] dst;
}
+BENCHMARK(BM_string_memcmp)->AT_COMMON_SIZES;
-BENCHMARK_WITH_ARG(BM_string_memcpy, int)->AT_COMMON_SIZES;
-void BM_string_memcpy::Run(int iters, int nbytes) {
- StopBenchmarkTiming();
+static void BM_string_memcpy(benchmark::State& state) {
+ const size_t nbytes = state.range_x();
char* src = new char[nbytes]; char* dst = new char[nbytes];
memset(src, 'x', nbytes);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
memcpy(dst, src, nbytes);
}
- StopBenchmarkTiming();
- SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
+ state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
delete[] src;
delete[] dst;
}
+BENCHMARK(BM_string_memcpy)->AT_COMMON_SIZES;
-BENCHMARK_WITH_ARG(BM_string_memmove, int)->AT_COMMON_SIZES;
-void BM_string_memmove::Run(int iters, int nbytes) {
- StopBenchmarkTiming();
+static void BM_string_memmove(benchmark::State& state) {
+ const size_t nbytes = state.range_x();
char* buf = new char[nbytes + 64];
memset(buf, 'x', nbytes + 64);
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
memmove(buf, buf + 1, nbytes); // Worst-case overlap.
}
- StopBenchmarkTiming();
- SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
+ state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
delete[] buf;
}
+BENCHMARK(BM_string_memmove)->AT_COMMON_SIZES;
-BENCHMARK_WITH_ARG(BM_string_memset, int)->AT_COMMON_SIZES;
-void BM_string_memset::Run(int iters, int nbytes) {
- StopBenchmarkTiming();
+static void BM_string_memset(benchmark::State& state) {
+ const size_t nbytes = state.range_x();
char* dst = new char[nbytes];
- StartBenchmarkTiming();
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
memset(dst, 0, nbytes);
}
- StopBenchmarkTiming();
- SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
+ state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
delete[] dst;
}
+BENCHMARK(BM_string_memset)->AT_COMMON_SIZES;
-BENCHMARK_WITH_ARG(BM_string_strlen, int)->AT_COMMON_SIZES;
-void BM_string_strlen::Run(int iters, int nbytes) {
- StopBenchmarkTiming();
+static void BM_string_strlen(benchmark::State& state) {
+ const size_t nbytes = state.range_x();
char* s = new char[nbytes];
memset(s, 'x', nbytes);
s[nbytes - 1] = 0;
- StartBenchmarkTiming();
volatile int c __attribute__((unused)) = 0;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
c += strlen(s);
}
- StopBenchmarkTiming();
- SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
+ state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
delete[] s;
}
+BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index 1b0d08d..4a5c2da 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -19,63 +19,43 @@
#include <time.h>
#include <unistd.h>
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
-BENCHMARK_NO_ARG(BM_time_clock_gettime);
-void BM_time_clock_gettime::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_time_clock_gettime(benchmark::State& state) {
timespec t;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
clock_gettime(CLOCK_MONOTONIC, &t);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_time_clock_gettime);
-BENCHMARK_NO_ARG(BM_time_clock_gettime_syscall);
-void BM_time_clock_gettime_syscall::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_time_clock_gettime_syscall(benchmark::State& state) {
timespec t;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_time_clock_gettime_syscall);
-BENCHMARK_NO_ARG(BM_time_gettimeofday);
-void BM_time_gettimeofday::Run(int iters) {
- StartBenchmarkTiming();
-
+static void BM_time_gettimeofday(benchmark::State& state) {
timeval tv;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
gettimeofday(&tv, NULL);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_time_gettimeofday);
-BENCHMARK_NO_ARG(BM_time_gettimeofday_syscall);
-void BM_time_gettimeofday_syscall::Run(int iters) {
- StartBenchmarkTiming();
-
+void BM_time_gettimeofday_syscall(benchmark::State& state) {
timeval tv;
- for (int i = 0; i < iters; ++i) {
+ while (state.KeepRunning()) {
syscall(__NR_gettimeofday, &tv, NULL);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_time_gettimeofday_syscall);
-BENCHMARK_NO_ARG(BM_time_time);
-void BM_time_time::Run(int iters) {
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; ++i) {
+void BM_time_time(benchmark::State& state) {
+ while (state.KeepRunning()) {
time(NULL);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_time_time);
diff --git a/benchmarks/unistd_benchmark.cpp b/benchmarks/unistd_benchmark.cpp
index 09ca0e6..b78d3eb 100644
--- a/benchmarks/unistd_benchmark.cpp
+++ b/benchmarks/unistd_benchmark.cpp
@@ -17,55 +17,41 @@
#include <sys/syscall.h>
#include <unistd.h>
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
-BENCHMARK_NO_ARG(BM_unistd_getpid);
-void BM_unistd_getpid::Run(int iters) {
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; ++i) {
+static void BM_unistd_getpid(benchmark::State& state) {
+ while (state.KeepRunning()) {
getpid();
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_unistd_getpid);
-BENCHMARK_NO_ARG(BM_unistd_getpid_syscall);
-void BM_unistd_getpid_syscall::Run(int iters) {
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; ++i) {
+static void BM_unistd_getpid_syscall(benchmark::State& state) {
+ while (state.KeepRunning()) {
syscall(__NR_getpid);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_unistd_getpid_syscall);
#if defined(__BIONIC__)
// Stop GCC optimizing out our pure function.
/* Must not be static! */ pid_t (*gettid_fp)() = gettid;
-BENCHMARK_NO_ARG(BM_unistd_gettid);
-void BM_unistd_gettid::Run(int iters) {
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; ++i) {
+static void BM_unistd_gettid(benchmark::State& state) {
+ while (state.KeepRunning()) {
gettid_fp();
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_unistd_gettid);
#endif
-BENCHMARK_NO_ARG(BM_unistd_gettid_syscall);
-void BM_unistd_gettid_syscall::Run(int iters) {
- StartBenchmarkTiming();
-
- for (int i = 0; i < iters; ++i) {
+void BM_unistd_gettid_syscall(benchmark::State& state) {
+ while (state.KeepRunning()) {
syscall(__NR_gettid);
}
-
- StopBenchmarkTiming();
}
+BENCHMARK(BM_unistd_gettid_syscall);
+
+BENCHMARK_MAIN()
diff --git a/benchmarks/utils.cpp b/benchmarks/utils.cpp
deleted file mode 100644
index 8bbd20a..0000000
--- a/benchmarks/utils.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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 "utils.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <string>
-
-#include <android-base/stringprintf.h>
-
-int Round(int n) {
- int base = 1;
- while (base*10 < n) {
- base *= 10;
- }
- if (n < 2*base) {
- return 2*base;
- }
- if (n < 5*base) {
- return 5*base;
- }
- return 10*base;
-}
-
-// Similar to the code in art, but supporting both binary and decimal prefixes.
-std::string PrettyInt(long value, size_t base) {
- if (base != 2 && base != 10) abort();
-
- uint64_t count = static_cast<uint64_t>(value);
- bool negative_number = false;
- if (value < 0) {
- negative_number = true;
- count = static_cast<uint64_t>(-value);
- }
-
- // The byte thresholds at which we display amounts. A count is displayed
- // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
- static const uint64_t kUnitThresholds2[] = {
- 1024*1024*1024 /* Gi */, 2*1024*1024 /* Mi */, 3*1024 /* Ki */, 0,
- };
- static const uint64_t kUnitThresholds10[] = {
- 1000*1000*1000 /* G */, 2*1000*1000 /* M */, 3*1000 /* k */, 0,
- };
- static const uint64_t kAmountPerUnit2[] = { 1024*1024*1024, 1024*1024, 1024, 1 };
- static const uint64_t kAmountPerUnit10[] = { 1000*1000*1000, 1000*1000, 1000, 1 };
- static const char* const kUnitStrings2[] = { "Gi", "Mi", "Ki", "" };
- static const char* const kUnitStrings10[] = { "G", "M", "k", "" };
-
- // Which set are we using?
- const uint64_t* kUnitThresholds = ((base == 2) ? kUnitThresholds2 : kUnitThresholds10);
- const uint64_t* kAmountPerUnit = ((base == 2) ? kAmountPerUnit2 : kAmountPerUnit10);
- const char* const* kUnitStrings = ((base == 2) ? kUnitStrings2 : kUnitStrings10);
-
- size_t i = 0;
- for (; kUnitThresholds[i] != 0; ++i) {
- if (count >= kUnitThresholds[i]) {
- break;
- }
- }
- return android::base::StringPrintf("%s%" PRId64 "%s",
- negative_number ? "-" : "",
- count / kAmountPerUnit[i], kUnitStrings[i]);
-}
diff --git a/benchmarks/utils.h b/benchmarks/utils.h
deleted file mode 100644
index c3c64ba..0000000
--- a/benchmarks/utils.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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 BENCHMARKS_UTILS_H
-#define BENCHMARKS_UTILS_H
-
-#include <stddef.h>
-#include <string>
-
-int Round(int n);
-std::string PrettyInt(long value, size_t base);
-
-#endif // BENCHMARKS_UTILS_H