summaryrefslogtreecommitdiffstats
path: root/libcxx/utils/google-benchmark/src
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/utils/google-benchmark/src')
-rw-r--r--libcxx/utils/google-benchmark/src/CMakeLists.txt25
-rw-r--r--libcxx/utils/google-benchmark/src/benchmark.cc206
-rw-r--r--libcxx/utils/google-benchmark/src/benchmark_api_internal.h2
-rw-r--r--libcxx/utils/google-benchmark/src/benchmark_main.cc17
-rw-r--r--libcxx/utils/google-benchmark/src/benchmark_register.cc83
-rw-r--r--libcxx/utils/google-benchmark/src/benchmark_register.h33
-rw-r--r--libcxx/utils/google-benchmark/src/check.h5
-rw-r--r--libcxx/utils/google-benchmark/src/commandlineflags.cc2
-rw-r--r--libcxx/utils/google-benchmark/src/complexity.cc25
-rw-r--r--libcxx/utils/google-benchmark/src/counter.cc25
-rw-r--r--libcxx/utils/google-benchmark/src/counter.h8
-rw-r--r--libcxx/utils/google-benchmark/src/csv_reporter.cc20
-rw-r--r--libcxx/utils/google-benchmark/src/cycleclock.h7
-rw-r--r--libcxx/utils/google-benchmark/src/internal_macros.h20
-rw-r--r--libcxx/utils/google-benchmark/src/json_reporter.cc46
-rw-r--r--libcxx/utils/google-benchmark/src/log.h3
-rw-r--r--libcxx/utils/google-benchmark/src/re.h44
-rw-r--r--libcxx/utils/google-benchmark/src/reporter.cc6
-rw-r--r--libcxx/utils/google-benchmark/src/statistics.cc46
-rw-r--r--libcxx/utils/google-benchmark/src/string_util.cc95
-rw-r--r--libcxx/utils/google-benchmark/src/string_util.h28
-rw-r--r--libcxx/utils/google-benchmark/src/sysinfo.cc86
-rw-r--r--libcxx/utils/google-benchmark/src/thread_manager.h66
-rw-r--r--libcxx/utils/google-benchmark/src/thread_timer.h69
-rw-r--r--libcxx/utils/google-benchmark/src/timers.cc11
25 files changed, 666 insertions, 312 deletions
diff --git a/libcxx/utils/google-benchmark/src/CMakeLists.txt b/libcxx/utils/google-benchmark/src/CMakeLists.txt
index e22620a7291..977474f43f2 100644
--- a/libcxx/utils/google-benchmark/src/CMakeLists.txt
+++ b/libcxx/utils/google-benchmark/src/CMakeLists.txt
@@ -11,6 +11,10 @@ file(GLOB
*.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})
set_target_properties(benchmark PROPERTIES
@@ -34,6 +38,23 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
target_link_libraries(benchmark Shlwapi)
endif()
+# We need extra libraries on Solaris
+if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
+ target_link_libraries(benchmark kstat)
+endif()
+
+# Benchmark main library
+add_library(benchmark_main "benchmark_main.cc")
+set_target_properties(benchmark_main PROPERTIES
+ OUTPUT_NAME "benchmark_main"
+ VERSION ${GENERIC_LIB_VERSION}
+ SOVERSION ${GENERIC_LIB_SOVERSION}
+)
+target_include_directories(benchmark PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
+ )
+target_link_libraries(benchmark_main benchmark)
+
set(include_install_dir "include")
set(lib_install_dir "lib/")
set(bin_install_dir "bin/")
@@ -51,7 +72,7 @@ set(namespace "${PROJECT_NAME}::")
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
- "${version_config}" VERSION ${GIT_VERSION} COMPATIBILITY SameMajorVersion
+ "${version_config}" VERSION ${GENERIC_LIB_VERSION} COMPATIBILITY SameMajorVersion
)
configure_file("${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in" "${project_config}" @ONLY)
@@ -60,7 +81,7 @@ configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark.pc.in" "${pkg_config}" @ON
if (BENCHMARK_ENABLE_INSTALL)
# Install target (will install the library to specified CMAKE_INSTALL_PREFIX variable)
install(
- TARGETS benchmark
+ TARGETS benchmark benchmark_main
EXPORT ${targets_export_name}
ARCHIVE DESTINATION ${lib_install_dir}
LIBRARY DESTINATION ${lib_install_dir}
diff --git a/libcxx/utils/google-benchmark/src/benchmark.cc b/libcxx/utils/google-benchmark/src/benchmark.cc
index 1a7d218283c..b14bc629143 100644
--- a/libcxx/utils/google-benchmark/src/benchmark.cc
+++ b/libcxx/utils/google-benchmark/src/benchmark.cc
@@ -17,7 +17,9 @@
#include "internal_macros.h"
#ifndef BENCHMARK_OS_WINDOWS
+#ifndef BENCHMARK_OS_FUCHSIA
#include <sys/resource.h>
+#endif
#include <sys/time.h>
#include <unistd.h>
#endif
@@ -27,10 +29,10 @@
#include <condition_variable>
#include <cstdio>
#include <cstdlib>
-#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
+#include <string>
#include <thread>
#include "check.h"
@@ -44,7 +46,8 @@
#include "re.h"
#include "statistics.h"
#include "string_util.h"
-#include "timers.h"
+#include "thread_manager.h"
+#include "thread_timer.h"
DEFINE_bool(benchmark_list_tests, false,
"Print a list of benchmarks. This option overrides all other "
@@ -82,7 +85,7 @@ DEFINE_string(benchmark_out_format, "json",
"The format to use for file output. Valid values are "
"'console', 'json', or 'csv'.");
-DEFINE_string(benchmark_out, "", "The file to write additonal output to");
+DEFINE_string(benchmark_out, "", "The file to write additional output to");
DEFINE_string(benchmark_color, "auto",
"Whether to use colors in the output. Valid values: "
@@ -108,119 +111,11 @@ namespace internal {
void UseCharPointer(char const volatile*) {}
-class ThreadManager {
- public:
- ThreadManager(int num_threads)
- : alive_threads_(num_threads), start_stop_barrier_(num_threads) {}
-
- Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) {
- return benchmark_mutex_;
- }
-
- bool StartStopBarrier() EXCLUDES(end_cond_mutex_) {
- return start_stop_barrier_.wait();
- }
-
- void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) {
- start_stop_barrier_.removeThread();
- if (--alive_threads_ == 0) {
- MutexLock lock(end_cond_mutex_);
- end_condition_.notify_all();
- }
- }
-
- void WaitForAllThreads() EXCLUDES(end_cond_mutex_) {
- MutexLock lock(end_cond_mutex_);
- end_condition_.wait(lock.native_handle(),
- [this]() { return alive_threads_ == 0; });
- }
-
- public:
- struct Result {
- double real_time_used = 0;
- double cpu_time_used = 0;
- double manual_time_used = 0;
- int64_t bytes_processed = 0;
- int64_t items_processed = 0;
- int complexity_n = 0;
- std::string report_label_;
- std::string error_message_;
- bool has_error_ = false;
- UserCounters counters;
- };
- GUARDED_BY(GetBenchmarkMutex()) Result results;
-
- private:
- mutable Mutex benchmark_mutex_;
- std::atomic<int> alive_threads_;
- Barrier start_stop_barrier_;
- Mutex end_cond_mutex_;
- Condition end_condition_;
-};
-
-// Timer management class
-class ThreadTimer {
- public:
- ThreadTimer() = default;
-
- // Called by each thread
- void StartTimer() {
- running_ = true;
- start_real_time_ = ChronoClockNow();
- start_cpu_time_ = ThreadCPUUsage();
- }
-
- // Called by each thread
- void StopTimer() {
- CHECK(running_);
- running_ = false;
- real_time_used_ += ChronoClockNow() - start_real_time_;
- // Floating point error can result in the subtraction producing a negative
- // time. Guard against that.
- cpu_time_used_ += std::max<double>(ThreadCPUUsage() - start_cpu_time_, 0);
- }
-
- // Called by each thread
- void SetIterationTime(double seconds) { manual_time_used_ += seconds; }
-
- bool running() const { return running_; }
-
- // REQUIRES: timer is not running
- double real_time_used() {
- CHECK(!running_);
- return real_time_used_;
- }
-
- // REQUIRES: timer is not running
- double cpu_time_used() {
- CHECK(!running_);
- return cpu_time_used_;
- }
-
- // REQUIRES: timer is not running
- double manual_time_used() {
- CHECK(!running_);
- return manual_time_used_;
- }
-
- private:
- bool running_ = false; // Is the timer running
- double start_real_time_ = 0; // If running_
- double start_cpu_time_ = 0; // If running_
-
- // Accumulated time so far (does not contain current slice if running_)
- double real_time_used_ = 0;
- double cpu_time_used_ = 0;
- // Manually set iteration time. User sets this with SetIterationTime(seconds).
- double manual_time_used_ = 0;
-};
-
namespace {
BenchmarkReporter::Run CreateRunReport(
const benchmark::internal::Benchmark::Instance& b,
- const internal::ThreadManager::Result& results, size_t iters,
- double seconds) {
+ const internal::ThreadManager::Result& results, double seconds) {
// Create report about this benchmark run.
BenchmarkReporter::Run report;
@@ -228,8 +123,8 @@ BenchmarkReporter::Run CreateRunReport(
report.error_occurred = results.has_error_;
report.error_message = results.error_message_;
report.report_label = results.report_label_;
- // Report the total iterations across all threads.
- report.iterations = static_cast<int64_t>(iters) * b.threads;
+ // This is the total iterations across all threads.
+ report.iterations = results.iterations;
report.time_unit = b.time_unit;
if (!report.error_occurred) {
@@ -255,7 +150,7 @@ BenchmarkReporter::Run CreateRunReport(
report.complexity_lambda = b.complexity_lambda;
report.statistics = b.statistics;
report.counters = results.counters;
- internal::Finish(&report.counters, seconds, b.threads);
+ internal::Finish(&report.counters, results.iterations, seconds, b.threads);
}
return report;
}
@@ -268,11 +163,12 @@ void RunInThread(const benchmark::internal::Benchmark::Instance* b,
internal::ThreadTimer timer;
State st(iters, b->arg, thread_id, b->threads, &timer, manager);
b->benchmark->Run(st);
- CHECK(st.iterations() == st.max_iterations)
+ CHECK(st.iterations() >= st.max_iterations)
<< "Benchmark returned before State::KeepRunning() returned false!";
{
MutexLock l(manager->GetBenchmarkMutex());
internal::ThreadManager::Result& results = manager->results;
+ results.iterations += st.iterations();
results.cpu_time_used += timer.cpu_time_used();
results.real_time_used += timer.real_time_used();
results.manual_time_used += timer.manual_time_used();
@@ -337,21 +233,23 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
const double min_time =
!IsZero(b.min_time) ? b.min_time : FLAGS_benchmark_min_time;
+ // clang-format off
+ // turn off clang-format since it mangles prettiness here
// Determine if this run should be reported; Either it has
// run for a sufficient amount of time or because an error was reported.
const bool should_report = repetition_num > 0
- || has_explicit_iteration_count // An exact iteration count was requested
+ || has_explicit_iteration_count // An exact iteration count was requested
|| results.has_error_
- || iters >= kMaxIterations
- || seconds >= min_time // the elapsed time is large enough
+ || iters >= kMaxIterations // No chance to try again, we hit the limit.
+ || seconds >= min_time // the elapsed time is large enough
// CPU time is specified but the elapsed real time greatly exceeds the
// minimum time. Note that user provided timers are except from this
// sanity check.
|| ((results.real_time_used >= 5 * min_time) && !b.use_manual_time);
+ // clang-format on
if (should_report) {
- BenchmarkReporter::Run report =
- CreateRunReport(b, results, iters, seconds);
+ BenchmarkReporter::Run report = CreateRunReport(b, results, seconds);
if (!report.error_occurred && b.complexity != oNone)
complexity_reports->push_back(report);
reports.push_back(report);
@@ -394,26 +292,50 @@ std::vector<BenchmarkReporter::Run> RunBenchmark(
} // namespace
} // namespace internal
-State::State(size_t max_iters, const std::vector<int>& ranges, int thread_i,
+State::State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i,
int n_threads, internal::ThreadTimer* timer,
internal::ThreadManager* manager)
- : started_(false),
+ : total_iterations_(0),
+ batch_leftover_(0),
+ max_iterations(max_iters),
+ started_(false),
finished_(false),
- total_iterations_(max_iters + 1),
+ error_occurred_(false),
range_(ranges),
bytes_processed_(0),
items_processed_(0),
complexity_n_(0),
- error_occurred_(false),
counters(),
thread_index(thread_i),
threads(n_threads),
- max_iterations(max_iters),
timer_(timer),
manager_(manager) {
CHECK(max_iterations != 0) << "At least one iteration must be run";
- CHECK(total_iterations_ != 0) << "max iterations wrapped around";
CHECK_LT(thread_index, threads) << "thread_index must be less than threads";
+
+ // 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__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#endif
+ // Offset tests to ensure commonly accessed data is on the first cache line.
+ const int cache_line_size = 64;
+ static_assert(offsetof(State, error_occurred_) <=
+ (cache_line_size - sizeof(error_occurred_)),
+ "");
+#if defined(__INTEL_COMPILER)
+#pragma warning pop
+#elif defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
}
void State::PauseTiming() {
@@ -437,7 +359,7 @@ void State::SkipWithError(const char* msg) {
manager_->results.has_error_ = true;
}
}
- total_iterations_ = 1;
+ total_iterations_ = 0;
if (timer_->running()) timer_->StopTimer();
}
@@ -453,6 +375,7 @@ void State::SetLabel(const char* label) {
void State::StartKeepRunning() {
CHECK(!started_ && !finished_);
started_ = true;
+ total_iterations_ = error_occurred_ ? 0 : max_iterations;
manager_->StartStopBarrier();
if (!error_occurred_) ResumeTiming();
}
@@ -462,8 +385,8 @@ void State::FinishKeepRunning() {
if (!error_occurred_) {
PauseTiming();
}
- // Total iterations has now wrapped around zero. Fix this.
- total_iterations_ = 1;
+ // Total iterations has now wrapped around past 0. Fix this.
+ total_iterations_ = 0;
finished_ = true;
manager_->StartStopBarrier();
}
@@ -472,8 +395,8 @@ namespace internal {
namespace {
void RunBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
- BenchmarkReporter* console_reporter,
- BenchmarkReporter* file_reporter) {
+ BenchmarkReporter* console_reporter,
+ BenchmarkReporter* file_reporter) {
// Note the file_reporter can be null.
CHECK(console_reporter != nullptr);
@@ -486,7 +409,7 @@ void RunBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
std::max<size_t>(name_field_width, benchmark.name.size());
has_repetitions |= benchmark.repetitions > 1;
- for(const auto& Stat : *benchmark.statistics)
+ for (const auto& Stat : *benchmark.statistics)
stat_field_width = std::max<size_t>(stat_field_width, Stat.name_.size());
}
if (has_repetitions) name_field_width += 1 + stat_field_width;
@@ -495,7 +418,7 @@ void RunBenchmarks(const std::vector<Benchmark::Instance>& benchmarks,
BenchmarkReporter::Context context;
context.name_field_width = name_field_width;
- // Keep track of runing times of all instances of current benchmark
+ // Keep track of running times of all instances of current benchmark
std::vector<BenchmarkReporter::Run> complexity_reports;
// We flush streams after invoking reporter methods that write to them. This
@@ -554,15 +477,15 @@ ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) {
} else {
output_opts &= ~ConsoleReporter::OO_Color;
}
- if(force_no_color) {
+ if (force_no_color) {
output_opts &= ~ConsoleReporter::OO_Color;
}
- if(FLAGS_benchmark_counters_tabular) {
+ if (FLAGS_benchmark_counters_tabular) {
output_opts |= ConsoleReporter::OO_Tabular;
} else {
output_opts &= ~ConsoleReporter::OO_Tabular;
}
- return static_cast< ConsoleReporter::OutputOptions >(output_opts);
+ return static_cast<ConsoleReporter::OutputOptions>(output_opts);
}
} // end namespace internal
@@ -587,7 +510,7 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter,
std::unique_ptr<BenchmarkReporter> default_file_reporter;
if (!console_reporter) {
default_console_reporter = internal::CreateReporter(
- FLAGS_benchmark_format, internal::GetOutputOptions());
+ FLAGS_benchmark_format, internal::GetOutputOptions());
console_reporter = default_console_reporter.get();
}
auto& Out = console_reporter->GetOutputStream();
@@ -653,6 +576,8 @@ void PrintUsageAndExit() {
void ParseCommandLineFlags(int* argc, char** argv) {
using namespace benchmark;
+ BenchmarkReporter::Context::executable_name =
+ (argc && *argc > 0) ? argv[0] : "unknown";
for (int i = 1; i < *argc; ++i) {
if (ParseBoolFlag(argv[i], "benchmark_list_tests",
&FLAGS_benchmark_list_tests) ||
@@ -672,7 +597,7 @@ void ParseCommandLineFlags(int* argc, char** argv) {
// TODO: Remove this.
ParseStringFlag(argv[i], "color_print", &FLAGS_benchmark_color) ||
ParseBoolFlag(argv[i], "benchmark_counters_tabular",
- &FLAGS_benchmark_counters_tabular) ||
+ &FLAGS_benchmark_counters_tabular) ||
ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1];
@@ -706,7 +631,8 @@ void Initialize(int* argc, char** argv) {
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]);
+ fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0],
+ argv[i]);
}
return argc > 1;
}
diff --git a/libcxx/utils/google-benchmark/src/benchmark_api_internal.h b/libcxx/utils/google-benchmark/src/benchmark_api_internal.h
index d481dc52864..dd7a3ffe8cb 100644
--- a/libcxx/utils/google-benchmark/src/benchmark_api_internal.h
+++ b/libcxx/utils/google-benchmark/src/benchmark_api_internal.h
@@ -17,7 +17,7 @@ struct Benchmark::Instance {
std::string name;
Benchmark* benchmark;
ReportMode report_mode;
- std::vector<int> arg;
+ std::vector<int64_t> arg;
TimeUnit time_unit;
int range_multiplier;
bool use_real_time;
diff --git a/libcxx/utils/google-benchmark/src/benchmark_main.cc b/libcxx/utils/google-benchmark/src/benchmark_main.cc
new file mode 100644
index 00000000000..b3b24783149
--- /dev/null
+++ b/libcxx/utils/google-benchmark/src/benchmark_main.cc
@@ -0,0 +1,17 @@
+// Copyright 2018 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.h"
+
+BENCHMARK_MAIN();
diff --git a/libcxx/utils/google-benchmark/src/benchmark_register.cc b/libcxx/utils/google-benchmark/src/benchmark_register.cc
index d5746a3632a..26a89721c78 100644
--- a/libcxx/utils/google-benchmark/src/benchmark_register.cc
+++ b/libcxx/utils/google-benchmark/src/benchmark_register.cc
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "benchmark/benchmark.h"
-#include "benchmark_api_internal.h"
-#include "internal_macros.h"
+#include "benchmark_register.h"
#ifndef BENCHMARK_OS_WINDOWS
+#ifndef BENCHMARK_OS_FUCHSIA
#include <sys/resource.h>
+#endif
#include <sys/time.h>
#include <unistd.h>
#endif
@@ -34,13 +34,16 @@
#include <sstream>
#include <thread>
+#include "benchmark/benchmark.h"
+#include "benchmark_api_internal.h"
#include "check.h"
#include "commandlineflags.h"
#include "complexity.h"
-#include "statistics.h"
+#include "internal_macros.h"
#include "log.h"
#include "mutex.h"
#include "re.h"
+#include "statistics.h"
#include "string_util.h"
#include "timers.h"
@@ -74,7 +77,7 @@ class BenchmarkFamilies {
// Extract the list of benchmark instances that match the specified
// regular expression.
- bool FindBenchmarks(const std::string& re,
+ bool FindBenchmarks(std::string re,
std::vector<Benchmark::Instance>* benchmarks,
std::ostream* Err);
@@ -104,13 +107,18 @@ void BenchmarkFamilies::ClearBenchmarks() {
}
bool BenchmarkFamilies::FindBenchmarks(
- const std::string& spec, std::vector<Benchmark::Instance>* benchmarks,
+ std::string spec, std::vector<Benchmark::Instance>* benchmarks,
std::ostream* ErrStream) {
CHECK(ErrStream);
auto& Err = *ErrStream;
// Make regular expression out of command-line flag
std::string error_msg;
Regex re;
+ bool isNegativeFilter = false;
+ if (spec[0] == '-') {
+ spec.replace(0, 1, "");
+ isNegativeFilter = true;
+ }
if (!re.Init(spec, &error_msg)) {
Err << "Could not compile benchmark re: " << error_msg << std::endl;
return false;
@@ -170,20 +178,20 @@ bool BenchmarkFamilies::FindBenchmarks(
const auto& arg_name = family->arg_names_[arg_i];
if (!arg_name.empty()) {
instance.name +=
- StringPrintF("%s:", family->arg_names_[arg_i].c_str());
+ StrFormat("%s:", family->arg_names_[arg_i].c_str());
}
}
-
- instance.name += StringPrintF("%d", arg);
+
+ instance.name += StrFormat("%d", arg);
++arg_i;
}
if (!IsZero(family->min_time_))
- instance.name += StringPrintF("/min_time:%0.3f", family->min_time_);
+ instance.name += StrFormat("/min_time:%0.3f", family->min_time_);
if (family->iterations_ != 0)
- instance.name += StringPrintF("/iterations:%d", family->iterations_);
+ instance.name += StrFormat("/iterations:%d", family->iterations_);
if (family->repetitions_ != 0)
- instance.name += StringPrintF("/repeats:%d", family->repetitions_);
+ instance.name += StrFormat("/repeats:%d", family->repetitions_);
if (family->use_manual_time_) {
instance.name += "/manual_time";
@@ -193,10 +201,11 @@ bool BenchmarkFamilies::FindBenchmarks(
// Add the number of threads used to the name
if (!family->thread_counts_.empty()) {
- instance.name += StringPrintF("/threads:%d", instance.threads);
+ instance.name += StrFormat("/threads:%d", instance.threads);
}
- if (re.Match(instance.name)) {
+ if ((re.Match(instance.name) && !isNegativeFilter) ||
+ (!re.Match(instance.name) && isNegativeFilter)) {
instance.last_benchmark_instance = (&args == &family->args_.back());
benchmarks->push_back(std::move(instance));
}
@@ -244,30 +253,7 @@ Benchmark::Benchmark(const char* name)
Benchmark::~Benchmark() {}
-void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
- CHECK_GE(lo, 0);
- CHECK_GE(hi, lo);
- CHECK_GE(mult, 2);
-
- // Add "lo"
- dst->push_back(lo);
-
- static const int kint32max = std::numeric_limits<int32_t>::max();
-
- // Now space out the benchmarks in multiples of "mult"
- for (int32_t i = 1; i < kint32max / mult; i *= mult) {
- if (i >= hi) break;
- if (i > lo) {
- dst->push_back(i);
- }
- }
- // Add "hi" (if different from "lo")
- if (hi != lo) {
- dst->push_back(hi);
- }
-}
-
-Benchmark* Benchmark::Arg(int x) {
+Benchmark* Benchmark::Arg(int64_t x) {
CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
args_.push_back({x});
return this;
@@ -278,20 +264,21 @@ Benchmark* Benchmark::Unit(TimeUnit unit) {
return this;
}
-Benchmark* Benchmark::Range(int start, int limit) {
+Benchmark* Benchmark::Range(int64_t start, int64_t limit) {
CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
- std::vector<int> arglist;
+ std::vector<int64_t> arglist;
AddRange(&arglist, start, limit, range_multiplier_);
- for (int i : arglist) {
+ for (int64_t i : arglist) {
args_.push_back({i});
}
return this;
}
-Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges) {
+Benchmark* Benchmark::Ranges(
+ const std::vector<std::pair<int64_t, int64_t>>& ranges) {
CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(ranges.size()));
- std::vector<std::vector<int>> arglists(ranges.size());
+ std::vector<std::vector<int64_t>> arglists(ranges.size());
std::size_t total = 1;
for (std::size_t i = 0; i < ranges.size(); i++) {
AddRange(&arglists[i], ranges[i].first, ranges[i].second,
@@ -302,7 +289,7 @@ Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges) {
std::vector<std::size_t> ctr(arglists.size(), 0);
for (std::size_t i = 0; i < total; i++) {
- std::vector<int> tmp;
+ std::vector<int64_t> tmp;
tmp.reserve(arglists.size());
for (std::size_t j = 0; j < arglists.size(); j++) {
@@ -334,17 +321,17 @@ Benchmark* Benchmark::ArgNames(const std::vector<std::string>& names) {
return this;
}
-Benchmark* Benchmark::DenseRange(int start, int limit, int step) {
+Benchmark* Benchmark::DenseRange(int64_t start, int64_t limit, int step) {
CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
CHECK_GE(start, 0);
CHECK_LE(start, limit);
- for (int arg = start; arg <= limit; arg += step) {
+ for (int64_t arg = start; arg <= limit; arg += step) {
args_.push_back({arg});
}
return this;
}
-Benchmark* Benchmark::Args(const std::vector<int>& args) {
+Benchmark* Benchmark::Args(const std::vector<int64_t>& args) {
CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(args.size()));
args_.push_back(args);
return this;
@@ -361,7 +348,6 @@ Benchmark* Benchmark::RangeMultiplier(int multiplier) {
return this;
}
-
Benchmark* Benchmark::MinTime(double t) {
CHECK(t > 0.0);
CHECK(iterations_ == 0);
@@ -369,7 +355,6 @@ Benchmark* Benchmark::MinTime(double t) {
return this;
}
-
Benchmark* Benchmark::Iterations(size_t n) {
CHECK(n > 0);
CHECK(IsZero(min_time_));
diff --git a/libcxx/utils/google-benchmark/src/benchmark_register.h b/libcxx/utils/google-benchmark/src/benchmark_register.h
new file mode 100644
index 00000000000..0705e219f2f
--- /dev/null
+++ b/libcxx/utils/google-benchmark/src/benchmark_register.h
@@ -0,0 +1,33 @@
+#ifndef BENCHMARK_REGISTER_H
+#define BENCHMARK_REGISTER_H
+
+#include <vector>
+
+#include "check.h"
+
+template <typename T>
+void AddRange(std::vector<T>* dst, T lo, T hi, int mult) {
+ CHECK_GE(lo, 0);
+ CHECK_GE(hi, lo);
+ CHECK_GE(mult, 2);
+
+ // Add "lo"
+ dst->push_back(lo);
+
+ static const T kmax = std::numeric_limits<T>::max();
+
+ // Now space out the benchmarks in multiples of "mult"
+ for (T i = 1; i < kmax / mult; i *= mult) {
+ if (i >= hi) break;
+ if (i > lo) {
+ dst->push_back(i);
+ }
+ }
+
+ // Add "hi" (if different from "lo")
+ if (hi != lo) {
+ dst->push_back(hi);
+ }
+}
+
+#endif // BENCHMARK_REGISTER_H
diff --git a/libcxx/utils/google-benchmark/src/check.h b/libcxx/utils/google-benchmark/src/check.h
index 73bead2fb55..f5f8253f804 100644
--- a/libcxx/utils/google-benchmark/src/check.h
+++ b/libcxx/utils/google-benchmark/src/check.h
@@ -1,9 +1,9 @@
#ifndef CHECK_H_
#define CHECK_H_
+#include <cmath>
#include <cstdlib>
#include <ostream>
-#include <cmath>
#include "internal_macros.h"
#include "log.h"
@@ -62,6 +62,8 @@ class CheckHandler {
#define CHECK(b) ::benchmark::internal::GetNullLogInstance()
#endif
+// clang-format off
+// preserve whitespacing between operators for alignment
#define CHECK_EQ(a, b) CHECK((a) == (b))
#define CHECK_NE(a, b) CHECK((a) != (b))
#define CHECK_GE(a, b) CHECK((a) >= (b))
@@ -75,5 +77,6 @@ class CheckHandler {
#define CHECK_FLOAT_LE(a, b, eps) CHECK((b) - (a) > -(eps))
#define CHECK_FLOAT_GT(a, b, eps) CHECK((a) - (b) > (eps))
#define CHECK_FLOAT_LT(a, b, eps) CHECK((b) - (a) > (eps))
+//clang-format on
#endif // CHECK_H_
diff --git a/libcxx/utils/google-benchmark/src/commandlineflags.cc b/libcxx/utils/google-benchmark/src/commandlineflags.cc
index 2fc92517a32..734e88bbec6 100644
--- a/libcxx/utils/google-benchmark/src/commandlineflags.cc
+++ b/libcxx/utils/google-benchmark/src/commandlineflags.cc
@@ -45,7 +45,7 @@ bool ParseInt32(const std::string& src_text, const char* str, int32_t* value) {
// LONG_MAX or LONG_MIN when the input overflows.)
result != long_value
// The parsed value overflows as an Int32.
- ) {
+ ) {
std::cerr << src_text << " is expected to be a 32-bit integer, "
<< "but actually has value \"" << str << "\", "
<< "which overflows.\n";
diff --git a/libcxx/utils/google-benchmark/src/complexity.cc b/libcxx/utils/google-benchmark/src/complexity.cc
index 88832698ef6..aafd538df21 100644
--- a/libcxx/utils/google-benchmark/src/complexity.cc
+++ b/libcxx/utils/google-benchmark/src/complexity.cc
@@ -26,20 +26,23 @@ namespace benchmark {
// Internal function to calculate the different scalability forms
BigOFunc* FittingCurve(BigO complexity) {
+ static const double kLog2E = 1.44269504088896340736;
switch (complexity) {
case oN:
- return [](int n) -> double { return n; };
+ return [](int64_t n) -> double { return static_cast<double>(n); };
case oNSquared:
- return [](int n) -> double { return std::pow(n, 2); };
+ return [](int64_t n) -> double { return std::pow(n, 2); };
case oNCubed:
- return [](int n) -> double { return std::pow(n, 3); };
+ return [](int64_t n) -> double { return std::pow(n, 3); };
case oLogN:
- return [](int n) { return log2(n); };
+ /* Note: can't use log2 because Android's GNU STL lacks it */
+ return [](int64_t n) { return kLog2E * log(static_cast<double>(n)); };
case oNLogN:
- return [](int n) { return n * log2(n); };
+ /* Note: can't use log2 because Android's GNU STL lacks it */
+ return [](int64_t n) { return kLog2E * n * log(static_cast<double>(n)); };
case o1:
default:
- return [](int) { return 1.0; };
+ return [](int64_t) { return 1.0; };
}
}
@@ -65,15 +68,15 @@ std::string GetBigOString(BigO complexity) {
// Find the coefficient for the high-order term in the running time, by
// minimizing the sum of squares of relative error, for the fitting curve
-// given by the lambda expresion.
+// given by the lambda expression.
// - n : Vector containing the size of the benchmark tests.
// - time : Vector containing the times for the benchmark tests.
-// - fitting_curve : lambda expresion (e.g. [](int n) {return n; };).
+// - fitting_curve : lambda expression (e.g. [](int64_t n) {return n; };).
// For a deeper explanation on the algorithm logic, look the README file at
// http://github.com/ismaelJimenez/Minimal-Cpp-Least-Squared-Fit
-LeastSq MinimalLeastSq(const std::vector<int>& n,
+LeastSq MinimalLeastSq(const std::vector<int64_t>& n,
const std::vector<double>& time,
BigOFunc* fitting_curve) {
double sigma_gn = 0.0;
@@ -117,7 +120,7 @@ LeastSq MinimalLeastSq(const std::vector<int>& n,
// - complexity : If different than oAuto, the fitting curve will stick to
// this one. If it is oAuto, it will be calculated the best
// fitting curve.
-LeastSq MinimalLeastSq(const std::vector<int>& n,
+LeastSq MinimalLeastSq(const std::vector<int64_t>& n,
const std::vector<double>& time, const BigO complexity) {
CHECK_EQ(n.size(), time.size());
CHECK_GE(n.size(), 2); // Do not compute fitting curve is less than two
@@ -157,7 +160,7 @@ std::vector<BenchmarkReporter::Run> ComputeBigO(
if (reports.size() < 2) return results;
// Accumulators.
- std::vector<int> n;
+ std::vector<int64_t> n;
std::vector<double> real_time;
std::vector<double> cpu_time;
diff --git a/libcxx/utils/google-benchmark/src/counter.cc b/libcxx/utils/google-benchmark/src/counter.cc
index ed1aa044ee7..cb604e060b6 100644
--- a/libcxx/utils/google-benchmark/src/counter.cc
+++ b/libcxx/utils/google-benchmark/src/counter.cc
@@ -17,7 +17,8 @@
namespace benchmark {
namespace internal {
-double Finish(Counter const& c, double cpu_time, double num_threads) {
+double Finish(Counter const& c, int64_t iterations, double cpu_time,
+ double num_threads) {
double v = c.value;
if (c.flags & Counter::kIsRate) {
v /= cpu_time;
@@ -25,25 +26,31 @@ double Finish(Counter const& c, double cpu_time, double num_threads) {
if (c.flags & Counter::kAvgThreads) {
v /= num_threads;
}
+ if (c.flags & Counter::kIsIterationInvariant) {
+ v *= iterations;
+ }
+ if (c.flags & Counter::kAvgIterations) {
+ v /= iterations;
+ }
return v;
}
-void Finish(UserCounters *l, double cpu_time, double num_threads) {
- for (auto &c : *l) {
- c.second.value = Finish(c.second, cpu_time, num_threads);
+void Finish(UserCounters* l, int64_t iterations, double cpu_time, double num_threads) {
+ for (auto& c : *l) {
+ c.second.value = Finish(c.second, iterations, cpu_time, num_threads);
}
}
-void Increment(UserCounters *l, UserCounters const& r) {
+void Increment(UserCounters* l, UserCounters const& r) {
// add counters present in both or just in *l
- for (auto &c : *l) {
+ for (auto& c : *l) {
auto it = r.find(c.first);
if (it != r.end()) {
c.second.value = c.second + it->second;
}
}
// add counters present in r, but not in *l
- for (auto const &tc : r) {
+ for (auto const& tc : r) {
auto it = l->find(tc.first);
if (it == l->end()) {
(*l)[tc.first] = tc.second;
@@ -64,5 +71,5 @@ bool SameNames(UserCounters const& l, UserCounters const& r) {
return true;
}
-} // end namespace internal
-} // end namespace benchmark
+} // end namespace internal
+} // end namespace benchmark
diff --git a/libcxx/utils/google-benchmark/src/counter.h b/libcxx/utils/google-benchmark/src/counter.h
index dd6865a31d7..d884e50aa12 100644
--- a/libcxx/utils/google-benchmark/src/counter.h
+++ b/libcxx/utils/google-benchmark/src/counter.h
@@ -18,9 +18,9 @@ namespace benchmark {
// these counter-related functions are hidden to reduce API surface.
namespace internal {
-void Finish(UserCounters *l, double time, double num_threads);
-void Increment(UserCounters *l, UserCounters const& r);
+void Finish(UserCounters* l, int64_t iterations, double time, double num_threads);
+void Increment(UserCounters* l, UserCounters const& r);
bool SameNames(UserCounters const& l, UserCounters const& r);
-} // end namespace internal
+} // end namespace internal
-} //end namespace benchmark
+} // end namespace benchmark
diff --git a/libcxx/utils/google-benchmark/src/csv_reporter.cc b/libcxx/utils/google-benchmark/src/csv_reporter.cc
index 35510645b08..4a641909d80 100644
--- a/libcxx/utils/google-benchmark/src/csv_reporter.cc
+++ b/libcxx/utils/google-benchmark/src/csv_reporter.cc
@@ -22,9 +22,9 @@
#include <tuple>
#include <vector>
+#include "check.h"
#include "string_util.h"
#include "timers.h"
-#include "check.h"
// File format reference: http://edoceo.com/utilitas/csv-file-format.
@@ -42,7 +42,7 @@ bool CSVReporter::ReportContext(const Context& context) {
return true;
}
-void CSVReporter::ReportRuns(const std::vector<Run> & reports) {
+void CSVReporter::ReportRuns(const std::vector<Run>& reports) {
std::ostream& Out = GetOutputStream();
if (!printed_header_) {
@@ -58,7 +58,8 @@ void CSVReporter::ReportRuns(const std::vector<Run> & reports) {
Out << *B++;
if (B != elements.end()) Out << ",";
}
- for (auto B = user_counter_names_.begin(); B != user_counter_names_.end();) {
+ for (auto B = user_counter_names_.begin();
+ B != user_counter_names_.end();) {
Out << ",\"" << *B++ << "\"";
}
Out << "\n";
@@ -69,9 +70,9 @@ void CSVReporter::ReportRuns(const std::vector<Run> & reports) {
for (const auto& run : reports) {
for (const auto& cnt : run.counters) {
CHECK(user_counter_names_.find(cnt.first) != user_counter_names_.end())
- << "All counters must be present in each run. "
- << "Counter named \"" << cnt.first
- << "\" was not in a run after being added to the header";
+ << "All counters must be present in each run. "
+ << "Counter named \"" << cnt.first
+ << "\" was not in a run after being added to the header";
}
}
}
@@ -80,10 +81,9 @@ void CSVReporter::ReportRuns(const std::vector<Run> & reports) {
for (const auto& run : reports) {
PrintRunData(run);
}
-
}
-void CSVReporter::PrintRunData(const Run & run) {
+void CSVReporter::PrintRunData(const Run& run) {
std::ostream& Out = GetOutputStream();
// Field with embedded double-quote characters must be doubled and the field
@@ -135,9 +135,9 @@ void CSVReporter::PrintRunData(const Run & run) {
Out << ",,"; // for error_occurred and error_message
// Print user counters
- for (const auto &ucn : user_counter_names_) {
+ for (const auto& ucn : user_counter_names_) {
auto it = run.counters.find(ucn);
- if(it == run.counters.end()) {
+ if (it == run.counters.end()) {
Out << ",";
} else {
Out << "," << it->second;
diff --git a/libcxx/utils/google-benchmark/src/cycleclock.h b/libcxx/utils/google-benchmark/src/cycleclock.h
index 4251fe4c32a..00d57641676 100644
--- a/libcxx/utils/google-benchmark/src/cycleclock.h
+++ b/libcxx/utils/google-benchmark/src/cycleclock.h
@@ -121,7 +121,7 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() {
// because is provides nanosecond resolution (which is noticable at
// least for PNaCl modules running on x86 Mac & Linux).
// Initialize to always return 0 if clock_gettime fails.
- struct timespec ts = { 0, 0 };
+ struct timespec ts = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &ts);
return static_cast<int64_t>(ts.tv_sec) * 1000000000 + ts.tv_nsec;
#elif defined(__aarch64__)
@@ -159,6 +159,11 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() {
struct timeval tv;
gettimeofday(&tv, nullptr);
return static_cast<int64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
+#elif defined(__s390__) // Covers both s390 and s390x.
+ // Return the CPU clock.
+ uint64_t tsc;
+ asm("stck %0" : "=Q"(tsc) : : "cc");
+ return tsc;
#else
// The soft failover to a generic implementation is automatic only for ARM.
// For other platforms the developer is expected to make an attempt to create
diff --git a/libcxx/utils/google-benchmark/src/internal_macros.h b/libcxx/utils/google-benchmark/src/internal_macros.h
index c34f5716e61..b7e9203ff60 100644
--- a/libcxx/utils/google-benchmark/src/internal_macros.h
+++ b/libcxx/utils/google-benchmark/src/internal_macros.h
@@ -3,6 +3,11 @@
#include "benchmark/benchmark.h"
+/* Needed to detect STL */
+#include <cstdlib>
+
+// clang-format off
+
#ifndef __has_feature
#define __has_feature(x) 0
#endif
@@ -39,6 +44,7 @@
#elif defined(_WIN32)
#define BENCHMARK_OS_WINDOWS 1
#elif defined(__APPLE__)
+ #define BENCHMARK_OS_APPLE 1
#include "TargetConditionals.h"
#if defined(TARGET_OS_MAC)
#define BENCHMARK_OS_MACOSX 1
@@ -50,14 +56,24 @@
#define BENCHMARK_OS_FREEBSD 1
#elif defined(__NetBSD__)
#define BENCHMARK_OS_NETBSD 1
+#elif defined(__OpenBSD__)
+ #define BENCHMARK_OS_OPENBSD 1
#elif defined(__linux__)
#define BENCHMARK_OS_LINUX 1
#elif defined(__native_client__)
#define BENCHMARK_OS_NACL 1
-#elif defined(EMSCRIPTEN)
+#elif defined(__EMSCRIPTEN__)
#define BENCHMARK_OS_EMSCRIPTEN 1
#elif defined(__rtems__)
#define BENCHMARK_OS_RTEMS 1
+#elif defined(__Fuchsia__)
+#define BENCHMARK_OS_FUCHSIA 1
+#elif defined (__SVR4) && defined (__sun)
+#define BENCHMARK_OS_SOLARIS 1
+#endif
+
+#if defined(__ANDROID__) && defined(__GLIBCXX__)
+#define BENCHMARK_STL_ANDROID_GNUSTL 1
#endif
#if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \
@@ -79,4 +95,6 @@
#define BENCHMARK_UNREACHABLE() ((void)0)
#endif
+// clang-format on
+
#endif // BENCHMARK_INTERNAL_MACROS_H_
diff --git a/libcxx/utils/google-benchmark/src/json_reporter.cc b/libcxx/utils/google-benchmark/src/json_reporter.cc
index b5ae302ad48..611605af6b5 100644
--- a/libcxx/utils/google-benchmark/src/json_reporter.cc
+++ b/libcxx/utils/google-benchmark/src/json_reporter.cc
@@ -17,12 +17,12 @@
#include <algorithm>
#include <cstdint>
+#include <iomanip> // for setprecision
#include <iostream>
+#include <limits>
#include <string>
#include <tuple>
#include <vector>
-#include <iomanip> // for setprecision
-#include <limits>
#include "string_util.h"
#include "timers.h"
@@ -32,15 +32,15 @@ namespace benchmark {
namespace {
std::string FormatKV(std::string const& key, std::string const& value) {
- return StringPrintF("\"%s\": \"%s\"", key.c_str(), value.c_str());
+ return StrFormat("\"%s\": \"%s\"", key.c_str(), value.c_str());
}
std::string FormatKV(std::string const& key, const char* value) {
- return StringPrintF("\"%s\": \"%s\"", key.c_str(), value);
+ return StrFormat("\"%s\": \"%s\"", key.c_str(), value);
}
std::string FormatKV(std::string const& key, bool value) {
- return StringPrintF("\"%s\": %s", key.c_str(), value ? "true" : "false");
+ return StrFormat("\"%s\": %s", key.c_str(), value ? "true" : "false");
}
std::string FormatKV(std::string const& key, int64_t value) {
@@ -53,7 +53,7 @@ std::string FormatKV(std::string const& key, double value) {
std::stringstream ss;
ss << '"' << key << "\": ";
- const auto max_digits10 = std::numeric_limits<decltype (value)>::max_digits10;
+ const auto max_digits10 = std::numeric_limits<decltype(value)>::max_digits10;
const auto max_fractional_digits10 = max_digits10 - 1;
ss << std::scientific << std::setprecision(max_fractional_digits10) << value;
@@ -77,6 +77,10 @@ bool JSONReporter::ReportContext(const Context& context) {
std::string walltime_value = LocalDateTimeString();
out << indent << FormatKV("date", walltime_value) << ",\n";
+ if (Context::executable_name) {
+ out << indent << FormatKV("executable", Context::executable_name) << ",\n";
+ }
+
CPUInfo const& info = context.cpu_info;
out << indent << FormatKV("num_cpus", static_cast<int64_t>(info.num_cpus))
<< ",\n";
@@ -157,40 +161,30 @@ void JSONReporter::PrintRunData(Run const& run) {
}
if (!run.report_big_o && !run.report_rms) {
out << indent << FormatKV("iterations", run.iterations) << ",\n";
- out << indent
- << FormatKV("real_time", run.GetAdjustedRealTime())
- << ",\n";
- out << indent
- << FormatKV("cpu_time", run.GetAdjustedCPUTime());
+ out << indent << FormatKV("real_time", run.GetAdjustedRealTime()) << ",\n";
+ out << indent << FormatKV("cpu_time", run.GetAdjustedCPUTime());
out << ",\n"
<< indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
} else if (run.report_big_o) {
- out << indent
- << FormatKV("cpu_coefficient", run.GetAdjustedCPUTime())
+ out << indent << FormatKV("cpu_coefficient", run.GetAdjustedCPUTime())
<< ",\n";
- out << indent
- << FormatKV("real_coefficient", run.GetAdjustedRealTime())
+ out << indent << FormatKV("real_coefficient", run.GetAdjustedRealTime())
<< ",\n";
out << indent << FormatKV("big_o", GetBigOString(run.complexity)) << ",\n";
out << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
} else if (run.report_rms) {
- out << indent
- << FormatKV("rms", run.GetAdjustedCPUTime());
+ out << indent << FormatKV("rms", run.GetAdjustedCPUTime());
}
if (run.bytes_per_second > 0.0) {
out << ",\n"
- << indent
- << FormatKV("bytes_per_second", run.bytes_per_second);
+ << indent << FormatKV("bytes_per_second", run.bytes_per_second);
}
if (run.items_per_second > 0.0) {
out << ",\n"
- << indent
- << FormatKV("items_per_second", run.items_per_second);
+ << indent << FormatKV("items_per_second", run.items_per_second);
}
- for(auto &c : run.counters) {
- out << ",\n"
- << indent
- << FormatKV(c.first, c.second);
+ for (auto& c : run.counters) {
+ out << ",\n" << indent << FormatKV(c.first, c.second);
}
if (!run.report_label.empty()) {
out << ",\n" << indent << FormatKV("label", run.report_label);
@@ -198,4 +192,4 @@ void JSONReporter::PrintRunData(Run const& run) {
out << '\n';
}
-} // end namespace benchmark
+} // end namespace benchmark
diff --git a/libcxx/utils/google-benchmark/src/log.h b/libcxx/utils/google-benchmark/src/log.h
index d06e1031db1..47d0c35c018 100644
--- a/libcxx/utils/google-benchmark/src/log.h
+++ b/libcxx/utils/google-benchmark/src/log.h
@@ -66,8 +66,9 @@ inline LogType& GetLogInstanceForLevel(int level) {
} // end namespace internal
} // end namespace benchmark
+// clang-format off
#define VLOG(x) \
(::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \
" ")
-
+// clang-format on
#endif
diff --git a/libcxx/utils/google-benchmark/src/re.h b/libcxx/utils/google-benchmark/src/re.h
index 01e9736505e..fbe25037b46 100644
--- a/libcxx/utils/google-benchmark/src/re.h
+++ b/libcxx/utils/google-benchmark/src/re.h
@@ -17,22 +17,39 @@
#include "internal_macros.h"
+// clang-format off
+
+#if !defined(HAVE_STD_REGEX) && \
+ !defined(HAVE_GNU_POSIX_REGEX) && \
+ !defined(HAVE_POSIX_REGEX)
+ // No explicit regex selection; detect based on builtin hints.
+ #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE)
+ #define HAVE_POSIX_REGEX 1
+ #elif __cplusplus >= 199711L
+ #define HAVE_STD_REGEX 1
+ #endif
+#endif
+
// Prefer C regex libraries when compiling w/o exceptions so that we can
// correctly report errors.
-#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && defined(HAVE_STD_REGEX) && \
+#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \
+ defined(BENCHMARK_HAVE_STD_REGEX) && \
(defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX))
-#undef HAVE_STD_REGEX
+ #undef HAVE_STD_REGEX
#endif
#if defined(HAVE_STD_REGEX)
-#include <regex>
+ #include <regex>
#elif defined(HAVE_GNU_POSIX_REGEX)
-#include <gnuregex.h>
+ #include <gnuregex.h>
#elif defined(HAVE_POSIX_REGEX)
-#include <regex.h>
+ #include <regex.h>
#else
#error No regular expression backend was found!
#endif
+
+// clang-format on
+
#include <string>
#include "check.h"
@@ -72,20 +89,21 @@ class Regex {
inline bool Regex::Init(const std::string& spec, std::string* error) {
#ifdef BENCHMARK_HAS_NO_EXCEPTIONS
- ((void)error); // suppress unused warning
+ ((void)error); // suppress unused warning
#else
try {
#endif
- re_ = std::regex(spec, std::regex_constants::extended);
- init_ = true;
+ re_ = std::regex(spec, std::regex_constants::extended);
+ init_ = true;
#ifndef BENCHMARK_HAS_NO_EXCEPTIONS
- } catch (const std::regex_error& e) {
- if (error) {
- *error = e.what();
- }
+}
+catch (const std::regex_error& e) {
+ if (error) {
+ *error = e.what();
}
+}
#endif
- return init_;
+return init_;
}
inline Regex::~Regex() {}
diff --git a/libcxx/utils/google-benchmark/src/reporter.cc b/libcxx/utils/google-benchmark/src/reporter.cc
index 5d2fa05a2b2..541661a25f0 100644
--- a/libcxx/utils/google-benchmark/src/reporter.cc
+++ b/libcxx/utils/google-benchmark/src/reporter.cc
@@ -37,6 +37,9 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out,
Out << LocalDateTimeString() << "\n";
+ if (context.executable_name)
+ Out << "Running " << context.executable_name << "\n";
+
const CPUInfo &info = context.cpu_info;
Out << "Run on (" << info.num_cpus << " X "
<< (info.cycles_per_second / 1000000.0) << " MHz CPU "
@@ -64,6 +67,9 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out,
#endif
}
+// No initializer because it's already initialized to NULL.
+const char *BenchmarkReporter::Context::executable_name;
+
BenchmarkReporter::Context::Context() : cpu_info(CPUInfo::Get()) {}
double BenchmarkReporter::Run::GetAdjustedRealTime() const {
diff --git a/libcxx/utils/google-benchmark/src/statistics.cc b/libcxx/utils/google-benchmark/src/statistics.cc
index 5932ad43860..612dda2d1a7 100644
--- a/libcxx/utils/google-benchmark/src/statistics.cc
+++ b/libcxx/utils/google-benchmark/src/statistics.cc
@@ -17,9 +17,9 @@
#include <algorithm>
#include <cmath>
+#include <numeric>
#include <string>
#include <vector>
-#include <numeric>
#include "check.h"
#include "statistics.h"
@@ -30,22 +30,25 @@ auto StatisticsSum = [](const std::vector<double>& v) {
};
double StatisticsMean(const std::vector<double>& v) {
- if (v.size() == 0) return 0.0;
+ if (v.empty()) return 0.0;
return StatisticsSum(v) * (1.0 / v.size());
}
double StatisticsMedian(const std::vector<double>& v) {
if (v.size() < 3) return StatisticsMean(v);
- std::vector<double> partial;
- // we need roundDown(count/2)+1 slots
- partial.resize(1 + (v.size() / 2));
- std::partial_sort_copy(v.begin(), v.end(), partial.begin(), partial.end());
- // did we have odd number of samples?
- // if yes, then the last element of partially-sorted vector is the median
- // it no, then the average of the last two elements is the median
- if(v.size() % 2 == 1)
- return partial.back();
- return (partial[partial.size() - 2] + partial[partial.size() - 1]) / 2.0;
+ std::vector<double> copy(v);
+
+ auto center = copy.begin() + v.size() / 2;
+ std::nth_element(copy.begin(), center, copy.end());
+
+ // did we have an odd number of samples?
+ // if yes, then center is the median
+ // it no, then we are looking for the average between center and the value
+ // before
+ if (v.size() % 2 == 1) return *center;
+ auto center2 = copy.begin() + v.size() / 2 - 1;
+ std::nth_element(copy.begin(), center2, copy.end());
+ return (*center + *center2) / 2.0;
}
// Return the sum of the squares of this sample set
@@ -62,11 +65,10 @@ auto Sqrt = [](const double dat) {
double StatisticsStdDev(const std::vector<double>& v) {
const auto mean = StatisticsMean(v);
- if (v.size() == 0) return mean;
+ if (v.empty()) return mean;
// Sample standard deviation is undefined for n = 1
- if (v.size() == 1)
- return 0.0;
+ if (v.size() == 1) return 0.0;
const double avg_squares = SumSquares(v) * (1.0 / v.size());
return Sqrt(v.size() / (v.size() - 1.0) * (avg_squares - Sqr(mean)));
@@ -105,11 +107,11 @@ std::vector<BenchmarkReporter::Run> ComputeStats(
Counter c;
std::vector<double> s;
};
- std::map< std::string, CounterStat > counter_stats;
- for(Run const& r : reports) {
- for(auto const& cnt : r.counters) {
+ std::map<std::string, CounterStat> counter_stats;
+ for (Run const& r : reports) {
+ for (auto const& cnt : r.counters) {
auto it = counter_stats.find(cnt.first);
- if(it == counter_stats.end()) {
+ if (it == counter_stats.end()) {
counter_stats.insert({cnt.first, {cnt.second, std::vector<double>{}}});
it = counter_stats.find(cnt.first);
it->second.s.reserve(reports.size());
@@ -129,7 +131,7 @@ std::vector<BenchmarkReporter::Run> ComputeStats(
items_per_second_stat.emplace_back(run.items_per_second);
bytes_per_second_stat.emplace_back(run.bytes_per_second);
// user counters
- for(auto const& cnt : run.counters) {
+ for (auto const& cnt : run.counters) {
auto it = counter_stats.find(cnt.first);
CHECK_NE(it, counter_stats.end());
it->second.s.emplace_back(cnt.second);
@@ -145,7 +147,7 @@ std::vector<BenchmarkReporter::Run> ComputeStats(
}
}
- for(const auto& Stat : *reports[0].statistics) {
+ for (const auto& Stat : *reports[0].statistics) {
// Get the data from the accumulator to BenchmarkReporter::Run's.
Run data;
data.benchmark_name = reports[0].benchmark_name + "_" + Stat.name_;
@@ -160,7 +162,7 @@ std::vector<BenchmarkReporter::Run> ComputeStats(
data.time_unit = reports[0].time_unit;
// user counters
- for(auto const& kv : counter_stats) {
+ for (auto const& kv : counter_stats) {
const auto uc_stat = Stat.compute_(kv.second.s);
auto c = Counter(uc_stat, counter_stats[kv.first].c.flags);
data.counters[kv.first] = c;
diff --git a/libcxx/utils/google-benchmark/src/string_util.cc b/libcxx/utils/google-benchmark/src/string_util.cc
index 29edb2a4683..05ac5b4ea36 100644
--- a/libcxx/utils/google-benchmark/src/string_util.cc
+++ b/libcxx/utils/google-benchmark/src/string_util.cc
@@ -122,7 +122,7 @@ std::string HumanReadableNumber(double n, double one_k) {
return ToBinaryStringFullySpecified(n, 1.1, 1, one_k);
}
-std::string StringPrintFImp(const char* msg, va_list args) {
+std::string StrFormatImp(const char* msg, va_list args) {
// we might need a second shot at this, so pre-emptivly make a copy
va_list args_cp;
va_copy(args_cp, args);
@@ -152,10 +152,10 @@ std::string StringPrintFImp(const char* msg, va_list args) {
return std::string(buff_ptr.get());
}
-std::string StringPrintF(const char* format, ...) {
+std::string StrFormat(const char* format, ...) {
va_list args;
va_start(args, format);
- std::string tmp = StringPrintFImp(format, args);
+ std::string tmp = StrFormatImp(format, args);
va_end(args);
return tmp;
}
@@ -169,4 +169,93 @@ void ReplaceAll(std::string* str, const std::string& from,
}
}
+#ifdef BENCHMARK_STL_ANDROID_GNUSTL
+/*
+ * GNU STL in Android NDK lacks support for some C++11 functions, including
+ * stoul, stoi, stod. We reimplement them here using C functions strtoul,
+ * strtol, strtod. Note that reimplemented functions are in benchmark::
+ * namespace, not std:: namespace.
+ */
+unsigned long stoul(const std::string& str, size_t* pos, int base) {
+ /* Record previous errno */
+ const int oldErrno = errno;
+ errno = 0;
+
+ const char* strStart = str.c_str();
+ char* strEnd = const_cast<char*>(strStart);
+ const unsigned long result = strtoul(strStart, &strEnd, base);
+
+ const int strtoulErrno = errno;
+ /* Restore previous errno */
+ errno = oldErrno;
+
+ /* Check for errors and return */
+ if (strtoulErrno == ERANGE) {
+ throw std::out_of_range(
+ "stoul failed: " + str + " is outside of range of unsigned long");
+ } else if (strEnd == strStart || strtoulErrno != 0) {
+ throw std::invalid_argument(
+ "stoul failed: " + str + " is not an integer");
+ }
+ if (pos != nullptr) {
+ *pos = static_cast<size_t>(strEnd - strStart);
+ }
+ return result;
+}
+
+int stoi(const std::string& str, size_t* pos, int base) {
+ /* Record previous errno */
+ const int oldErrno = errno;
+ errno = 0;
+
+ const char* strStart = str.c_str();
+ char* strEnd = const_cast<char*>(strStart);
+ const long result = strtol(strStart, &strEnd, base);
+
+ const int strtolErrno = errno;
+ /* Restore previous errno */
+ errno = oldErrno;
+
+ /* Check for errors and return */
+ if (strtolErrno == ERANGE || long(int(result)) != result) {
+ throw std::out_of_range(
+ "stoul failed: " + str + " is outside of range of int");
+ } else if (strEnd == strStart || strtolErrno != 0) {
+ throw std::invalid_argument(
+ "stoul failed: " + str + " is not an integer");
+ }
+ if (pos != nullptr) {
+ *pos = static_cast<size_t>(strEnd - strStart);
+ }
+ return int(result);
+}
+
+double stod(const std::string& str, size_t* pos) {
+ /* Record previous errno */
+ const int oldErrno = errno;
+ errno = 0;
+
+ const char* strStart = str.c_str();
+ char* strEnd = const_cast<char*>(strStart);
+ const double result = strtod(strStart, &strEnd);
+
+ /* Restore previous errno */
+ const int strtodErrno = errno;
+ errno = oldErrno;
+
+ /* Check for errors and return */
+ if (strtodErrno == ERANGE) {
+ throw std::out_of_range(
+ "stoul failed: " + str + " is outside of range of int");
+ } else if (strEnd == strStart || strtodErrno != 0) {
+ throw std::invalid_argument(
+ "stoul failed: " + str + " is not an integer");
+ }
+ if (pos != nullptr) {
+ *pos = static_cast<size_t>(strEnd - strStart);
+ }
+ return result;
+}
+#endif
+
} // end namespace benchmark
diff --git a/libcxx/utils/google-benchmark/src/string_util.h b/libcxx/utils/google-benchmark/src/string_util.h
index c3d53bfd334..4a5501273cf 100644
--- a/libcxx/utils/google-benchmark/src/string_util.h
+++ b/libcxx/utils/google-benchmark/src/string_util.h
@@ -12,29 +12,45 @@ void AppendHumanReadable(int n, std::string* str);
std::string HumanReadableNumber(double n, double one_k = 1024.0);
-std::string StringPrintF(const char* format, ...);
+std::string StrFormat(const char* format, ...);
-inline std::ostream& StringCatImp(std::ostream& out) BENCHMARK_NOEXCEPT {
+inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT {
return out;
}
template <class First, class... Rest>
-inline std::ostream& StringCatImp(std::ostream& out, First&& f,
- Rest&&... rest) {
+inline std::ostream& StrCatImp(std::ostream& out, First&& f, Rest&&... rest) {
out << std::forward<First>(f);
- return StringCatImp(out, std::forward<Rest>(rest)...);
+ return StrCatImp(out, std::forward<Rest>(rest)...);
}
template <class... Args>
inline std::string StrCat(Args&&... args) {
std::ostringstream ss;
- StringCatImp(ss, std::forward<Args>(args)...);
+ StrCatImp(ss, std::forward<Args>(args)...);
return ss.str();
}
void ReplaceAll(std::string* str, const std::string& from,
const std::string& to);
+#ifdef BENCHMARK_STL_ANDROID_GNUSTL
+/*
+ * GNU STL in Android NDK lacks support for some C++11 functions, including
+ * stoul, stoi, stod. We reimplement them here using C functions strtoul,
+ * strtol, strtod. Note that reimplemented functions are in benchmark::
+ * namespace, not std:: namespace.
+ */
+unsigned long stoul(const std::string& str, size_t* pos = nullptr,
+ int base = 10);
+int stoi(const std::string& str, size_t* pos = nullptr, int base = 10);
+double stod(const std::string& str, size_t* pos = nullptr);
+#else
+using std::stoul;
+using std::stoi;
+using std::stod;
+#endif
+
} // end namespace benchmark
#endif // BENCHMARK_STRING_UTIL_H_
diff --git a/libcxx/utils/google-benchmark/src/sysinfo.cc b/libcxx/utils/google-benchmark/src/sysinfo.cc
index 2520ad5aeda..73064b97ba2 100644
--- a/libcxx/utils/google-benchmark/src/sysinfo.cc
+++ b/libcxx/utils/google-benchmark/src/sysinfo.cc
@@ -16,20 +16,26 @@
#ifdef BENCHMARK_OS_WINDOWS
#include <Shlwapi.h>
+#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
#include <VersionHelpers.h>
#include <Windows.h>
#else
#include <fcntl.h>
+#ifndef BENCHMARK_OS_FUCHSIA
#include <sys/resource.h>
+#endif
#include <sys/time.h>
#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
#include <unistd.h>
#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX || \
- defined BENCHMARK_OS_NETBSD
+ defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD
#define BENCHMARK_HAS_SYSCTL
#include <sys/sysctl.h>
#endif
#endif
+#if defined(BENCHMARK_OS_SOLARIS)
+#include <kstat.h>
+#endif
#include <algorithm>
#include <array>
@@ -130,6 +136,26 @@ struct ValueUnion {
};
ValueUnion GetSysctlImp(std::string const& Name) {
+#if defined BENCHMARK_OS_OPENBSD
+ int mib[2];
+
+ mib[0] = CTL_HW;
+ if ((Name == "hw.ncpu") || (Name == "hw.cpuspeed")){
+ ValueUnion buff(sizeof(int));
+
+ if (Name == "hw.ncpu") {
+ mib[1] = HW_NCPU;
+ } else {
+ mib[1] = HW_CPUSPEED;
+ }
+
+ if (sysctl(mib, 2, buff.data(), &buff.Size, nullptr, 0) == -1) {
+ return ValueUnion();
+ }
+ return buff;
+ }
+ return ValueUnion();
+#else
size_t CurBuffSize = 0;
if (sysctlbyname(Name.c_str(), nullptr, &CurBuffSize, nullptr, 0) == -1)
return ValueUnion();
@@ -138,6 +164,7 @@ ValueUnion GetSysctlImp(std::string const& Name) {
if (sysctlbyname(Name.c_str(), buff.data(), &buff.Size, nullptr, 0) == 0)
return buff;
return ValueUnion();
+#endif
}
BENCHMARK_MAYBE_UNUSED
@@ -198,7 +225,7 @@ int CountSetBitsInCPUMap(std::string Val) {
auto CountBits = [](std::string Part) {
using CPUMask = std::bitset<sizeof(std::uintptr_t) * CHAR_BIT>;
Part = "0x" + Part;
- CPUMask Mask(std::stoul(Part, nullptr, 16));
+ CPUMask Mask(benchmark::stoul(Part, nullptr, 16));
return static_cast<int>(Mask.count());
};
size_t Pos;
@@ -303,7 +330,7 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizesWindows() {
if (!B.test(0)) continue;
CInfo* Cache = &it->Cache;
CPUInfo::CacheInfo C;
- C.num_sharing = B.count();
+ C.num_sharing = static_cast<int>(B.count());
C.level = Cache->Level;
C.size = Cache->Size;
switch (Cache->Type) {
@@ -354,6 +381,15 @@ int GetNumCPUs() {
return sysinfo.dwNumberOfProcessors; // number of logical
// processors in the current
// group
+#elif defined(BENCHMARK_OS_SOLARIS)
+ // Returns -1 in case of a failure.
+ int NumCPU = sysconf(_SC_NPROCESSORS_ONLN);
+ if (NumCPU < 0) {
+ fprintf(stderr,
+ "sysconf(_SC_NPROCESSORS_ONLN) failed with error: %s\n",
+ strerror(errno));
+ }
+ return NumCPU;
#else
int NumCPUs = 0;
int MaxID = -1;
@@ -372,7 +408,7 @@ int GetNumCPUs() {
if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) {
NumCPUs++;
if (!value.empty()) {
- int CurID = std::stoi(value);
+ int CurID = benchmark::stoi(value);
MaxID = std::max(CurID, MaxID);
}
}
@@ -441,16 +477,16 @@ double GetCPUCyclesPerSecond() {
std::string value;
if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1);
// When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
- // accept postive values. Some environments (virtual machines) report zero,
+ // accept positive values. Some environments (virtual machines) report zero,
// which would cause infinite looping in WallTime_Init.
if (startsWithKey(ln, "cpu MHz")) {
if (!value.empty()) {
- double cycles_per_second = std::stod(value) * 1000000.0;
+ double cycles_per_second = benchmark::stod(value) * 1000000.0;
if (cycles_per_second > 0) return cycles_per_second;
}
} else if (startsWithKey(ln, "bogomips")) {
if (!value.empty()) {
- bogo_clock = std::stod(value) * 1000000.0;
+ bogo_clock = benchmark::stod(value) * 1000000.0;
if (bogo_clock < 0.0) bogo_clock = error_value;
}
}
@@ -473,12 +509,17 @@ double GetCPUCyclesPerSecond() {
constexpr auto* FreqStr =
#if defined(BENCHMARK_OS_FREEBSD) || defined(BENCHMARK_OS_NETBSD)
"machdep.tsc_freq";
+#elif defined BENCHMARK_OS_OPENBSD
+ "hw.cpuspeed";
#else
"hw.cpufrequency";
#endif
unsigned long long hz = 0;
+#if defined BENCHMARK_OS_OPENBSD
+ if (GetSysctl(FreqStr, &hz)) return hz * 1000000;
+#else
if (GetSysctl(FreqStr, &hz)) return hz;
-
+#endif
fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n",
FreqStr, strerror(errno));
@@ -493,6 +534,35 @@ double GetCPUCyclesPerSecond() {
"~MHz", nullptr, &data, &data_size)))
return static_cast<double>((int64_t)data *
(int64_t)(1000 * 1000)); // was mhz
+#elif defined (BENCHMARK_OS_SOLARIS)
+ kstat_ctl_t *kc = kstat_open();
+ if (!kc) {
+ std::cerr << "failed to open /dev/kstat\n";
+ return -1;
+ }
+ kstat_t *ksp = kstat_lookup(kc, (char*)"cpu_info", -1, (char*)"cpu_info0");
+ if (!ksp) {
+ std::cerr << "failed to lookup in /dev/kstat\n";
+ return -1;
+ }
+ if (kstat_read(kc, ksp, NULL) < 0) {
+ std::cerr << "failed to read from /dev/kstat\n";
+ return -1;
+ }
+ kstat_named_t *knp =
+ (kstat_named_t*)kstat_data_lookup(ksp, (char*)"current_clock_Hz");
+ if (!knp) {
+ std::cerr << "failed to lookup data in /dev/kstat\n";
+ return -1;
+ }
+ if (knp->data_type != KSTAT_DATA_UINT64) {
+ std::cerr << "current_clock_Hz is of unexpected data type: "
+ << knp->data_type << "\n";
+ return -1;
+ }
+ double clock_hz = knp->value.ui64;
+ kstat_close(kc);
+ return clock_hz;
#endif
// If we've fallen through, attempt to roughly estimate the CPU clock rate.
const int estimate_time_ms = 1000;
diff --git a/libcxx/utils/google-benchmark/src/thread_manager.h b/libcxx/utils/google-benchmark/src/thread_manager.h
new file mode 100644
index 00000000000..82b4d72b62f
--- /dev/null
+++ b/libcxx/utils/google-benchmark/src/thread_manager.h
@@ -0,0 +1,66 @@
+#ifndef BENCHMARK_THREAD_MANAGER_H
+#define BENCHMARK_THREAD_MANAGER_H
+
+#include <atomic>
+
+#include "benchmark/benchmark.h"
+#include "mutex.h"
+
+namespace benchmark {
+namespace internal {
+
+class ThreadManager {
+ public:
+ ThreadManager(int num_threads)
+ : alive_threads_(num_threads), start_stop_barrier_(num_threads) {}
+
+ Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) {
+ return benchmark_mutex_;
+ }
+
+ bool StartStopBarrier() EXCLUDES(end_cond_mutex_) {
+ return start_stop_barrier_.wait();
+ }
+
+ void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) {
+ start_stop_barrier_.removeThread();
+ if (--alive_threads_ == 0) {
+ MutexLock lock(end_cond_mutex_);
+ end_condition_.notify_all();
+ }
+ }
+
+ void WaitForAllThreads() EXCLUDES(end_cond_mutex_) {
+ MutexLock lock(end_cond_mutex_);
+ end_condition_.wait(lock.native_handle(),
+ [this]() { return alive_threads_ == 0; });
+ }
+
+ public:
+ struct Result {
+ int64_t iterations = 0;
+ double real_time_used = 0;
+ double cpu_time_used = 0;
+ double manual_time_used = 0;
+ int64_t bytes_processed = 0;
+ int64_t items_processed = 0;
+ int64_t complexity_n = 0;
+ std::string report_label_;
+ std::string error_message_;
+ bool has_error_ = false;
+ UserCounters counters;
+ };
+ GUARDED_BY(GetBenchmarkMutex()) Result results;
+
+ private:
+ mutable Mutex benchmark_mutex_;
+ std::atomic<int> alive_threads_;
+ Barrier start_stop_barrier_;
+ Mutex end_cond_mutex_;
+ Condition end_condition_;
+};
+
+} // namespace internal
+} // namespace benchmark
+
+#endif // BENCHMARK_THREAD_MANAGER_H
diff --git a/libcxx/utils/google-benchmark/src/thread_timer.h b/libcxx/utils/google-benchmark/src/thread_timer.h
new file mode 100644
index 00000000000..eaf108e017d
--- /dev/null
+++ b/libcxx/utils/google-benchmark/src/thread_timer.h
@@ -0,0 +1,69 @@
+#ifndef BENCHMARK_THREAD_TIMER_H
+#define BENCHMARK_THREAD_TIMER_H
+
+#include "check.h"
+#include "timers.h"
+
+namespace benchmark {
+namespace internal {
+
+class ThreadTimer {
+ public:
+ ThreadTimer() = default;
+
+ // Called by each thread
+ void StartTimer() {
+ running_ = true;
+ start_real_time_ = ChronoClockNow();
+ start_cpu_time_ = ThreadCPUUsage();
+ }
+
+ // Called by each thread
+ void StopTimer() {
+ CHECK(running_);
+ running_ = false;
+ real_time_used_ += ChronoClockNow() - start_real_time_;
+ // Floating point error can result in the subtraction producing a negative
+ // time. Guard against that.
+ cpu_time_used_ += std::max<double>(ThreadCPUUsage() - start_cpu_time_, 0);
+ }
+
+ // Called by each thread
+ void SetIterationTime(double seconds) { manual_time_used_ += seconds; }
+
+ bool running() const { return running_; }
+
+ // REQUIRES: timer is not running
+ double real_time_used() {
+ CHECK(!running_);
+ return real_time_used_;
+ }
+
+ // REQUIRES: timer is not running
+ double cpu_time_used() {
+ CHECK(!running_);
+ return cpu_time_used_;
+ }
+
+ // REQUIRES: timer is not running
+ double manual_time_used() {
+ CHECK(!running_);
+ return manual_time_used_;
+ }
+
+ private:
+ bool running_ = false; // Is the timer running
+ double start_real_time_ = 0; // If running_
+ double start_cpu_time_ = 0; // If running_
+
+ // Accumulated time so far (does not contain current slice if running_)
+ double real_time_used_ = 0;
+ double cpu_time_used_ = 0;
+ // Manually set iteration time. User sets this with SetIterationTime(seconds).
+ double manual_time_used_ = 0;
+};
+
+} // namespace internal
+} // namespace benchmark
+
+#endif // BENCHMARK_THREAD_TIMER_H
diff --git a/libcxx/utils/google-benchmark/src/timers.cc b/libcxx/utils/google-benchmark/src/timers.cc
index 817272d00bc..2010e2450b4 100644
--- a/libcxx/utils/google-benchmark/src/timers.cc
+++ b/libcxx/utils/google-benchmark/src/timers.cc
@@ -17,11 +17,14 @@
#ifdef BENCHMARK_OS_WINDOWS
#include <Shlwapi.h>
+#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
#include <VersionHelpers.h>
#include <Windows.h>
#else
#include <fcntl.h>
+#ifndef BENCHMARK_OS_FUCHSIA
#include <sys/resource.h>
+#endif
#include <sys/time.h>
#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
#include <unistd.h>
@@ -74,7 +77,7 @@ double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) {
static_cast<double>(user.QuadPart)) *
1e-7;
}
-#else
+#elif !defined(BENCHMARK_OS_FUCHSIA)
double MakeTime(struct rusage const& ru) {
return (static_cast<double>(ru.ru_utime.tv_sec) +
static_cast<double>(ru.ru_utime.tv_usec) * 1e-6 +
@@ -162,6 +165,10 @@ double ThreadCPUUsage() {
// RTEMS doesn't support CLOCK_THREAD_CPUTIME_ID. See
// https://github.com/RTEMS/rtems/blob/master/cpukit/posix/src/clockgettime.c
return ProcessCPUUsage();
+#elif defined(BENCHMARK_OS_SOLARIS)
+ struct rusage ru;
+ if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru);
+ DiagnoseAndExit("getrusage(RUSAGE_LWP, ...) failed");
#elif defined(CLOCK_THREAD_CPUTIME_ID)
struct timespec ts;
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts);
@@ -186,7 +193,6 @@ std::string DateTimeString(bool local) {
std::strftime(storage, sizeof(storage), "%x %X", ::localtime(&now));
#else
std::tm timeinfo;
- std::memset(&timeinfo, 0, sizeof(std::tm));
::localtime_r(&now, &timeinfo);
written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo);
#endif
@@ -195,7 +201,6 @@ std::string DateTimeString(bool local) {
written = std::strftime(storage, sizeof(storage), "%x %X", ::gmtime(&now));
#else
std::tm timeinfo;
- std::memset(&timeinfo, 0, sizeof(std::tm));
::gmtime_r(&now, &timeinfo);
written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo);
#endif
OpenPOWER on IntegriCloud