From 7e9138f8c167e5248788769da2dcff57918ce023 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Sat, 11 Apr 2026 16:52:24 -0700 Subject: [PATCH] [upstream_utils] Upgrade to Google Benchmark 1.9.5 (#8760) --- .github/workflows/upstream-utils.yml | 6 + .../benchmark/include/benchmark/benchmark.h | 151 ++++++++++++------ .../thirdparty/benchmark/src/benchmark.cpp | 8 +- .../benchmark/src/benchmark_api_internal.cpp | 3 +- .../benchmark/src/benchmark_api_internal.h | 4 +- .../benchmark/src/benchmark_register.cpp | 47 +++--- .../benchmark/src/benchmark_register.h | 1 + .../benchmark/src/benchmark_runner.cpp | 14 +- .../thirdparty/benchmark/src/colorprint.h | 7 +- .../benchmark/src/commandlineflags.cpp | 4 + .../thirdparty/benchmark/src/complexity.cpp | 9 +- .../benchmark/src/console_reporter.cpp | 1 + .../thirdparty/benchmark/src/counter.cpp | 4 + .../thirdparty/benchmark/src/csv_reporter.cpp | 9 +- .../thirdparty/benchmark/src/cycleclock.h | 10 +- .../benchmark/src/internal_macros.h | 10 ++ .../benchmark/src/json_reporter.cpp | 4 +- .../benchmark/src/perf_counters.cpp | 2 +- .../main/native/thirdparty/benchmark/src/re.h | 2 + .../thirdparty/benchmark/src/string_util.cpp | 5 +- .../thirdparty/benchmark/src/sysinfo.cpp | 2 +- upstream_utils/benchmark.py | 2 +- .../0001-Add-roboRIO-benchmark-support.patch | 2 +- .../0002-Suppress-Wformat-nonliteral.patch | 6 +- 24 files changed, 215 insertions(+), 98 deletions(-) diff --git a/.github/workflows/upstream-utils.yml b/.github/workflows/upstream-utils.yml index 4f6c8f9ff3..10a675e2ed 100644 --- a/.github/workflows/upstream-utils.yml +++ b/.github/workflows/upstream-utils.yml @@ -42,6 +42,12 @@ jobs: ./argparse_lib.py clone ./argparse_lib.py copy-src ./argparse_lib.py format-patch + - name: Run benchmark.py + run: | + cd upstream_utils + ./benchmark.py clone + ./benchmark.py copy-src + ./benchmark.py format-patch - name: Run double-conversion.py run: | cd upstream_utils diff --git a/benchmark/src/main/native/thirdparty/benchmark/include/benchmark/benchmark.h b/benchmark/src/main/native/thirdparty/benchmark/include/benchmark/benchmark.h index f455e05d78..f7d1341c8f 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/include/benchmark/benchmark.h +++ b/benchmark/src/main/native/thirdparty/benchmark/include/benchmark/benchmark.h @@ -103,7 +103,7 @@ BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {128, 512}}); // arbitrary set of arguments to run the microbenchmark on. // The following example enumerates a dense range on // one parameter, and a sparse range on the second. -static void CustomArguments(benchmark::internal::Benchmark* b) { +static void CustomArguments(benchmark::Benchmark* b) { for (int i = 0; i <= 10; ++i) for (int j = 32; j <= 1024*1024; j *= 8) b->Args({i, j}); @@ -171,7 +171,6 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #include #include #include -#include #include #include #include @@ -239,6 +238,16 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); _Pragma("diagnostic push") \ _Pragma("diag_suppress deprecated_entity_with_custom_message") #define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("diagnostic pop") +#elif defined(_MSC_VER) +#define BENCHMARK_BUILTIN_EXPECT(x, y) x +#define BENCHMARK_DEPRECATED_MSG(msg) __declspec(deprecated(msg)) +#define BENCHMARK_WARNING_MSG(msg) \ + __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \ + __LINE__) ") : warning note: " msg)) +#define BENCHMARK_DISABLE_DEPRECATED_WARNING \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) +#define BENCHMARK_RESTORE_DEPRECATED_WARNING __pragma(warning(pop)) #else #define BENCHMARK_BUILTIN_EXPECT(x, y) x #define BENCHMARK_DEPRECATED_MSG(msg) @@ -476,10 +485,11 @@ void RegisterProfilerManager(ProfilerManager* profiler_manager); // Add a key-value pair to output as part of the context stanza in the report. BENCHMARK_EXPORT -void AddCustomContext(const std::string& key, const std::string& value); +void AddCustomContext(std::string key, std::string value); + +class Benchmark; namespace internal { -class Benchmark; class BenchmarkImp; class BenchmarkFamilies; @@ -611,6 +621,17 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { _ReadWriteBarrier(); } +template +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) { + internal::UseCharPointer(&reinterpret_cast(value)); + _ReadWriteBarrier(); +} + +template +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) { + internal::UseCharPointer(&reinterpret_cast(value)); + _ReadWriteBarrier(); +} #else template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) { @@ -956,6 +977,8 @@ class BENCHMARK_EXPORT BENCHMARK_INTERNAL_CACHELINE_ALIGNED State { BENCHMARK_ALWAYS_INLINE std::string name() const { return name_; } + size_t range_size() const { return range_.size(); } + private: // items we expect on the first cache line (ie 64 bytes of the struct) // When total_iterations_ is 0, KeepRunning() and friends will return false. @@ -1102,20 +1125,15 @@ struct ThreadRunnerBase { virtual void RunThreads(const std::function& fn) = 0; }; -namespace internal { - // Define alias of ThreadRunner factory function type using threadrunner_factory = std::function(int)>; -typedef void(Function)(State&); - // ------------------------------------------------------ -// Benchmark registration object. The BENCHMARK() macro expands -// into an internal::Benchmark* object. Various methods can -// be called on this object to change the properties of the benchmark. -// Each method returns "this" so that multiple method calls can -// chained into one expression. +// Benchmark registration object. The BENCHMARK() macro expands into a +// Benchmark* object. Various methods can be called on this object to +// change the properties of the benchmark. Each method returns "this" so +// that multiple method calls can chained into one expression. class BENCHMARK_EXPORT Benchmark { public: virtual ~Benchmark(); @@ -1206,7 +1224,7 @@ class BENCHMARK_EXPORT Benchmark { // Pass this benchmark object to *func, which can customize // the benchmark by calling various methods like Arg, Args, // Threads, etc. - Benchmark* Apply(void (*custom_arguments)(Benchmark* benchmark)); + Benchmark* Apply(const std::function&); // Set the range multiplier for non-dense range. If not called, the range // multiplier kRangeMultiplier will be used. @@ -1329,11 +1347,11 @@ class BENCHMARK_EXPORT Benchmark { const char* GetArgName(int arg) const; private: - friend class BenchmarkFamilies; - friend class BenchmarkInstance; + friend class internal::BenchmarkFamilies; + friend class internal::BenchmarkInstance; std::string name_; - AggregationReportMode aggregation_report_mode_; + internal::AggregationReportMode aggregation_report_mode_; std::vector arg_names_; // Args for all benchmark runs std::vector> args_; // Args for all benchmark runs @@ -1350,7 +1368,7 @@ class BENCHMARK_EXPORT Benchmark { bool use_manual_time_; BigO complexity_; BigOFunc* complexity_lambda_; - std::vector statistics_; + std::vector statistics_; std::vector thread_counts_; callback_function setup_; @@ -1361,17 +1379,28 @@ class BENCHMARK_EXPORT Benchmark { BENCHMARK_DISALLOW_COPY_AND_ASSIGN(Benchmark); }; +namespace internal { + +// clang-format off +typedef BENCHMARK_DEPRECATED_MSG("Use ::benchmark::Benchmark instead") + ::benchmark::Benchmark Benchmark; +typedef BENCHMARK_DEPRECATED_MSG( + "Use ::benchmark::threadrunner_factory instead") + ::benchmark::threadrunner_factory threadrunner_factory; +// clang-format on + +typedef void(Function)(State&); + } // namespace internal // Create and register a benchmark with the specified 'name' that invokes // the specified functor 'fn'. // // RETURNS: A pointer to the registered benchmark. -internal::Benchmark* RegisterBenchmark(const std::string& name, - internal::Function* fn); +Benchmark* RegisterBenchmark(const std::string& name, internal::Function* fn); template -internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn); +Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn); // Remove all registered benchmarks. All pointers to previously registered // benchmarks are invalidated. @@ -1380,7 +1409,7 @@ BENCHMARK_EXPORT void ClearRegisteredBenchmarks(); namespace internal { // The class used to hold all Benchmarks created from static function. // (ie those created using the BENCHMARK(...) macros. -class BENCHMARK_EXPORT FunctionBenchmark : public Benchmark { +class BENCHMARK_EXPORT FunctionBenchmark : public benchmark::Benchmark { public: FunctionBenchmark(const std::string& name, Function* func) : Benchmark(name), func_(func) {} @@ -1392,7 +1421,7 @@ class BENCHMARK_EXPORT FunctionBenchmark : public Benchmark { }; template -class LambdaBenchmark : public Benchmark { +class LambdaBenchmark : public benchmark::Benchmark { public: void Run(State& st) override { lambda_(st); } @@ -1406,15 +1435,15 @@ class LambdaBenchmark : public Benchmark { }; } // namespace internal -inline internal::Benchmark* RegisterBenchmark(const std::string& name, - internal::Function* fn) { +inline Benchmark* RegisterBenchmark(const std::string& name, + internal::Function* fn) { return internal::RegisterBenchmarkInternal( ::benchmark::internal::make_unique(name, fn)); } template -internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn) { +Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn) { using BenchType = internal::LambdaBenchmark::type>; return internal::RegisterBenchmarkInternal( @@ -1423,16 +1452,16 @@ internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn) { } template -internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn, - Args&&... args) { +Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn, + Args&&... args) { return benchmark::RegisterBenchmark( name, [=](benchmark::State& st) { fn(st, args...); }); } // The base class for all fixture tests. -class Fixture : public internal::Benchmark { +class Fixture : public Benchmark { public: - Fixture() : internal::Benchmark("") {} + Fixture() : Benchmark("") {} void Run(State& st) override { this->SetUp(st); @@ -1455,14 +1484,29 @@ class Fixture : public internal::Benchmark { // ------------------------------------------------------ // Macro to register benchmarks +// clang-format off +#if defined(__clang__) +#define BENCHMARK_DISABLE_COUNTER_WARNING \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wunknown-warning-option\"") \ + _Pragma("GCC diagnostic ignored \"-Wc2y-extensions\"") +#define BENCHMARK_RESTORE_COUNTER_WARNING _Pragma("GCC diagnostic pop") +#else +#define BENCHMARK_DISABLE_COUNTER_WARNING +#define BENCHMARK_RESTORE_COUNTER_WARNING +#endif +// clang-format on + // Check that __COUNTER__ is defined and that __COUNTER__ increases by 1 // every time it is expanded. X + 1 == X + 0 is used in case X is defined to be // empty. If X is empty the expression becomes (+1 == +0). +BENCHMARK_DISABLE_COUNTER_WARNING #if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0) #define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__ #else #define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__ #endif +BENCHMARK_RESTORE_COUNTER_WARNING // Helpers for generating unique variable names #define BENCHMARK_PRIVATE_NAME(...) \ @@ -1475,17 +1519,19 @@ class Fixture : public internal::Benchmark { #define BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method) \ BaseClass##_##Method##_Benchmark -#define BENCHMARK_PRIVATE_DECLARE(n) \ - /* NOLINTNEXTLINE(misc-use-anonymous-namespace) */ \ - static ::benchmark::internal::Benchmark const* const BENCHMARK_PRIVATE_NAME( \ - n) BENCHMARK_UNUSED +#define BENCHMARK_PRIVATE_DECLARE(n) \ + BENCHMARK_DISABLE_COUNTER_WARNING \ + /* NOLINTNEXTLINE(misc-use-anonymous-namespace) */ \ + static ::benchmark::Benchmark const* const BENCHMARK_PRIVATE_NAME(n) \ + BENCHMARK_RESTORE_COUNTER_WARNING BENCHMARK_UNUSED -#define BENCHMARK(...) \ - BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \ - (::benchmark::internal::RegisterBenchmarkInternal( \ - ::benchmark::internal::make_unique< \ - ::benchmark::internal::FunctionBenchmark>(#__VA_ARGS__, \ - __VA_ARGS__))) +#define BENCHMARK(...) \ + BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \ + (::benchmark::internal::RegisterBenchmarkInternal( \ + ::benchmark::internal::make_unique< \ + ::benchmark::internal::FunctionBenchmark>( \ + #__VA_ARGS__, \ + static_cast<::benchmark::internal::Function*>(__VA_ARGS__)))) // Old-style macros #define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a)) @@ -1526,21 +1572,25 @@ class Fixture : public internal::Benchmark { BENCHMARK_PRIVATE_DECLARE(n) = \ (::benchmark::internal::RegisterBenchmarkInternal( \ ::benchmark::internal::make_unique< \ - ::benchmark::internal::FunctionBenchmark>(#n "<" #a ">", n))) + ::benchmark::internal::FunctionBenchmark>( \ + #n "<" #a ">", \ + static_cast<::benchmark::internal::Function*>(n)))) -#define BENCHMARK_TEMPLATE2(n, a, b) \ - BENCHMARK_PRIVATE_DECLARE(n) = \ - (::benchmark::internal::RegisterBenchmarkInternal( \ - ::benchmark::internal::make_unique< \ - ::benchmark::internal::FunctionBenchmark>(#n "<" #a "," #b ">", \ - n))) +#define BENCHMARK_TEMPLATE2(n, a, b) \ + BENCHMARK_PRIVATE_DECLARE(n) = \ + (::benchmark::internal::RegisterBenchmarkInternal( \ + ::benchmark::internal::make_unique< \ + ::benchmark::internal::FunctionBenchmark>( \ + #n "<" #a "," #b ">", \ + static_cast<::benchmark::internal::Function*>(n)))) #define BENCHMARK_TEMPLATE(n, ...) \ BENCHMARK_PRIVATE_DECLARE(n) = \ (::benchmark::internal::RegisterBenchmarkInternal( \ ::benchmark::internal::make_unique< \ ::benchmark::internal::FunctionBenchmark>( \ - #n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>))) + #n "<" #__VA_ARGS__ ">", \ + static_cast<::benchmark::internal::Function*>(n<__VA_ARGS__>)))) // This will register a benchmark for a templatized function, // with the additional arguments specified by `...`. @@ -1661,9 +1711,11 @@ class Fixture : public internal::Benchmark { ::benchmark::internal::make_unique())) #define BENCHMARK_TEMPLATE_INSTANTIATE_F(BaseClass, Method, ...) \ + BENCHMARK_DISABLE_COUNTER_WARNING \ BENCHMARK_TEMPLATE_PRIVATE_INSTANTIATE_F( \ BaseClass, Method, BENCHMARK_PRIVATE_NAME(BaseClass##Method), \ - __VA_ARGS__) + __VA_ARGS__) \ + BENCHMARK_RESTORE_COUNTER_WARNING // This macro will define and register a benchmark within a fixture class. #define BENCHMARK_F(BaseClass, Method) \ @@ -1798,6 +1850,7 @@ class BENCHMARK_EXPORT BenchmarkReporter { complexity(oNone), complexity_lambda(), complexity_n(0), + statistics(), report_big_o(false), report_rms(false), allocs_per_iter(0.0) {} diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark.cpp index 8672c8a94f..fc36fedb19 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark.cpp @@ -708,11 +708,12 @@ void RegisterProfilerManager(ProfilerManager* manager) { internal::profiler_manager = manager; } -void AddCustomContext(const std::string& key, const std::string& value) { +void AddCustomContext(std::string key, std::string value) { if (internal::global_context == nullptr) { internal::global_context = new std::map(); } - if (!internal::global_context->emplace(key, value).second) { + if (!internal::global_context->emplace(std::move(key), std::move(value)) + .second) { std::cerr << "Failed to add custom context \"" << key << "\" as it already " << "exists with value \"" << value << "\"\n"; } @@ -722,6 +723,7 @@ namespace internal { void (*HelperPrintf)(); +namespace { void PrintUsageAndExit() { HelperPrintf(); std::flush(std::cout); @@ -810,6 +812,8 @@ void ParseCommandLineFlags(int* argc, char** argv) { } } +} // end namespace + int InitializeStreams() { static std::ios_base::Init init; return 0; diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_api_internal.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_api_internal.cpp index 60609d30cd..f9c4990ddf 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_api_internal.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_api_internal.cpp @@ -7,7 +7,8 @@ namespace benchmark { namespace internal { -BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx, +BenchmarkInstance::BenchmarkInstance(benchmark::Benchmark* benchmark, + int family_idx, int per_family_instance_idx, const std::vector& args, int thread_count) diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_api_internal.h b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_api_internal.h index efa0602173..5b48ea2fdf 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_api_internal.h +++ b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_api_internal.h @@ -17,7 +17,7 @@ namespace internal { // Information kept per benchmark we may want to run class BenchmarkInstance { public: - BenchmarkInstance(Benchmark* benchmark, int family_idx, + BenchmarkInstance(benchmark::Benchmark* benchmark, int family_idx, int per_family_instance_idx, const std::vector& args, int thread_count); @@ -52,7 +52,7 @@ class BenchmarkInstance { private: BenchmarkName name_; - Benchmark& benchmark_; + benchmark::Benchmark& benchmark_; const int family_index_; const int per_family_instance_index_; AggregationReportMode aggregation_report_mode_; diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_register.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_register.cpp index d8cefe480c..65e1afced3 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_register.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_register.cpp @@ -75,7 +75,7 @@ class BenchmarkFamilies { static BenchmarkFamilies* GetInstance(); // Registers a benchmark family and returns the index assigned to it. - size_t AddBenchmark(std::unique_ptr family); + size_t AddBenchmark(std::unique_ptr family); // Clear all registered benchmark families. void ClearBenchmarks(); @@ -89,7 +89,7 @@ class BenchmarkFamilies { private: BenchmarkFamilies() {} - std::vector> families_; + std::vector> families_; Mutex mutex_; }; @@ -98,7 +98,8 @@ BenchmarkFamilies* BenchmarkFamilies::GetInstance() { return &instance; } -size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr family) { +size_t BenchmarkFamilies::AddBenchmark( + std::unique_ptr family) { MutexLock l(mutex_); size_t index = families_.size(); families_.push_back(std::move(family)); @@ -135,7 +136,7 @@ bool BenchmarkFamilies::FindBenchmarks( int next_family_index = 0; MutexLock l(mutex_); - for (std::unique_ptr& family : families_) { + for (std::unique_ptr& family : families_) { int family_index = next_family_index; int per_family_instance_index = 0; @@ -179,7 +180,7 @@ bool BenchmarkFamilies::FindBenchmarks( ++per_family_instance_index; - // Only bump the next family index once we've estabilished that + // Only bump the next family index once we've established that // at least one instance of this family will be run. if (next_family_index == family_index) { ++next_family_index; @@ -191,8 +192,9 @@ bool BenchmarkFamilies::FindBenchmarks( return true; } -Benchmark* RegisterBenchmarkInternal(std::unique_ptr bench) { - Benchmark* bench_ptr = bench.get(); +benchmark::Benchmark* RegisterBenchmarkInternal( + std::unique_ptr bench) { + benchmark::Benchmark* bench_ptr = bench.get(); BenchmarkFamilies* families = BenchmarkFamilies::GetInstance(); families->AddBenchmark(std::move(bench)); return bench_ptr; @@ -206,13 +208,15 @@ bool FindBenchmarksInternal(const std::string& re, return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err); } +} // end namespace internal + //=============================================================================// // Benchmark //=============================================================================// Benchmark::Benchmark(const std::string& name) : name_(name), - aggregation_report_mode_(ARM_Unspecified), + aggregation_report_mode_(internal::ARM_Unspecified), time_unit_(GetDefaultTimeUnit()), use_default_time_unit_(true), range_multiplier_(kRangeMultiplier), @@ -253,7 +257,7 @@ Benchmark* Benchmark::Unit(TimeUnit unit) { Benchmark* Benchmark::Range(int64_t start, int64_t limit) { BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); std::vector arglist; - AddRange(&arglist, start, limit, range_multiplier_); + internal::AddRange(&arglist, start, limit, range_multiplier_); for (int64_t i : arglist) { args_.push_back({i}); @@ -266,8 +270,8 @@ Benchmark* Benchmark::Ranges( BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(ranges.size())); std::vector> arglists(ranges.size()); for (std::size_t i = 0; i < ranges.size(); i++) { - AddRange(&arglists[i], ranges[i].first, ranges[i].second, - range_multiplier_); + internal::AddRange(&arglists[i], ranges[i].first, ranges[i].second, + range_multiplier_); } ArgsProduct(arglists); @@ -330,7 +334,8 @@ Benchmark* Benchmark::Args(const std::vector& args) { return this; } -Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) { +Benchmark* Benchmark::Apply( + const std::function& custom_arguments) { custom_arguments(this); return this; } @@ -381,8 +386,8 @@ Benchmark* Benchmark::MinWarmUpTime(double t) { Benchmark* Benchmark::Iterations(IterationCount n) { BM_CHECK(n > 0); - BM_CHECK(IsZero(min_time_)); - BM_CHECK(IsZero(min_warmup_time_)); + BM_CHECK(internal::IsZero(min_time_)); + BM_CHECK(internal::IsZero(min_warmup_time_)); iterations_ = n; return this; } @@ -394,21 +399,23 @@ Benchmark* Benchmark::Repetitions(int n) { } Benchmark* Benchmark::ReportAggregatesOnly(bool value) { - aggregation_report_mode_ = value ? ARM_ReportAggregatesOnly : ARM_Default; + aggregation_report_mode_ = + value ? internal::ARM_ReportAggregatesOnly : internal::ARM_Default; return this; } Benchmark* Benchmark::DisplayAggregatesOnly(bool value) { // If we were called, the report mode is no longer 'unspecified', in any case. + using internal::AggregationReportMode; aggregation_report_mode_ = static_cast( - aggregation_report_mode_ | ARM_Default); + aggregation_report_mode_ | internal::ARM_Default); if (value) { aggregation_report_mode_ = static_cast( - aggregation_report_mode_ | ARM_DisplayReportAggregatesOnly); + aggregation_report_mode_ | internal::ARM_DisplayReportAggregatesOnly); } else { aggregation_report_mode_ = static_cast( - aggregation_report_mode_ & ~ARM_DisplayReportAggregatesOnly); + aggregation_report_mode_ & ~internal::ARM_DisplayReportAggregatesOnly); } return this; @@ -462,7 +469,7 @@ Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) { BM_CHECK_GT(min_threads, 0); BM_CHECK_GE(max_threads, min_threads); - AddRange(&thread_counts_, min_threads, max_threads, 2); + internal::AddRange(&thread_counts_, min_threads, max_threads, 2); return this; } @@ -514,6 +521,8 @@ TimeUnit Benchmark::GetTimeUnit() const { return use_default_time_unit_ ? GetDefaultTimeUnit() : time_unit_; } +namespace internal { + //=============================================================================// // FunctionBenchmark //=============================================================================// diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_register.h b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_register.h index be50265f72..e0ace51ef0 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_register.h +++ b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_register.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "check.h" diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_runner.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_runner.cpp index 1f5bb6b79f..fb688672a4 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_runner.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/benchmark_runner.cpp @@ -123,7 +123,12 @@ BenchmarkReporter::Run CreateRunReport( : 0; } - internal::Finish(&report.counters, results.iterations, seconds, + // The CPU time is the total time taken by all thread. If we used that as + // the denominator, we'd be calculating the rate per thread here. This is + // why we have to divide the total cpu_time by the number of threads for + // global counters to get a global rate. + const double thread_seconds = seconds / b.threads(); + internal::Finish(&report.counters, results.iterations, thread_seconds, b.threads()); } return report; @@ -191,7 +196,7 @@ class ThreadRunnerDefault : public ThreadRunnerBase { explicit ThreadRunnerDefault(int num_threads) : pool(static_cast(num_threads - 1)) {} - void RunThreads(const std::function& fn) final { + void RunThreads(const std::function& fn) override final { // Run all but one thread in separate threads for (std::size_t ti = 0; ti < pool.size(); ++ti) { pool[ti] = std::thread(fn, static_cast(ti + 1)); @@ -212,7 +217,8 @@ class ThreadRunnerDefault : public ThreadRunnerBase { }; std::unique_ptr GetThreadRunner( - const threadrunner_factory& userThreadRunnerFactory, int num_threads) { + const benchmark::threadrunner_factory& userThreadRunnerFactory, + int num_threads) { return userThreadRunnerFactory ? userThreadRunnerFactory(num_threads) : std::make_unique(num_threads); @@ -400,7 +406,7 @@ bool BenchmarkRunner::ShouldReportIterationResults( } double BenchmarkRunner::GetMinTimeToApply() const { - // In order to re-use functionality to run and measure benchmarks for running + // In order to reuse functionality to run and measure benchmarks for running // a warmup phase of the benchmark, we need a way of telling whether to apply // min_time or min_warmup_time. This function will figure out if we are in the // warmup phase and therefore need to apply min_warmup_time or if we already diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/colorprint.h b/benchmark/src/main/native/thirdparty/benchmark/src/colorprint.h index 9f6fab9b34..469045c5f5 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/colorprint.h +++ b/benchmark/src/main/native/thirdparty/benchmark/src/colorprint.h @@ -5,6 +5,8 @@ #include #include +#include "internal_macros.h" + namespace benchmark { enum LogColor { COLOR_DEFAULT, @@ -17,11 +19,14 @@ enum LogColor { COLOR_WHITE }; +PRINTF_FORMAT_STRING_FUNC(1, 0) std::string FormatString(const char* msg, va_list args); -std::string FormatString(const char* msg, ...); +PRINTF_FORMAT_STRING_FUNC(1, 2) std::string FormatString(const char* msg, ...); +PRINTF_FORMAT_STRING_FUNC(3, 0) void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, va_list args); +PRINTF_FORMAT_STRING_FUNC(3, 4) void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...); // Returns true if stdout appears to be a terminal that supports colored diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/commandlineflags.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/commandlineflags.cpp index 3ab280a028..99a240c122 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/commandlineflags.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/commandlineflags.cpp @@ -179,6 +179,8 @@ std::map KvPairsFromEnv( return value; } +namespace { + // Parses a string as a command line flag. The string should have // the format "--flag=value". When def_optional is true, the "=value" // part can be omitted. @@ -217,6 +219,8 @@ const char* ParseFlagValue(const char* str, const char* flag, return flag_end + 1; } +} // end namespace + BENCHMARK_EXPORT bool ParseBoolFlag(const char* str, const char* flag, bool* value) { // Gets the value of the flag as a string. diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/complexity.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/complexity.cpp index a474645a0d..4c9ef6d0c7 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/complexity.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/complexity.cpp @@ -17,7 +17,6 @@ #include "complexity.h" -#include #include #include "benchmark/benchmark.h" @@ -25,6 +24,8 @@ namespace benchmark { +namespace { + // Internal function to calculate the different scalability forms BigOFunc* FittingCurve(BigO complexity) { switch (complexity) { @@ -48,6 +49,8 @@ BigOFunc* FittingCurve(BigO complexity) { } } +} // end namespace + // Function to return an string for the calculated complexity std::string GetBigOString(BigO complexity) { switch (complexity) { @@ -68,6 +71,8 @@ std::string GetBigOString(BigO complexity) { } } +namespace { + // 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 expression. @@ -152,6 +157,8 @@ LeastSq MinimalLeastSq(const std::vector& n, return best_fit; } +} // end namespace + std::vector ComputeBigO( const std::vector& reports) { typedef BenchmarkReporter::Run Run; diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/console_reporter.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/console_reporter.cpp index 0bb9f27fbf..6db6788f94 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/console_reporter.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/console_reporter.cpp @@ -97,6 +97,7 @@ void ConsoleReporter::ReportRuns(const std::vector& reports) { } } +PRINTF_FORMAT_STRING_FUNC(3, 4) static void IgnoreColorPrint(std::ostream& out, LogColor /*unused*/, const char* fmt, ...) { va_list args; diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/counter.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/counter.cpp index a76bf76770..4bdd5e9b59 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/counter.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/counter.cpp @@ -17,6 +17,8 @@ namespace benchmark { namespace internal { +namespace { + double Finish(Counter const& c, IterationCount iterations, double cpu_time, double num_threads) { double v = c.value; @@ -39,6 +41,8 @@ double Finish(Counter const& c, IterationCount iterations, double cpu_time, return v; } +} // namespace + void Finish(UserCounters* l, IterationCount iterations, double cpu_time, double num_threads) { for (auto& c : *l) { diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/csv_reporter.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/csv_reporter.cpp index 3ee434b43c..0f998045bd 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/csv_reporter.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/csv_reporter.cpp @@ -12,29 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include -#include #include #include -#include #include #include "benchmark/benchmark.h" #include "check.h" #include "complexity.h" -#include "string_util.h" -#include "timers.h" // File format reference: http://edoceo.com/utilitas/csv-file-format. namespace benchmark { namespace { -std::vector elements = { +const std::vector elements = { "name", "iterations", "real_time", "cpu_time", "time_unit", "bytes_per_second", "items_per_second", "label", "error_occurred", "error_message"}; -} // namespace std::string CsvEscape(const std::string& s) { std::string tmp; @@ -51,6 +45,7 @@ std::string CsvEscape(const std::string& s) { } return '"' + tmp + '"'; } +} // namespace BENCHMARK_EXPORT bool CSVReporter::ReportContext(const Context& context) { diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/cycleclock.h b/benchmark/src/main/native/thirdparty/benchmark/src/cycleclock.h index 3951ff3546..0671a425f0 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/cycleclock.h +++ b/benchmark/src/main/native/thirdparty/benchmark/src/cycleclock.h @@ -36,6 +36,9 @@ // declarations of some other intrinsics, breaking compilation. // Therefore, we simply declare __rdtsc ourselves. See also // http://connect.microsoft.com/VisualStudio/feedback/details/262047 +// +// Note that MSVC defines the x64 preprocessor macros when building +// for Arm64EC, despite it using Arm64 assembly instructions. #if defined(COMPILER_MSVC) && !defined(_M_IX86) && !defined(_M_ARM64) && \ !defined(_M_ARM64EC) extern "C" uint64_t __rdtsc(); @@ -79,7 +82,10 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { int64_t ret; __asm__ volatile("rdtsc" : "=A"(ret)); return ret; -#elif defined(__x86_64__) || defined(__amd64__) + +// Note that Clang, like MSVC, defines the x64 preprocessor macros when building +// for Arm64EC, despite it using Arm64 assembly instructions. +#elif (defined(__x86_64__) || defined(__amd64__)) && !defined(__arm64ec__) uint64_t low, high; __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); return static_cast((high << 32) | low); @@ -139,7 +145,7 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { struct timespec ts = {0, 0}; clock_gettime(CLOCK_MONOTONIC, &ts); return static_cast(ts.tv_sec) * 1000000000 + ts.tv_nsec; -#elif defined(__aarch64__) +#elif defined(__aarch64__) || defined(__arm64ec__) // System timer of ARMv8 runs at a different frequency than the CPU's. // The frequency is fixed, typically in the range 1-50MHz. It can be // read at CNTFRQ special register. We assume the OS has set up diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/internal_macros.h b/benchmark/src/main/native/thirdparty/benchmark/src/internal_macros.h index f4894ba8e6..22e3e21753 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/internal_macros.h +++ b/benchmark/src/main/native/thirdparty/benchmark/src/internal_macros.h @@ -106,6 +106,16 @@ #define BENCHMARK_MAYBE_UNUSED #endif +#if defined(__GNUC__) || defined(__clang__) +#define PRINTF_FORMAT_STRING_FUNC(format_arg, first_idx) \ + __attribute__((format(printf, format_arg, first_idx))) +#elif defined(__MINGW32__) +#define PRINTF_FORMAT_STRING_FUNC(format_arg, first_idx) \ + __attribute__((format(__MINGW_PRINTF_FORMAT, format_arg, first_idx))) +#else +#define PRINTF_FORMAT_STRING_FUNC(format_arg, first_idx) +#endif + // clang-format on #endif // BENCHMARK_INTERNAL_MACROS_H_ diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/json_reporter.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/json_reporter.cpp index deff77e9ac..2b84cd14a5 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/json_reporter.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/json_reporter.cpp @@ -81,7 +81,9 @@ std::string FormatKV(std::string const& key, bool value) { std::string FormatKV(std::string const& key, int64_t value) { std::stringstream ss; - ss << '"' << StrEscape(key) << "\": " << value; + // We really want to just dump the integer as-is, + // without the system locale interfering. + ss << '"' << StrEscape(key) << "\": " << std::to_string(value); return ss.str(); } diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/perf_counters.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/perf_counters.cpp index a2fa7fe35f..f47aa7b42d 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/perf_counters.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/perf_counters.cpp @@ -214,7 +214,7 @@ PerfCounters PerfCounters::Create( // This should never happen but if it does, we give up on the // entire batch as recovery would be a mess. GetErrorLogInstance() << "***WARNING*** Failed to start counters. " - "Claring out all counters.\n"; + "Clearing out all counters.\n"; // Close all performance counters for (int id : counter_ids) { diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/re.h b/benchmark/src/main/native/thirdparty/benchmark/src/re.h index af4b8bb16e..1486dd8778 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/re.h +++ b/benchmark/src/main/native/thirdparty/benchmark/src/re.h @@ -15,6 +15,8 @@ #ifndef BENCHMARK_RE_H_ #define BENCHMARK_RE_H_ +#include + #include "internal_macros.h" // clang-format off diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/string_util.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/string_util.cpp index 698129453c..9c483b3351 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/string_util.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/string_util.cpp @@ -112,13 +112,14 @@ std::string ToBinaryStringFullySpecified(double value, int precision, return mantissa + ExponentToPrefix(exponent, one_k == Counter::kIs1024); } +PRINTF_FORMAT_STRING_FUNC(1, 0) 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); - // TODO(ericwf): use std::array for first attempt to avoid one memory - // allocation guess what the size might be + // Use std::array for first attempt to avoid one memory allocation guess what + // the size might be std::array local_buff = {}; // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation diff --git a/benchmark/src/main/native/thirdparty/benchmark/src/sysinfo.cpp b/benchmark/src/main/native/thirdparty/benchmark/src/sysinfo.cpp index 93ad20b2f9..ec52119ad7 100644 --- a/benchmark/src/main/native/thirdparty/benchmark/src/sysinfo.cpp +++ b/benchmark/src/main/native/thirdparty/benchmark/src/sysinfo.cpp @@ -463,7 +463,7 @@ std::string GetSystemName() { DWCOUNT, NULL, 0, NULL, NULL); str.resize(len); WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, hostname, DWCOUNT, &str[0], - str.size(), NULL, NULL); + static_cast(str.size()), NULL, NULL); #endif return str; #elif defined(BENCHMARK_OS_QURT) diff --git a/upstream_utils/benchmark.py b/upstream_utils/benchmark.py index c1163a3617..c50eee2b1f 100755 --- a/upstream_utils/benchmark.py +++ b/upstream_utils/benchmark.py @@ -35,7 +35,7 @@ def copy_upstream_src(wpilib_root: Path): def main(): name = "benchmark" url = "https://github.com/google/benchmark.git" - tag = "v1.9.4" + tag = "v1.9.5" benchmark = Lib(name, url, tag, copy_upstream_src) benchmark.main() diff --git a/upstream_utils/benchmark_patches/0001-Add-roboRIO-benchmark-support.patch b/upstream_utils/benchmark_patches/0001-Add-roboRIO-benchmark-support.patch index 3d496379b1..e0b8e34b47 100644 --- a/upstream_utils/benchmark_patches/0001-Add-roboRIO-benchmark-support.patch +++ b/upstream_utils/benchmark_patches/0001-Add-roboRIO-benchmark-support.patch @@ -8,7 +8,7 @@ Subject: [PATCH 1/2] Add roboRIO benchmark support 1 file changed, 2 insertions(+) diff --git a/src/sysinfo.cc b/src/sysinfo.cc -index 60e9e5c219a470944609f36773b4d8effa019059..86922c0da6303e1c35b4f7cb92a751fb84ba6f95 100644 +index 3977772bfede4971379b157b5478abe7bdad21f7..ec52119ad73aca9c4667855e2f2fdbf4d22ced77 100644 --- a/src/sysinfo.cc +++ b/src/sysinfo.cc @@ -441,6 +441,8 @@ std::vector GetCacheSizes() { diff --git a/upstream_utils/benchmark_patches/0002-Suppress-Wformat-nonliteral.patch b/upstream_utils/benchmark_patches/0002-Suppress-Wformat-nonliteral.patch index 584e0ac042..22450cc271 100644 --- a/upstream_utils/benchmark_patches/0002-Suppress-Wformat-nonliteral.patch +++ b/upstream_utils/benchmark_patches/0002-Suppress-Wformat-nonliteral.patch @@ -43,10 +43,10 @@ index c90232f20ff7b6dfdc09ee2df02a6d735b1d99ea..c4c48d15a049f39c77aeee47ae46741e return buff.get(); } diff --git a/src/string_util.cc b/src/string_util.cc -index 420de4cf259ce0bf3087b004b1f0d0b1c78028a7..698129453cd6ea1baf5f12ae58db467008b6ce8c 100644 +index 9c5df3ba25c92012bbae5063522a17bb47777151..9c483b335136a5b0e62c5f364a5eb1dfef5a414d 100644 --- a/src/string_util.cc +++ b/src/string_util.cc -@@ -123,7 +123,14 @@ std::string StrFormatImp(const char* msg, va_list args) { +@@ -124,7 +124,14 @@ std::string StrFormatImp(const char* msg, va_list args) { // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation // in the android-ndk @@ -61,7 +61,7 @@ index 420de4cf259ce0bf3087b004b1f0d0b1c78028a7..698129453cd6ea1baf5f12ae58db4670 va_end(args_cp); -@@ -141,7 +148,14 @@ std::string StrFormatImp(const char* msg, va_list args) { +@@ -142,7 +149,14 @@ std::string StrFormatImp(const char* msg, va_list args) { auto buff_ptr = std::unique_ptr(new char[size]); // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation // in the android-ndk