diff options
author | ilnaz <ilnaz@ydb.tech> | 2022-07-21 09:45:49 +0300 |
---|---|---|
committer | ilnaz <ilnaz@ydb.tech> | 2022-07-21 09:45:49 +0300 |
commit | fab0834c2c9d7652c3b4b3897654a85b3fbb7885 (patch) | |
tree | 34d27f24cfe9c87ce9e6ce9b8866cc122d9b8e34 | |
parent | 6b94014b1082ce9c3c702bdc7051efd00658da1b (diff) | |
download | ydb-fab0834c2c9d7652c3b4b3897654a85b3fbb7885.tar.gz |
Get rid of 'streamImpl' in responses
33 files changed, 758 insertions, 266 deletions
diff --git a/contrib/libs/benchmark/AUTHORS b/contrib/libs/benchmark/AUTHORS index 2b8072e095b..7d689350b51 100644 --- a/contrib/libs/benchmark/AUTHORS +++ b/contrib/libs/benchmark/AUTHORS @@ -13,6 +13,7 @@ Alex Steele <steeleal123@gmail.com> Andriy Berestovskyy <berestovskyy@gmail.com> Arne Beer <arne@twobeer.de> Carto +Cezary SkrzyĆski <czars1988@gmail.com> Christian Wassermann <christian_wassermann@web.de> Christopher Seymour <chris.j.seymour@hotmail.com> Colin Braley <braley.colin@gmail.com> @@ -52,6 +53,7 @@ Paul Redmond <paul.redmond@gmail.com> Radoslav Yovchev <radoslav.tm@gmail.com> Roman Lebedev <lebedev.ri@gmail.com> Sayan Bhattacharjee <aero.sayan@gmail.com> +Shapr3D <google-contributors@shapr3d.com> Shuo Chen <chenshuo@chenshuo.com> Staffan Tjernstrom <staffantj@gmail.com> Steinar H. Gunderson <sgunderson@bigfoot.com> diff --git a/contrib/libs/benchmark/LICENSE b/contrib/libs/benchmark/LICENSE index d6456956733..a5c40b3ee13 100644 --- a/contrib/libs/benchmark/LICENSE +++ b/contrib/libs/benchmark/LICENSE @@ -200,3 +200,35 @@ 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. + + +Only benchmark/config/generate_export_header.bzl depends on the following licence: + + BSD 3-Clause License + +Copyright (c) [year], [fullname] + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/libs/benchmark/README.md b/contrib/libs/benchmark/README.md index 7b81d960fc1..205fb008af0 100644 --- a/contrib/libs/benchmark/README.md +++ b/contrib/libs/benchmark/README.md @@ -47,6 +47,8 @@ IRC channels: [Assembly Testing Documentation](docs/AssemblyTests.md) +[Building and installing Python bindings](docs/python_bindings.md) + ## Requirements The library can be used with C++03. However, it requires C++11 to build, diff --git a/contrib/libs/benchmark/include/benchmark/benchmark.h b/contrib/libs/benchmark/include/benchmark/benchmark.h index 56d2805c77c..b856066561b 100644 --- a/contrib/libs/benchmark/include/benchmark/benchmark.h +++ b/contrib/libs/benchmark/include/benchmark/benchmark.h @@ -187,6 +187,8 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #include <utility> #include <vector> +#include "benchmark/export.h" + #if defined(BENCHMARK_HAS_CXX11) #include <atomic> #include <initializer_list> @@ -280,18 +282,41 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #define BENCHMARK_OVERRIDE #endif +#if defined(_MSC_VER) +#pragma warning(push) +// C4251: <symbol> needs to have dll-interface to be used by clients of class +#pragma warning(disable : 4251) +#endif + namespace benchmark { class BenchmarkReporter; -void Initialize(int* argc, char** argv); -void Shutdown(); +BENCHMARK_EXPORT void PrintDefaultHelp(); + +BENCHMARK_EXPORT void Initialize(int* argc, char** argv, + void (*HelperPrinterf)() = PrintDefaultHelp); +BENCHMARK_EXPORT void Shutdown(); // Report to stdout all arguments in 'argv' as unrecognized except the first. // Returns true there is at least on unrecognized argument (i.e. 'argc' > 1). -bool ReportUnrecognizedArguments(int argc, char** argv); +BENCHMARK_EXPORT bool ReportUnrecognizedArguments(int argc, char** argv); // Returns the current value of --benchmark_filter. -std::string GetBenchmarkFilter(); +BENCHMARK_EXPORT std::string GetBenchmarkFilter(); + +// Sets a new value to --benchmark_filter. (This will override this flag's +// current value). +// Should be called after `benchmark::Initialize()`, as +// `benchmark::Initialize()` will override the flag's value. +BENCHMARK_EXPORT void SetBenchmarkFilter(std::string value); + +// Returns the current value of --v (command line value for verbosity). +BENCHMARK_EXPORT int32_t GetBenchmarkVerbosity(); + +// Creates a default display reporter. Used by the library when no display +// reporter is provided, but also made available for external use in case a +// custom reporter should respect the `--benchmark_format` flag as a fallback +BENCHMARK_EXPORT BenchmarkReporter* CreateDefaultDisplayReporter(); // Generate a list of benchmarks matching the specified --benchmark_filter flag // and if --benchmark_list_tests is specified return after printing the name @@ -309,18 +334,29 @@ std::string GetBenchmarkFilter(); // 'file_reporter' is ignored. // // RETURNS: The number of matching benchmarks. -size_t RunSpecifiedBenchmarks(); -size_t RunSpecifiedBenchmarks(std::string spec); +BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(); +BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(std::string spec); + +BENCHMARK_EXPORT size_t +RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter); +BENCHMARK_EXPORT size_t +RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, std::string spec); + +BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks( + BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter); +BENCHMARK_EXPORT size_t +RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, + BenchmarkReporter* file_reporter, std::string spec); + +// TimeUnit is passed to a benchmark in order to specify the order of magnitude +// for the measured time. +enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond, kSecond }; -size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter); -size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, - std::string spec); +BENCHMARK_EXPORT TimeUnit GetDefaultTimeUnit(); -size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, - BenchmarkReporter* file_reporter); -size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, - BenchmarkReporter* file_reporter, - std::string spec); +// Sets the default time unit the benchmarks use +// Has to be called before the benchmark loop to take effect +BENCHMARK_EXPORT void SetDefaultTimeUnit(TimeUnit unit); // If a MemoryManager is registered (via RegisterMemoryManager()), // it can be used to collect and report allocation metrics for a run of the @@ -369,9 +405,11 @@ class MemoryManager { // Register a MemoryManager instance that will be used to collect and report // allocation measurements for benchmark runs. +BENCHMARK_EXPORT void RegisterMemoryManager(MemoryManager* memory_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); namespace internal { @@ -379,14 +417,15 @@ class Benchmark; class BenchmarkImp; class BenchmarkFamilies; +BENCHMARK_EXPORT void UseCharPointer(char const volatile*); // Take ownership of the pointer and register the benchmark. Return the // registered benchmark. -Benchmark* RegisterBenchmarkInternal(Benchmark*); +BENCHMARK_EXPORT Benchmark* RegisterBenchmarkInternal(Benchmark*); // Ensure that the standard streams are properly initialized in every TU. -int InitializeStreams(); +BENCHMARK_EXPORT int InitializeStreams(); BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams(); } // namespace internal @@ -409,6 +448,7 @@ inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { // intended to add little to no overhead. // See: https://youtu.be/nXaxk27zwlk?t=2441 #ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY +#if !defined(__GNUC__) || defined(__llvm__) || defined(__INTEL_COMPILER) template <class Tp> inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { asm volatile("" : : "r,m"(value) : "memory"); @@ -422,6 +462,55 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) { asm volatile("" : "+m,r"(value) : : "memory"); #endif } +#elif defined(BENCHMARK_HAS_CXX11) && (__GNUC__ >= 5) +// Workaround for a bug with full argument copy overhead with GCC. +// See: #1340 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105519 +template <class Tp> +inline BENCHMARK_ALWAYS_INLINE + typename std::enable_if<std::is_trivially_copyable<Tp>::value && + (sizeof(Tp) <= sizeof(Tp*))>::type + DoNotOptimize(Tp const& value) { + asm volatile("" : : "r,m"(value) : "memory"); +} + +template <class Tp> +inline BENCHMARK_ALWAYS_INLINE + typename std::enable_if<!std::is_trivially_copyable<Tp>::value || + (sizeof(Tp) > sizeof(Tp*))>::type + DoNotOptimize(Tp const& value) { + asm volatile("" : : "m"(value) : "memory"); +} + +template <class Tp> +inline BENCHMARK_ALWAYS_INLINE + typename std::enable_if<std::is_trivially_copyable<Tp>::value && + (sizeof(Tp) <= sizeof(Tp*))>::type + DoNotOptimize(Tp& value) { + asm volatile("" : "+m,r"(value) : : "memory"); +} + +template <class Tp> +inline BENCHMARK_ALWAYS_INLINE + typename std::enable_if<!std::is_trivially_copyable<Tp>::value || + (sizeof(Tp) > sizeof(Tp*))>::type + DoNotOptimize(Tp& value) { + asm volatile("" : "+m"(value) : : "memory"); +} + +#else +// Fallback for GCC < 5. Can add some overhead because the compiler is forced +// to use memory operations instead of operations with registers. +// TODO: Remove if GCC < 5 will be unsupported. +template <class Tp> +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { + asm volatile("" : : "m"(value) : "memory"); +} + +template <class Tp> +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) { + asm volatile("" : "+m"(value) : : "memory"); +} +#endif #ifndef BENCHMARK_HAS_CXX11 inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { @@ -506,17 +595,13 @@ Counter::Flags inline operator|(const Counter::Flags& LHS, // This is the container for the user-defined counters. typedef std::map<std::string, Counter> UserCounters; -// TimeUnit is passed to a benchmark in order to specify the order of magnitude -// for the measured time. -enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond, kSecond }; - // BigO is passed to a benchmark in order to specify the asymptotic // computational // complexity for the benchmark. In case oAuto is selected, complexity will be // calculated automatically to the best fit. enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda }; -typedef uint64_t IterationCount; +typedef int64_t IterationCount; enum StatisticUnit { kTime, kPercentage }; @@ -568,7 +653,7 @@ enum AggregationReportMode // State is passed to a running Benchmark and contains state for the // benchmark to use. -class State { +class BENCHMARK_EXPORT State { public: struct StateIterator; friend struct StateIterator; @@ -899,7 +984,7 @@ typedef void(Function)(State&); // 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 { +class BENCHMARK_EXPORT Benchmark { public: virtual ~Benchmark(); @@ -1000,6 +1085,12 @@ class Benchmark { // REQUIRES: `t > 0` and `Iterations` has not been called on this benchmark. Benchmark* MinTime(double t); + // Set the minimum amount of time to run the benchmark before taking runtimes + // of this benchmark into account. This + // option overrides the `benchmark_min_warmup_time` flag. + // REQUIRES: `t >= 0` and `Iterations` has not been called on this benchmark. + Benchmark* MinWarmUpTime(double t); + // Specify the amount of iterations that should be run by this benchmark. // REQUIRES: 'n > 0' and `MinTime` has not been called on this benchmark. // @@ -1090,9 +1181,10 @@ class Benchmark { virtual void Run(State& state) = 0; + TimeUnit GetTimeUnit() const; + protected: explicit Benchmark(const char* name); - Benchmark(Benchmark const&); void SetName(const char* name); int ArgsCnt() const; @@ -1105,9 +1197,13 @@ class Benchmark { AggregationReportMode aggregation_report_mode_; std::vector<std::string> arg_names_; // Args for all benchmark runs std::vector<std::vector<int64_t> > args_; // Args for all benchmark runs + TimeUnit time_unit_; + bool use_default_time_unit_; + int range_multiplier_; double min_time_; + double min_warmup_time_; IterationCount iterations_; int repetitions_; bool measure_process_cpu_time_; @@ -1122,7 +1218,17 @@ class Benchmark { callback_function setup_; callback_function teardown_; - Benchmark& operator=(Benchmark const&); + Benchmark(Benchmark const&) +#if defined(BENCHMARK_HAS_CXX11) + = delete +#endif + ; + + Benchmark& operator=(Benchmark const&) +#if defined(BENCHMARK_HAS_CXX11) + = delete +#endif + ; }; } // namespace internal @@ -1141,12 +1247,12 @@ internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn); // Remove all registered benchmarks. All pointers to previously registered // benchmarks are invalidated. -void ClearRegisteredBenchmarks(); +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 FunctionBenchmark : public Benchmark { +class BENCHMARK_EXPORT FunctionBenchmark : public Benchmark { public: FunctionBenchmark(const char* name, Function* func) : Benchmark(name), func_(func) {} @@ -1176,7 +1282,6 @@ class LambdaBenchmark : public Benchmark { Lambda lambda_; }; #endif - } // namespace internal inline internal::Benchmark* RegisterBenchmark(const char* name, @@ -1228,7 +1333,6 @@ class Fixture : public internal::Benchmark { protected: virtual void BenchmarkCase(State&) = 0; }; - } // namespace benchmark // ------------------------------------------------------ @@ -1454,7 +1558,7 @@ class Fixture : public internal::Benchmark { namespace benchmark { -struct CPUInfo { +struct BENCHMARK_EXPORT CPUInfo { struct CacheInfo { std::string type; int level; @@ -1478,7 +1582,7 @@ struct CPUInfo { }; // Adding Struct for System Information -struct SystemInfo { +struct BENCHMARK_EXPORT SystemInfo { std::string name; static const SystemInfo& Get(); @@ -1490,10 +1594,11 @@ struct SystemInfo { // BenchmarkName contains the components of the Benchmark's name // which allows individual fields to be modified or cleared before // building the final name using 'str()'. -struct BenchmarkName { +struct BENCHMARK_EXPORT BenchmarkName { std::string function_name; std::string args; std::string min_time; + std::string min_warmup_time; std::string iterations; std::string repetitions; std::string time_type; @@ -1509,7 +1614,7 @@ struct BenchmarkName { // can control the destination of the reports by calling // RunSpecifiedBenchmarks and passing it a custom reporter object. // The reporter object must implement the following interface. -class BenchmarkReporter { +class BENCHMARK_EXPORT BenchmarkReporter { public: struct Context { CPUInfo const& cpu_info; @@ -1520,7 +1625,7 @@ class BenchmarkReporter { Context(); }; - struct Run { + struct BENCHMARK_EXPORT Run { static const int64_t no_repetition_index = -1; enum RunType { RT_Iteration, RT_Aggregate }; @@ -1530,7 +1635,7 @@ class BenchmarkReporter { error_occurred(false), iterations(1), threads(1), - time_unit(kNanosecond), + time_unit(GetDefaultTimeUnit()), real_accumulated_time(0), cpu_accumulated_time(0), max_heapbytes_used(0), @@ -1669,7 +1774,7 @@ class BenchmarkReporter { // Simple reporter that outputs benchmark data to the console. This is the // default reporter used by RunSpecifiedBenchmarks(). -class ConsoleReporter : public BenchmarkReporter { +class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter { public: enum OutputOptions { OO_None = 0, @@ -1694,7 +1799,7 @@ class ConsoleReporter : public BenchmarkReporter { bool printed_header_; }; -class JSONReporter : public BenchmarkReporter { +class BENCHMARK_EXPORT JSONReporter : public BenchmarkReporter { public: JSONReporter() : first_report_(true) {} virtual bool ReportContext(const Context& context) BENCHMARK_OVERRIDE; @@ -1707,7 +1812,7 @@ class JSONReporter : public BenchmarkReporter { bool first_report_; }; -class BENCHMARK_DEPRECATED_MSG( +class BENCHMARK_EXPORT BENCHMARK_DEPRECATED_MSG( "The CSV Reporter will be removed in a future release") CSVReporter : public BenchmarkReporter { public: @@ -1759,11 +1864,17 @@ inline double GetTimeUnitMultiplier(TimeUnit unit) { // CreateRange(0, 100, /*multi=*/4), // CreateDenseRange(0, 4, /*step=*/1), // }); +BENCHMARK_EXPORT std::vector<int64_t> CreateRange(int64_t lo, int64_t hi, int multi); // Creates a list of integer values for the given range and step. +BENCHMARK_EXPORT std::vector<int64_t> CreateDenseRange(int64_t start, int64_t limit, int step); } // namespace benchmark +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + #endif // BENCHMARK_BENCHMARK_H_ diff --git a/contrib/libs/benchmark/include/benchmark/export.h b/contrib/libs/benchmark/include/benchmark/export.h new file mode 100644 index 00000000000..fe5a452eded --- /dev/null +++ b/contrib/libs/benchmark/include/benchmark/export.h @@ -0,0 +1,42 @@ + +#ifndef BENCHMARK_EXPORT_H +#define BENCHMARK_EXPORT_H + +#ifdef BENCHMARK_STATIC_DEFINE +# define BENCHMARK_EXPORT +# define BENCHMARK_NO_EXPORT +#else +# ifndef BENCHMARK_EXPORT +# ifdef benchmark_EXPORTS + /* We are building this library */ +# define BENCHMARK_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define BENCHMARK_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef BENCHMARK_NO_EXPORT +# define BENCHMARK_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef BENCHMARK_DEPRECATED +# define BENCHMARK_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef BENCHMARK_DEPRECATED_EXPORT +# define BENCHMARK_DEPRECATED_EXPORT BENCHMARK_EXPORT BENCHMARK_DEPRECATED +#endif + +#ifndef BENCHMARK_DEPRECATED_NO_EXPORT +# define BENCHMARK_DEPRECATED_NO_EXPORT BENCHMARK_NO_EXPORT BENCHMARK_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef BENCHMARK_NO_DEPRECATED +# define BENCHMARK_NO_DEPRECATED +# endif +#endif + +#endif /* BENCHMARK_EXPORT_H */ diff --git a/contrib/libs/benchmark/src/benchmark.cc b/contrib/libs/benchmark/src/benchmark.cc index cedeee31c79..6035491413b 100644 --- a/contrib/libs/benchmark/src/benchmark.cc +++ b/contrib/libs/benchmark/src/benchmark.cc @@ -72,6 +72,13 @@ BM_DEFINE_string(benchmark_filter, ""); // benchmark execution, regardless of number of threads. BM_DEFINE_double(benchmark_min_time, 0.5); +// Minimum number of seconds a benchmark should be run before results should be +// taken into account. This e.g can be neccessary for benchmarks of code which +// needs to fill some form of cache before performance is of interrest. +// Note: results gathered within this period are discarded and not used for +// reported result. +BM_DEFINE_double(benchmark_min_warmup_time, 0.0); + // The number of runs of each benchmark. If greater than 1, the mean and // standard deviation of the runs will be reported. BM_DEFINE_int32(benchmark_repetitions, 1); @@ -121,12 +128,16 @@ BM_DEFINE_string(benchmark_perf_counters, ""); // pairs. Kept internal as it's only used for parsing from env/command line. BM_DEFINE_kvpairs(benchmark_context, {}); +// Set the default time unit to use for reports +// Valid values are 'ns', 'us', 'ms' or 's' +BM_DEFINE_string(benchmark_time_unit, ""); + // The level of verbose logging to output BM_DEFINE_int32(v, 0); namespace internal { -std::map<std::string, std::string>* global_context = nullptr; +BENCHMARK_EXPORT std::map<std::string, std::string>* global_context = nullptr; // FIXME: wouldn't LTO mess this up? void UseCharPointer(char const volatile*) {} @@ -167,6 +178,10 @@ State::State(IterationCount max_iters, const std::vector<int64_t>& ranges, #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Winvalid-offsetof" #endif +#if defined(__CUDACC__) +#pragma nv_diagnostic push +#pragma nv_diag_suppress 1427 +#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_) <= @@ -177,6 +192,9 @@ State::State(IterationCount max_iters, const std::vector<int64_t>& ranges, #elif defined(__GNUC__) #pragma GCC diagnostic pop #endif +#if defined(__CUDACC__) +#pragma nv_diagnostic pop +#endif } void State::PauseTiming() { @@ -184,11 +202,14 @@ void State::PauseTiming() { BM_CHECK(started_ && !finished_ && !error_occurred_); timer_->StopTimer(); if (perf_counters_measurement_) { - auto measurements = perf_counters_measurement_->StopAndGetMeasurements(); + std::vector<std::pair<std::string, double>> measurements; + if (!perf_counters_measurement_->Stop(measurements)) { + BM_CHECK(false) << "Perf counters read the value failed."; + } for (const auto& name_and_measurement : measurements) { auto name = name_and_measurement.first; auto measurement = name_and_measurement.second; - BM_CHECK_EQ(counters[name], 0.0); + BM_CHECK_EQ(std::fpclassify((double)counters[name]), FP_ZERO); counters[name] = Counter(measurement, Counter::kAvgIterations); } } @@ -385,9 +406,9 @@ std::unique_ptr<BenchmarkReporter> CreateReporter( if (name == "console") { return PtrType(new ConsoleReporter(output_opts)); } else if (name == "json") { - return PtrType(new JSONReporter); + return PtrType(new JSONReporter()); } else if (name == "csv") { - return PtrType(new CSVReporter); + return PtrType(new CSVReporter()); } else { std::cerr << "Unexpected format: '" << name << "'\n"; std::exit(1); @@ -428,6 +449,14 @@ ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) { } // end namespace internal +BenchmarkReporter* CreateDefaultDisplayReporter() { + static auto default_display_reporter = + internal::CreateReporter(FLAGS_benchmark_format, + internal::GetOutputOptions()) + .release(); + return default_display_reporter; +} + size_t RunSpecifiedBenchmarks() { return RunSpecifiedBenchmarks(nullptr, nullptr, FLAGS_benchmark_filter); } @@ -463,8 +492,7 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, std::unique_ptr<BenchmarkReporter> default_display_reporter; std::unique_ptr<BenchmarkReporter> default_file_reporter; if (!display_reporter) { - default_display_reporter = internal::CreateReporter( - FLAGS_benchmark_format, internal::GetOutputOptions()); + default_display_reporter.reset(CreateDefaultDisplayReporter()); display_reporter = default_display_reporter.get(); } auto& Out = display_reporter->GetOutputStream(); @@ -510,8 +538,23 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, return benchmarks.size(); } +namespace { +// stores the time unit benchmarks use by default +TimeUnit default_time_unit = kNanosecond; +} // namespace + +TimeUnit GetDefaultTimeUnit() { return default_time_unit; } + +void SetDefaultTimeUnit(TimeUnit unit) { default_time_unit = unit; } + std::string GetBenchmarkFilter() { return FLAGS_benchmark_filter; } +void SetBenchmarkFilter(std::string value) { + FLAGS_benchmark_filter = std::move(value); +} + +int32_t GetBenchmarkVerbosity() { return FLAGS_v; } + void RegisterMemoryManager(MemoryManager* manager) { internal::memory_manager = manager; } @@ -528,27 +571,27 @@ void AddCustomContext(const std::string& key, const std::string& value) { namespace internal { +void (*HelperPrintf)(); + void PrintUsageAndExit() { - fprintf(stdout, - "benchmark" - " [--benchmark_list_tests={true|false}]\n" - " [--benchmark_filter=<regex>]\n" - " [--benchmark_min_time=<min_time>]\n" - " [--benchmark_repetitions=<num_repetitions>]\n" - " [--benchmark_enable_random_interleaving={true|false}]\n" - " [--benchmark_report_aggregates_only={true|false}]\n" - " [--benchmark_display_aggregates_only={true|false}]\n" - " [--benchmark_format=<console|json|csv>]\n" - " [--benchmark_out=<filename>]\n" - " [--benchmark_out_format=<json|console|csv>]\n" - " [--benchmark_color={auto|true|false}]\n" - " [--benchmark_counters_tabular={true|false}]\n" - " [--benchmark_perf_counters=<counter>,...]\n" - " [--benchmark_context=<key>=<value>,...]\n" - " [--v=<verbosity>]\n"); + HelperPrintf(); exit(0); } +void SetDefaultTimeUnitFromFlag(const std::string& time_unit_flag) { + if (time_unit_flag == "s") { + return SetDefaultTimeUnit(kSecond); + } else if (time_unit_flag == "ms") { + return SetDefaultTimeUnit(kMillisecond); + } else if (time_unit_flag == "us") { + return SetDefaultTimeUnit(kMicrosecond); + } else if (time_unit_flag == "ns") { + return SetDefaultTimeUnit(kNanosecond); + } else if (!time_unit_flag.empty()) { + PrintUsageAndExit(); + } +} + void ParseCommandLineFlags(int* argc, char** argv) { using namespace benchmark; BenchmarkReporter::Context::executable_name = @@ -559,6 +602,8 @@ void ParseCommandLineFlags(int* argc, char** argv) { ParseStringFlag(argv[i], "benchmark_filter", &FLAGS_benchmark_filter) || ParseDoubleFlag(argv[i], "benchmark_min_time", &FLAGS_benchmark_min_time) || + ParseDoubleFlag(argv[i], "benchmark_min_warmup_time", + &FLAGS_benchmark_min_warmup_time) || ParseInt32Flag(argv[i], "benchmark_repetitions", &FLAGS_benchmark_repetitions) || ParseBoolFlag(argv[i], "benchmark_enable_random_interleaving", @@ -578,6 +623,8 @@ void ParseCommandLineFlags(int* argc, char** argv) { &FLAGS_benchmark_perf_counters) || ParseKeyValueFlag(argv[i], "benchmark_context", &FLAGS_benchmark_context) || + ParseStringFlag(argv[i], "benchmark_time_unit", + &FLAGS_benchmark_time_unit) || ParseInt32Flag(argv[i], "v", &FLAGS_v)) { for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1]; @@ -593,6 +640,7 @@ void ParseCommandLineFlags(int* argc, char** argv) { PrintUsageAndExit(); } } + SetDefaultTimeUnitFromFlag(FLAGS_benchmark_time_unit); if (FLAGS_benchmark_color.empty()) { PrintUsageAndExit(); } @@ -608,9 +656,31 @@ int InitializeStreams() { } // end namespace internal -void Initialize(int* argc, char** argv) { +void PrintDefaultHelp() { + fprintf(stdout, + "benchmark" + " [--benchmark_list_tests={true|false}]\n" + " [--benchmark_filter=<regex>]\n" + " [--benchmark_min_time=<min_time>]\n" + " [--benchmark_min_warmup_time=<min_warmup_time>]\n" + " [--benchmark_repetitions=<num_repetitions>]\n" + " [--benchmark_enable_random_interleaving={true|false}]\n" + " [--benchmark_report_aggregates_only={true|false}]\n" + " [--benchmark_display_aggregates_only={true|false}]\n" + " [--benchmark_format=<console|json|csv>]\n" + " [--benchmark_out=<filename>]\n" + " [--benchmark_out_format=<json|console|csv>]\n" + " [--benchmark_color={auto|true|false}]\n" + " [--benchmark_counters_tabular={true|false}]\n" + " [--benchmark_context=<key>=<value>,...]\n" + " [--benchmark_time_unit={ns|us|ms|s}]\n" + " [--v=<verbosity>]\n"); +} + +void Initialize(int* argc, char** argv, void (*HelperPrintf)()) { internal::ParseCommandLineFlags(argc, argv); internal::LogLevel() = FLAGS_v; + internal::HelperPrintf = HelperPrintf; } void Shutdown() { delete internal::global_context; } diff --git a/contrib/libs/benchmark/src/benchmark_api_internal.cc b/contrib/libs/benchmark/src/benchmark_api_internal.cc index 4de36e3c8ba..963fea22f31 100644 --- a/contrib/libs/benchmark/src/benchmark_api_internal.cc +++ b/contrib/libs/benchmark/src/benchmark_api_internal.cc @@ -16,7 +16,7 @@ BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx, per_family_instance_index_(per_family_instance_idx), aggregation_report_mode_(benchmark_.aggregation_report_mode_), args_(args), - time_unit_(benchmark_.time_unit_), + time_unit_(benchmark_.GetTimeUnit()), measure_process_cpu_time_(benchmark_.measure_process_cpu_time_), use_real_time_(benchmark_.use_real_time_), use_manual_time_(benchmark_.use_manual_time_), @@ -25,6 +25,7 @@ BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx, statistics_(benchmark_.statistics_), repetitions_(benchmark_.repetitions_), min_time_(benchmark_.min_time_), + min_warmup_time_(benchmark_.min_warmup_time_), iterations_(benchmark_.iterations_), threads_(thread_count) { name_.function_name = benchmark_.name_; @@ -50,6 +51,11 @@ BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx, name_.min_time = StrFormat("min_time:%0.3f", benchmark_.min_time_); } + if (!IsZero(benchmark->min_warmup_time_)) { + name_.min_warmup_time = + StrFormat("min_warmup_time:%0.3f", benchmark_.min_warmup_time_); + } + if (benchmark_.iterations_ != 0) { name_.iterations = StrFormat( "iterations:%lu", static_cast<unsigned long>(benchmark_.iterations_)); diff --git a/contrib/libs/benchmark/src/benchmark_api_internal.h b/contrib/libs/benchmark/src/benchmark_api_internal.h index 94c2b2972bb..94f516531bc 100644 --- a/contrib/libs/benchmark/src/benchmark_api_internal.h +++ b/contrib/libs/benchmark/src/benchmark_api_internal.h @@ -36,6 +36,7 @@ class BenchmarkInstance { const std::vector<Statistics>& statistics() const { return statistics_; } int repetitions() const { return repetitions_; } double min_time() const { return min_time_; } + double min_warmup_time() const { return min_warmup_time_; } IterationCount iterations() const { return iterations_; } int threads() const { return threads_; } void Setup() const; @@ -62,6 +63,7 @@ class BenchmarkInstance { const std::vector<Statistics>& statistics_; int repetitions_; double min_time_; + double min_warmup_time_; IterationCount iterations_; int threads_; // Number of concurrent threads to us @@ -76,6 +78,7 @@ bool FindBenchmarksInternal(const std::string& re, bool IsZero(double n); +BENCHMARK_EXPORT ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color = false); } // end namespace internal diff --git a/contrib/libs/benchmark/src/benchmark_name.cc b/contrib/libs/benchmark/src/benchmark_name.cc index 2a17ebce277..4f7386068da 100644 --- a/contrib/libs/benchmark/src/benchmark_name.cc +++ b/contrib/libs/benchmark/src/benchmark_name.cc @@ -52,7 +52,7 @@ std::string join(char delimiter, const Ts&... ts) { } // namespace std::string BenchmarkName::str() const { - return join('/', function_name, args, min_time, iterations, repetitions, - time_type, threads); + return join('/', function_name, args, min_time, min_warmup_time, iterations, + repetitions, time_type, threads); } } // namespace benchmark diff --git a/contrib/libs/benchmark/src/benchmark_register.cc b/contrib/libs/benchmark/src/benchmark_register.cc index 61a0c26178e..a42b76689b2 100644 --- a/contrib/libs/benchmark/src/benchmark_register.cc +++ b/contrib/libs/benchmark/src/benchmark_register.cc @@ -53,10 +53,13 @@ namespace benchmark { namespace { // For non-dense Range, intermediate values are powers of kRangeMultiplier. -static const int kRangeMultiplier = 8; +static constexpr int kRangeMultiplier = 8; + // The size of a benchmark family determines is the number of inputs to repeat // the benchmark on. If this is "large" then warn the user during configuration. -static const size_t kMaxFamilySize = 100; +static constexpr size_t kMaxFamilySize = 100; + +static constexpr char kDisabledPrefix[] = "DISABLED_"; } // end namespace namespace internal { @@ -116,10 +119,10 @@ bool BenchmarkFamilies::FindBenchmarks( // Make regular expression out of command-line flag std::string error_msg; Regex re; - bool isNegativeFilter = false; + bool is_negative_filter = false; if (spec[0] == '-') { spec.replace(0, 1, ""); - isNegativeFilter = true; + is_negative_filter = true; } if (!re.Init(spec, &error_msg)) { Err << "Could not compile benchmark re: " << error_msg << std::endl; @@ -154,7 +157,8 @@ bool BenchmarkFamilies::FindBenchmarks( << " will be repeated at least " << family_size << " times.\n"; } // reserve in the special case the regex ".", since we know the final - // family size. + // family size. this doesn't take into account any disabled benchmarks + // so worst case we reserve more than we need. if (spec == ".") benchmarks->reserve(benchmarks->size() + family_size); for (auto const& args : family->args_) { @@ -164,8 +168,9 @@ bool BenchmarkFamilies::FindBenchmarks( num_threads); const auto full_name = instance.name().str(); - if ((re.Match(full_name) && !isNegativeFilter) || - (!re.Match(full_name) && isNegativeFilter)) { + if (full_name.rfind(kDisabledPrefix, 0) != 0 && + ((re.Match(full_name) && !is_negative_filter) || + (!re.Match(full_name) && is_negative_filter))) { benchmarks->push_back(std::move(instance)); ++per_family_instance_index; @@ -202,9 +207,11 @@ bool FindBenchmarksInternal(const std::string& re, Benchmark::Benchmark(const char* name) : name_(name), aggregation_report_mode_(ARM_Unspecified), - time_unit_(kNanosecond), + time_unit_(GetDefaultTimeUnit()), + use_default_time_unit_(true), range_multiplier_(kRangeMultiplier), min_time_(0), + min_warmup_time_(0), iterations_(0), repetitions_(0), measure_process_cpu_time_(false), @@ -235,6 +242,7 @@ Benchmark* Benchmark::Arg(int64_t x) { Benchmark* Benchmark::Unit(TimeUnit unit) { time_unit_ = unit; + use_default_time_unit_ = false; return this; } @@ -348,9 +356,17 @@ Benchmark* Benchmark::MinTime(double t) { return this; } +Benchmark* Benchmark::MinWarmUpTime(double t) { + BM_CHECK(t >= 0.0); + BM_CHECK(iterations_ == 0); + min_warmup_time_ = t; + return this; +} + Benchmark* Benchmark::Iterations(IterationCount n) { BM_CHECK(n > 0); BM_CHECK(IsZero(min_time_)); + BM_CHECK(IsZero(min_warmup_time_)); iterations_ = n; return this; } @@ -462,6 +478,10 @@ int Benchmark::ArgsCnt() const { return static_cast<int>(args_.front().size()); } +TimeUnit Benchmark::GetTimeUnit() const { + return use_default_time_unit_ ? GetDefaultTimeUnit() : time_unit_; +} + //=============================================================================// // FunctionBenchmark //=============================================================================// diff --git a/contrib/libs/benchmark/src/benchmark_register.h b/contrib/libs/benchmark/src/benchmark_register.h index d3f4974e907..a5a250cc700 100644 --- a/contrib/libs/benchmark/src/benchmark_register.h +++ b/contrib/libs/benchmark/src/benchmark_register.h @@ -23,7 +23,7 @@ typename std::vector<T>::iterator AddPowers(std::vector<T>* dst, T lo, T hi, static const T kmax = std::numeric_limits<T>::max(); // Space out the values in multiples of "mult" - for (T i = static_cast<T>(1); i <= hi; i *= mult) { + for (T i = static_cast<T>(1); i <= hi; i *= static_cast<T>(mult)) { if (i >= lo) { dst->push_back(i); } @@ -32,7 +32,7 @@ typename std::vector<T>::iterator AddPowers(std::vector<T>* dst, T lo, T hi, if (i > kmax / mult) break; } - return dst->begin() + start_offset; + return dst->begin() + static_cast<int>(start_offset); } template <typename T> diff --git a/contrib/libs/benchmark/src/benchmark_runner.cc b/contrib/libs/benchmark/src/benchmark_runner.cc index 617973a78d3..d30d0449daf 100644 --- a/contrib/libs/benchmark/src/benchmark_runner.cc +++ b/contrib/libs/benchmark/src/benchmark_runner.cc @@ -123,6 +123,7 @@ void RunInThread(const BenchmarkInstance* b, IterationCount iters, b->measure_process_cpu_time() ? internal::ThreadTimer::CreateProcessCpuTime() : internal::ThreadTimer::Create()); + State st = b->Run(iters, thread_id, &timer, manager, perf_counters_measurement); BM_CHECK(st.error_occurred() || st.iterations() >= st.max_iterations) @@ -148,13 +149,16 @@ BenchmarkRunner::BenchmarkRunner( : b(b_), reports_for_family(reports_for_family_), min_time(!IsZero(b.min_time()) ? b.min_time() : FLAGS_benchmark_min_time), + min_warmup_time((!IsZero(b.min_time()) && b.min_warmup_time() > 0.0) + ? b.min_warmup_time() + : FLAGS_benchmark_min_warmup_time), + warmup_done(!(min_warmup_time > 0.0)), repeats(b.repetitions() != 0 ? b.repetitions() : FLAGS_benchmark_repetitions), has_explicit_iteration_count(b.iterations() != 0), pool(b.threads() - 1), iters(has_explicit_iteration_count ? b.iterations() : 1), - perf_counters_measurement( - PerfCounters::Create(StrSplit(FLAGS_benchmark_perf_counters, ','))), + perf_counters_measurement(StrSplit(FLAGS_benchmark_perf_counters, ',')), perf_counters_measurement_ptr(perf_counters_measurement.IsValid() ? &perf_counters_measurement : nullptr) { @@ -234,20 +238,20 @@ IterationCount BenchmarkRunner::PredictNumItersNeeded( const IterationResults& i) const { // See how much iterations should be increased by. // Note: Avoid division by zero with max(seconds, 1ns). - double multiplier = min_time * 1.4 / std::max(i.seconds, 1e-9); + double multiplier = GetMinTimeToApply() * 1.4 / std::max(i.seconds, 1e-9); // If our last run was at least 10% of FLAGS_benchmark_min_time then we // use the multiplier directly. // Otherwise we use at most 10 times expansion. // NOTE: When the last run was at least 10% of the min time the max // expansion should be 14x. - bool is_significant = (i.seconds / min_time) > 0.1; + const bool is_significant = (i.seconds / GetMinTimeToApply()) > 0.1; multiplier = is_significant ? multiplier : 10.0; // So what seems to be the sufficiently-large iteration count? Round up. const IterationCount max_next_iters = static_cast<IterationCount>( std::lround(std::max(multiplier * static_cast<double>(i.iters), static_cast<double>(i.iters) + 1.0))); - // But we do have *some* sanity limits though.. + // But we do have *some* limits though.. const IterationCount next_iters = std::min(max_next_iters, kMaxIterations); BM_VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n"; @@ -261,19 +265,78 @@ bool BenchmarkRunner::ShouldReportIterationResults( // or because an error was reported. return i.results.has_error_ || i.iters >= kMaxIterations || // Too many iterations already. - i.seconds >= min_time || // The elapsed time is large enough. + i.seconds >= + GetMinTimeToApply() || // 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. - ((i.results.real_time_used >= 5 * min_time) && !b.use_manual_time()); + // Note that user provided timers are except from this test. + ((i.results.real_time_used >= 5 * GetMinTimeToApply()) && + !b.use_manual_time()); +} + +double BenchmarkRunner::GetMinTimeToApply() const { + // In order to re-use 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 + // in the benchmarking phase and min_time needs to be applied. + return warmup_done ? min_time : min_warmup_time; +} + +void BenchmarkRunner::FinishWarmUp(const IterationCount& i) { + warmup_done = true; + iters = i; +} + +void BenchmarkRunner::RunWarmUp() { + // Use the same mechanisms for warming up the benchmark as used for actually + // running and measuring the benchmark. + IterationResults i_warmup; + // Dont use the iterations determined in the warmup phase for the actual + // measured benchmark phase. While this may be a good starting point for the + // benchmark and it would therefore get rid of the need to figure out how many + // iterations are needed if min_time is set again, this may also be a complete + // wrong guess since the warmup loops might be considerably slower (e.g + // because of caching effects). + const IterationCount i_backup = iters; + + for (;;) { + b.Setup(); + i_warmup = DoNIterations(); + b.Teardown(); + + const bool finish = ShouldReportIterationResults(i_warmup); + + if (finish) { + FinishWarmUp(i_backup); + break; + } + + // Although we are running "only" a warmup phase where running enough + // iterations at once without measuring time isn't as important as it is for + // the benchmarking phase, we still do it the same way as otherwise it is + // very confusing for the user to know how to choose a proper value for + // min_warmup_time if a different approach on running it is used. + iters = PredictNumItersNeeded(i_warmup); + assert(iters > i_warmup.iters && + "if we did more iterations than we want to do the next time, " + "then we should have accepted the current iteration run."); + } } void BenchmarkRunner::DoOneRepetition() { assert(HasRepeatsRemaining() && "Already done all repetitions?"); const bool is_the_first_repetition = num_repetitions_done == 0; - IterationResults i; + // In case a warmup phase is requested by the benchmark, run it now. + // After running the warmup phase the BenchmarkRunner should be in a state as + // this warmup never happened except the fact that warmup_done is set. Every + // other manipulation of the BenchmarkRunner instance would be a bug! Please + // fix it. + if (!warmup_done) RunWarmUp(); + + IterationResults i; // We *may* be gradually increasing the length (iteration count) // of the benchmark until we decide the results are significant. // And once we do, we report those last results and exit. diff --git a/contrib/libs/benchmark/src/benchmark_runner.h b/contrib/libs/benchmark/src/benchmark_runner.h index 752eefdc26f..0174bd34018 100644 --- a/contrib/libs/benchmark/src/benchmark_runner.h +++ b/contrib/libs/benchmark/src/benchmark_runner.h @@ -26,6 +26,7 @@ namespace benchmark { BM_DECLARE_double(benchmark_min_time); +BM_DECLARE_double(benchmark_min_warmup_time); BM_DECLARE_int32(benchmark_repetitions); BM_DECLARE_bool(benchmark_report_aggregates_only); BM_DECLARE_bool(benchmark_display_aggregates_only); @@ -69,6 +70,8 @@ class BenchmarkRunner { BenchmarkReporter::PerFamilyRunReports* reports_for_family; const double min_time; + const double min_warmup_time; + bool warmup_done; const int repeats; const bool has_explicit_iteration_count; @@ -95,6 +98,12 @@ class BenchmarkRunner { IterationCount PredictNumItersNeeded(const IterationResults& i) const; bool ShouldReportIterationResults(const IterationResults& i) const; + + double GetMinTimeToApply() const; + + void FinishWarmUp(const IterationCount& i); + + void RunWarmUp(); }; } // namespace internal diff --git a/contrib/libs/benchmark/src/check.cc b/contrib/libs/benchmark/src/check.cc new file mode 100644 index 00000000000..422b9483a8f --- /dev/null +++ b/contrib/libs/benchmark/src/check.cc @@ -0,0 +1,11 @@ +#include "check.h" + +namespace benchmark { +namespace internal { + +static AbortHandlerT* handler = &std::abort; + +AbortHandlerT*& GetAbortHandler() { return handler; } + +} // namespace internal +} // namespace benchmark diff --git a/contrib/libs/benchmark/src/check.h b/contrib/libs/benchmark/src/check.h index 90c7bbfa4b4..1129e814025 100644 --- a/contrib/libs/benchmark/src/check.h +++ b/contrib/libs/benchmark/src/check.h @@ -5,6 +5,7 @@ #include <cstdlib> #include <ostream> +#include "benchmark/export.h" #include "internal_macros.h" #include "log.h" @@ -13,10 +14,8 @@ namespace internal { typedef void(AbortHandlerT)(); -inline AbortHandlerT*& GetAbortHandler() { - static AbortHandlerT* handler = &std::abort; - return handler; -} +BENCHMARK_EXPORT +AbortHandlerT*& GetAbortHandler(); BENCHMARK_NORETURN inline void CallAbortHandler() { GetAbortHandler()(); diff --git a/contrib/libs/benchmark/src/commandlineflags.h b/contrib/libs/benchmark/src/commandlineflags.h index 5baaf11784d..7882628975e 100644 --- a/contrib/libs/benchmark/src/commandlineflags.h +++ b/contrib/libs/benchmark/src/commandlineflags.h @@ -5,28 +5,33 @@ #include <map> #include <string> +#include "benchmark/export.h" + // Macro for referencing flags. #define FLAG(name) FLAGS_##name // Macros for declaring flags. -#define BM_DECLARE_bool(name) extern bool FLAG(name) -#define BM_DECLARE_int32(name) extern int32_t FLAG(name) -#define BM_DECLARE_double(name) extern double FLAG(name) -#define BM_DECLARE_string(name) extern std::string FLAG(name) +#define BM_DECLARE_bool(name) BENCHMARK_EXPORT extern bool FLAG(name) +#define BM_DECLARE_int32(name) BENCHMARK_EXPORT extern int32_t FLAG(name) +#define BM_DECLARE_double(name) BENCHMARK_EXPORT extern double FLAG(name) +#define BM_DECLARE_string(name) BENCHMARK_EXPORT extern std::string FLAG(name) #define BM_DECLARE_kvpairs(name) \ - extern std::map<std::string, std::string> FLAG(name) + BENCHMARK_EXPORT extern std::map<std::string, std::string> FLAG(name) // Macros for defining flags. #define BM_DEFINE_bool(name, default_val) \ - bool FLAG(name) = benchmark::BoolFromEnv(#name, default_val) + BENCHMARK_EXPORT bool FLAG(name) = benchmark::BoolFromEnv(#name, default_val) #define BM_DEFINE_int32(name, default_val) \ - int32_t FLAG(name) = benchmark::Int32FromEnv(#name, default_val) + BENCHMARK_EXPORT int32_t FLAG(name) = \ + benchmark::Int32FromEnv(#name, default_val) #define BM_DEFINE_double(name, default_val) \ - double FLAG(name) = benchmark::DoubleFromEnv(#name, default_val) + BENCHMARK_EXPORT double FLAG(name) = \ + benchmark::DoubleFromEnv(#name, default_val) #define BM_DEFINE_string(name, default_val) \ - std::string FLAG(name) = benchmark::StringFromEnv(#name, default_val) -#define BM_DEFINE_kvpairs(name, default_val) \ - std::map<std::string, std::string> FLAG(name) = \ + BENCHMARK_EXPORT std::string FLAG(name) = \ + benchmark::StringFromEnv(#name, default_val) +#define BM_DEFINE_kvpairs(name, default_val) \ + BENCHMARK_EXPORT std::map<std::string, std::string> FLAG(name) = \ benchmark::KvPairsFromEnv(#name, default_val) namespace benchmark { @@ -35,6 +40,7 @@ namespace benchmark { // // If the variable exists, returns IsTruthyFlagValue() value; if not, // returns the given default value. +BENCHMARK_EXPORT bool BoolFromEnv(const char* flag, bool default_val); // Parses an Int32 from the environment variable corresponding to the given @@ -42,6 +48,7 @@ bool BoolFromEnv(const char* flag, bool default_val); // // If the variable exists, returns ParseInt32() value; if not, returns // the given default value. +BENCHMARK_EXPORT int32_t Int32FromEnv(const char* flag, int32_t default_val); // Parses an Double from the environment variable corresponding to the given @@ -49,6 +56,7 @@ int32_t Int32FromEnv(const char* flag, int32_t default_val); // // If the variable exists, returns ParseDouble(); if not, returns // the given default value. +BENCHMARK_EXPORT double DoubleFromEnv(const char* flag, double default_val); // Parses a string from the environment variable corresponding to the given @@ -56,6 +64,7 @@ double DoubleFromEnv(const char* flag, double default_val); // // If variable exists, returns its value; if not, returns // the given default value. +BENCHMARK_EXPORT const char* StringFromEnv(const char* flag, const char* default_val); // Parses a set of kvpairs from the environment variable corresponding to the @@ -63,6 +72,7 @@ const char* StringFromEnv(const char* flag, const char* default_val); // // If variable exists, returns its value; if not, returns // the given default value. +BENCHMARK_EXPORT std::map<std::string, std::string> KvPairsFromEnv( const char* flag, std::map<std::string, std::string> default_val); @@ -75,40 +85,47 @@ std::map<std::string, std::string> KvPairsFromEnv( // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. +BENCHMARK_EXPORT bool ParseBoolFlag(const char* str, const char* flag, bool* value); // Parses a string for an Int32 flag, in the form of "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. +BENCHMARK_EXPORT bool ParseInt32Flag(const char* str, const char* flag, int32_t* value); // Parses a string for a Double flag, in the form of "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. +BENCHMARK_EXPORT bool ParseDoubleFlag(const char* str, const char* flag, double* value); // Parses a string for a string flag, in the form of "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. +BENCHMARK_EXPORT bool ParseStringFlag(const char* str, const char* flag, std::string* value); // Parses a string for a kvpairs flag in the form "--flag=key=value,key=value" // // On success, stores the value of the flag in *value and returns true. On // failure returns false, though *value may have been mutated. +BENCHMARK_EXPORT bool ParseKeyValueFlag(const char* str, const char* flag, std::map<std::string, std::string>* value); // Returns true if the string matches the flag. +BENCHMARK_EXPORT bool IsFlag(const char* str, const char* flag); // Returns true unless value starts with one of: '0', 'f', 'F', 'n' or 'N', or // some non-alphanumeric character. Also returns false if the value matches // one of 'no', 'false', 'off' (case-insensitive). As a special case, also // returns true if value is the empty string. +BENCHMARK_EXPORT bool IsTruthyFlagValue(const std::string& value); } // end namespace benchmark diff --git a/contrib/libs/benchmark/src/console_reporter.cc b/contrib/libs/benchmark/src/console_reporter.cc index 04cc0b74e58..1711356b9b4 100644 --- a/contrib/libs/benchmark/src/console_reporter.cc +++ b/contrib/libs/benchmark/src/console_reporter.cc @@ -99,6 +99,9 @@ static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt, } static std::string FormatTime(double time) { + // For the time columns of the console printer 13 digits are reserved. One of + // them is a space and max two of them are the time unit (e.g ns). That puts + // us at 10 digits usable for the number. // Align decimal places... if (time < 1.0) { return FormatString("%10.3f", time); @@ -109,6 +112,11 @@ static std::string FormatTime(double time) { if (time < 100.0) { return FormatString("%10.1f", time); } + // Assuming the time ist at max 9.9999e+99 and we have 10 digits for the + // number, we get 10-1(.)-1(e)-1(sign)-2(exponent) = 5 digits to print. + if (time > 9999999999 /*max 10 digit number*/) { + return FormatString("%1.4e", time); + } return FormatString("%10.0f", time); } diff --git a/contrib/libs/benchmark/src/cycleclock.h b/contrib/libs/benchmark/src/cycleclock.h index 07dfdd2ec49..de5e47c5487 100644 --- a/contrib/libs/benchmark/src/cycleclock.h +++ b/contrib/libs/benchmark/src/cycleclock.h @@ -132,7 +132,7 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { // Native Client does not provide any API to access cycle counter. // Use clock_gettime(CLOCK_MONOTONIC, ...) instead of gettimeofday - // because is provides nanosecond resolution (which is noticable at + // because is provides nanosecond resolution (which is noticeable at // least for PNaCl modules running on x86 Mac & Linux). // Initialize to always return 0 if clock_gettime fails. struct timespec ts = {0, 0}; @@ -173,7 +173,7 @@ 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(__loongarch__) +#elif defined(__loongarch__) || defined(__csky__) struct timeval tv; gettimeofday(&tv, nullptr); return static_cast<int64_t>(tv.tv_sec) * 1000000 + tv.tv_usec; diff --git a/contrib/libs/benchmark/src/internal_macros.h b/contrib/libs/benchmark/src/internal_macros.h index 91f367b894b..72ba54bad2c 100644 --- a/contrib/libs/benchmark/src/internal_macros.h +++ b/contrib/libs/benchmark/src/internal_macros.h @@ -44,6 +44,13 @@ #define BENCHMARK_OS_CYGWIN 1 #elif defined(_WIN32) #define BENCHMARK_OS_WINDOWS 1 + #if defined(WINAPI_FAMILY_PARTITION) + #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + #define BENCHMARK_OS_WINDOWS_WIN32 1 + #elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + #define BENCHMARK_OS_WINDOWS_RT 1 + #endif + #endif #if defined(__MINGW32__) #define BENCHMARK_OS_MINGW 1 #endif diff --git a/contrib/libs/benchmark/src/json_reporter.cc b/contrib/libs/benchmark/src/json_reporter.cc index e84a4ed24f9..e9999e18ac0 100644 --- a/contrib/libs/benchmark/src/json_reporter.cc +++ b/contrib/libs/benchmark/src/json_reporter.cc @@ -89,12 +89,6 @@ std::string FormatKV(std::string const& key, int64_t value) { return ss.str(); } -std::string FormatKV(std::string const& key, IterationCount value) { - std::stringstream ss; - ss << '"' << StrEscape(key) << "\": " << value; - return ss.str(); -} - std::string FormatKV(std::string const& key, double value) { std::stringstream ss; ss << '"' << StrEscape(key) << "\": "; diff --git a/contrib/libs/benchmark/src/perf_counters.cc b/contrib/libs/benchmark/src/perf_counters.cc index 5a362c1c45c..8a60088ba73 100644 --- a/contrib/libs/benchmark/src/perf_counters.cc +++ b/contrib/libs/benchmark/src/perf_counters.cc @@ -15,6 +15,7 @@ #include "perf_counters.h" #include <cstring> +#include <memory> #include <vector> #if defined HAVE_LIBPFM @@ -104,7 +105,7 @@ PerfCounters PerfCounters::Create( return PerfCounters(counter_names, std::move(counter_ids)); } -PerfCounters::~PerfCounters() { +void PerfCounters::CloseCounters() const { if (counter_ids_.empty()) { return; } @@ -126,7 +127,44 @@ PerfCounters PerfCounters::Create( return NoCounters(); } -PerfCounters::~PerfCounters() = default; +void PerfCounters::CloseCounters() const {} #endif // defined HAVE_LIBPFM + +Mutex PerfCountersMeasurement::mutex_; +int PerfCountersMeasurement::ref_count_ = 0; +PerfCounters PerfCountersMeasurement::counters_ = PerfCounters::NoCounters(); + +PerfCountersMeasurement::PerfCountersMeasurement( + const std::vector<std::string>& counter_names) + : start_values_(counter_names.size()), end_values_(counter_names.size()) { + MutexLock l(mutex_); + if (ref_count_ == 0) { + counters_ = PerfCounters::Create(counter_names); + } + // We chose to increment it even if `counters_` ends up invalid, + // so that we don't keep trying to create, and also since the dtor + // will decrement regardless of `counters_`'s validity + ++ref_count_; + + BM_CHECK(!counters_.IsValid() || counters_.names() == counter_names); +} + +PerfCountersMeasurement::~PerfCountersMeasurement() { + MutexLock l(mutex_); + --ref_count_; + if (ref_count_ == 0) { + counters_ = PerfCounters::NoCounters(); + } +} + +PerfCounters& PerfCounters::operator=(PerfCounters&& other) noexcept { + if (this != &other) { + CloseCounters(); + + counter_ids_ = std::move(other.counter_ids_); + counter_names_ = std::move(other.counter_names_); + } + return *this; +} } // namespace internal } // namespace benchmark diff --git a/contrib/libs/benchmark/src/perf_counters.h b/contrib/libs/benchmark/src/perf_counters.h index 47ca1385e24..680555d4b0f 100644 --- a/contrib/libs/benchmark/src/perf_counters.h +++ b/contrib/libs/benchmark/src/perf_counters.h @@ -17,16 +17,24 @@ #include <array> #include <cstdint> +#include <memory> #include <vector> #include "benchmark/benchmark.h" #include "check.h" #include "log.h" +#include "mutex.h" #ifndef BENCHMARK_OS_WINDOWS #include <unistd.h> #endif +#if defined(_MSC_VER) +#pragma warning(push) +// C4251: <symbol> needs to have dll-interface to be used by clients of class +#pragma warning(disable : 4251) +#endif + namespace benchmark { namespace internal { @@ -66,17 +74,19 @@ class PerfCounterValues { // Collect PMU counters. The object, once constructed, is ready to be used by // calling read(). PMU counter collection is enabled from the time create() is // called, to obtain the object, until the object's destructor is called. -class PerfCounters final { +class BENCHMARK_EXPORT PerfCounters final { public: // True iff this platform supports performance counters. static const bool kSupported; - bool IsValid() const { return is_valid_; } + bool IsValid() const { return !counter_names_.empty(); } static PerfCounters NoCounters() { return PerfCounters(); } - ~PerfCounters(); + ~PerfCounters() { CloseCounters(); } PerfCounters(PerfCounters&&) = default; PerfCounters(const PerfCounters&) = delete; + PerfCounters& operator=(PerfCounters&&) noexcept; + PerfCounters& operator=(const PerfCounters&) = delete; // Platform-specific implementations may choose to do some library // initialization here. @@ -111,55 +121,66 @@ class PerfCounters final { private: PerfCounters(const std::vector<std::string>& counter_names, std::vector<int>&& counter_ids) - : counter_ids_(std::move(counter_ids)), - counter_names_(counter_names), - is_valid_(true) {} - PerfCounters() : is_valid_(false) {} + : counter_ids_(std::move(counter_ids)), counter_names_(counter_names) {} + PerfCounters() = default; + + void CloseCounters() const; std::vector<int> counter_ids_; - const std::vector<std::string> counter_names_; - const bool is_valid_; + std::vector<std::string> counter_names_; }; // Typical usage of the above primitives. -class PerfCountersMeasurement final { +class BENCHMARK_EXPORT PerfCountersMeasurement final { public: - PerfCountersMeasurement(PerfCounters&& c) - : counters_(std::move(c)), - start_values_(counters_.IsValid() ? counters_.names().size() : 0), - end_values_(counters_.IsValid() ? counters_.names().size() : 0) {} - - bool IsValid() const { return counters_.IsValid(); } + PerfCountersMeasurement(const std::vector<std::string>& counter_names); + ~PerfCountersMeasurement(); + + // The only way to get to `counters_` is after ctor-ing a + // `PerfCountersMeasurement`, which means that `counters_`'s state is, here, + // decided (either invalid or valid) and won't change again even if a ctor is + // concurrently running with this. This is preferring efficiency to + // maintainability, because the address of the static can be known at compile + // time. + bool IsValid() const { + MutexLock l(mutex_); + return counters_.IsValid(); + } BENCHMARK_ALWAYS_INLINE void Start() { assert(IsValid()); + MutexLock l(mutex_); // Tell the compiler to not move instructions above/below where we take // the snapshot. ClobberMemory(); - counters_.Snapshot(&start_values_); + valid_read_ &= counters_.Snapshot(&start_values_); ClobberMemory(); } - BENCHMARK_ALWAYS_INLINE std::vector<std::pair<std::string, double>> - StopAndGetMeasurements() { + BENCHMARK_ALWAYS_INLINE bool Stop( + std::vector<std::pair<std::string, double>>& measurements) { assert(IsValid()); + MutexLock l(mutex_); // Tell the compiler to not move instructions above/below where we take // the snapshot. ClobberMemory(); - counters_.Snapshot(&end_values_); + valid_read_ &= counters_.Snapshot(&end_values_); ClobberMemory(); - std::vector<std::pair<std::string, double>> ret; for (size_t i = 0; i < counters_.names().size(); ++i) { double measurement = static_cast<double>(end_values_[i]) - static_cast<double>(start_values_[i]); - ret.push_back({counters_.names()[i], measurement}); + measurements.push_back({counters_.names()[i], measurement}); } - return ret; + + return valid_read_; } private: - PerfCounters counters_; + static Mutex mutex_; + GUARDED_BY(mutex_) static int ref_count_; + GUARDED_BY(mutex_) static PerfCounters counters_; + bool valid_read_ = true; PerfCounterValues start_values_; PerfCounterValues end_values_; }; @@ -169,4 +190,8 @@ BENCHMARK_UNUSED static bool perf_init_anchor = PerfCounters::Initialize(); } // namespace internal } // namespace benchmark +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + #endif // BENCHMARK_PERF_COUNTERS_H diff --git a/contrib/libs/benchmark/src/statistics.cc b/contrib/libs/benchmark/src/statistics.cc index 3e5ef099397..5ba885ab005 100644 --- a/contrib/libs/benchmark/src/statistics.cc +++ b/contrib/libs/benchmark/src/statistics.cc @@ -118,11 +118,13 @@ std::vector<BenchmarkReporter::Run> ComputeStats( for (auto const& cnt : r.counters) { auto it = counter_stats.find(cnt.first); if (it == counter_stats.end()) { - counter_stats.insert({cnt.first, {cnt.second, std::vector<double>{}}}); - it = counter_stats.find(cnt.first); + it = counter_stats + .emplace(cnt.first, + CounterStat{cnt.second, std::vector<double>{}}) + .first; it->second.s.reserve(reports.size()); } else { - BM_CHECK_EQ(counter_stats[cnt.first].c.flags, cnt.second.flags); + BM_CHECK_EQ(it->second.c.flags, cnt.second.flags); } } } diff --git a/contrib/libs/benchmark/src/statistics.h b/contrib/libs/benchmark/src/statistics.h index a9545a58c64..b0d2c05e729 100644 --- a/contrib/libs/benchmark/src/statistics.h +++ b/contrib/libs/benchmark/src/statistics.h @@ -25,12 +25,17 @@ namespace benchmark { // Return a vector containing the mean, median and standard devation information // (and any user-specified info) for the specified list of reports. If 'reports' // contains less than two non-errored runs an empty vector is returned +BENCHMARK_EXPORT std::vector<BenchmarkReporter::Run> ComputeStats( const std::vector<BenchmarkReporter::Run>& reports); +BENCHMARK_EXPORT double StatisticsMean(const std::vector<double>& v); +BENCHMARK_EXPORT double StatisticsMedian(const std::vector<double>& v); +BENCHMARK_EXPORT double StatisticsStdDev(const std::vector<double>& v); +BENCHMARK_EXPORT double StatisticsCV(const std::vector<double>& v); } // end namespace benchmark diff --git a/contrib/libs/benchmark/src/string_util.h b/contrib/libs/benchmark/src/string_util.h index ff3b7da47d6..41458618351 100644 --- a/contrib/libs/benchmark/src/string_util.h +++ b/contrib/libs/benchmark/src/string_util.h @@ -5,6 +5,7 @@ #include <string> #include <utility> +#include "benchmark/export.h" #include "internal_macros.h" namespace benchmark { @@ -13,6 +14,7 @@ void AppendHumanReadable(int n, std::string* str); std::string HumanReadableNumber(double n, double one_k = 1024.0); +BENCHMARK_EXPORT #if defined(__MINGW32__) __attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2))) #elif defined(__GNUC__) @@ -38,6 +40,7 @@ inline std::string StrCat(Args&&... args) { return ss.str(); } +BENCHMARK_EXPORT std::vector<std::string> StrSplit(const std::string& str, char delim); // Disable lint checking for this block since it re-implements C functions. diff --git a/contrib/libs/benchmark/src/sysinfo.cc b/contrib/libs/benchmark/src/sysinfo.cc index 1f359894073..999c4ac79ef 100644 --- a/contrib/libs/benchmark/src/sysinfo.cc +++ b/contrib/libs/benchmark/src/sysinfo.cc @@ -91,67 +91,59 @@ BENCHMARK_NORETURN void PrintErrorAndDie(Args&&... args) { /// `sysctl` with the result type it's to be interpreted as. struct ValueUnion { union DataT { - uint32_t uint32_value; - uint64_t uint64_value; + int32_t int32_value; + int64_t int64_value; // For correct aliasing of union members from bytes. char bytes[8]; }; using DataPtr = std::unique_ptr<DataT, decltype(&std::free)>; // The size of the data union member + its trailing array size. - size_t Size; - DataPtr Buff; + std::size_t size; + DataPtr buff; public: - ValueUnion() : Size(0), Buff(nullptr, &std::free) {} + ValueUnion() : size(0), buff(nullptr, &std::free) {} - explicit ValueUnion(size_t BuffSize) - : Size(sizeof(DataT) + BuffSize), - Buff(::new (std::malloc(Size)) DataT(), &std::free) {} + explicit ValueUnion(std::size_t buff_size) + : size(sizeof(DataT) + buff_size), + buff(::new (std::malloc(size)) DataT(), &std::free) {} ValueUnion(ValueUnion&& other) = default; - explicit operator bool() const { return bool(Buff); } + explicit operator bool() const { return bool(buff); } - char* data() const { return Buff->bytes; } + char* data() const { return buff->bytes; } std::string GetAsString() const { return std::string(data()); } int64_t GetAsInteger() const { - if (Size == sizeof(Buff->uint32_value)) - return static_cast<int32_t>(Buff->uint32_value); - else if (Size == sizeof(Buff->uint64_value)) - return static_cast<int64_t>(Buff->uint64_value); - BENCHMARK_UNREACHABLE(); - } - - uint64_t GetAsUnsigned() const { - if (Size == sizeof(Buff->uint32_value)) - return Buff->uint32_value; - else if (Size == sizeof(Buff->uint64_value)) - return Buff->uint64_value; + if (size == sizeof(buff->int32_value)) + return buff->int32_value; + else if (size == sizeof(buff->int64_value)) + return buff->int64_value; BENCHMARK_UNREACHABLE(); } template <class T, int N> std::array<T, N> GetAsArray() { - const int ArrSize = sizeof(T) * N; - BM_CHECK_LE(ArrSize, Size); - std::array<T, N> Arr; - std::memcpy(Arr.data(), data(), ArrSize); - return Arr; + const int arr_size = sizeof(T) * N; + BM_CHECK_LE(arr_size, size); + std::array<T, N> arr; + std::memcpy(arr.data(), data(), arr_size); + return arr; } }; -ValueUnion GetSysctlImp(std::string const& Name) { +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")) { + if ((name == "hw.ncpu") || (name == "hw.cpuspeed")) { ValueUnion buff(sizeof(int)); - if (Name == "hw.ncpu") { + if (name == "hw.ncpu") { mib[1] = HW_NCPU; } else { mib[1] = HW_CPUSPEED; @@ -164,41 +156,41 @@ ValueUnion GetSysctlImp(std::string const& Name) { } return ValueUnion(); #else - size_t CurBuffSize = 0; - if (sysctlbyname(Name.c_str(), nullptr, &CurBuffSize, nullptr, 0) == -1) + std::size_t cur_buff_size = 0; + if (sysctlbyname(name.c_str(), nullptr, &cur_buff_size, nullptr, 0) == -1) return ValueUnion(); - ValueUnion buff(CurBuffSize); - if (sysctlbyname(Name.c_str(), buff.data(), &buff.Size, nullptr, 0) == 0) + ValueUnion buff(cur_buff_size); + if (sysctlbyname(name.c_str(), buff.data(), &buff.size, nullptr, 0) == 0) return buff; return ValueUnion(); #endif } BENCHMARK_MAYBE_UNUSED -bool GetSysctl(std::string const& Name, std::string* Out) { - Out->clear(); - auto Buff = GetSysctlImp(Name); - if (!Buff) return false; - Out->assign(Buff.data()); +bool GetSysctl(std::string const& name, std::string* out) { + out->clear(); + auto buff = GetSysctlImp(name); + if (!buff) return false; + out->assign(buff.data()); return true; } template <class Tp, class = typename std::enable_if<std::is_integral<Tp>::value>::type> -bool GetSysctl(std::string const& Name, Tp* Out) { - *Out = 0; - auto Buff = GetSysctlImp(Name); - if (!Buff) return false; - *Out = static_cast<Tp>(Buff.GetAsUnsigned()); +bool GetSysctl(std::string const& name, Tp* out) { + *out = 0; + auto buff = GetSysctlImp(name); + if (!buff) return false; + *out = static_cast<Tp>(buff.GetAsInteger()); return true; } template <class Tp, size_t N> -bool GetSysctl(std::string const& Name, std::array<Tp, N>* Out) { - auto Buff = GetSysctlImp(Name); - if (!Buff) return false; - *Out = Buff.GetAsArray<Tp, N>(); +bool GetSysctl(std::string const& name, std::array<Tp, N>* out) { + auto buff = GetSysctlImp(name); + if (!buff) return false; + *out = buff.GetAsArray<Tp, N>(); return true; } #endif @@ -234,21 +226,21 @@ CPUInfo::Scaling CpuScaling(int num_cpus) { #endif } -int CountSetBitsInCPUMap(std::string Val) { - auto CountBits = [](std::string Part) { +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(benchmark::stoul(Part, nullptr, 16)); - return static_cast<int>(Mask.count()); + part = "0x" + part; + CPUMask mask(benchmark::stoul(part, nullptr, 16)); + return static_cast<int>(mask.count()); }; - size_t Pos; + std::size_t pos; int total = 0; - while ((Pos = Val.find(',')) != std::string::npos) { - total += CountBits(Val.substr(0, Pos)); - Val = Val.substr(Pos + 1); + while ((pos = val.find(',')) != std::string::npos) { + total += CountBits(val.substr(0, pos)); + val = val.substr(pos + 1); } - if (!Val.empty()) { - total += CountBits(Val); + if (!val.empty()) { + total += CountBits(val); } return total; } @@ -257,16 +249,16 @@ BENCHMARK_MAYBE_UNUSED std::vector<CPUInfo::CacheInfo> GetCacheSizesFromKVFS() { std::vector<CPUInfo::CacheInfo> res; std::string dir = "/sys/devices/system/cpu/cpu0/cache/"; - int Idx = 0; + int idx = 0; while (true) { CPUInfo::CacheInfo info; - std::string FPath = StrCat(dir, "index", Idx++, "/"); - std::ifstream f(StrCat(FPath, "size").c_str()); + std::string fpath = StrCat(dir, "index", idx++, "/"); + std::ifstream f(StrCat(fpath, "size").c_str()); if (!f.is_open()) break; std::string suffix; f >> info.size; if (f.fail()) - PrintErrorAndDie("Failed while reading file '", FPath, "size'"); + PrintErrorAndDie("Failed while reading file '", fpath, "size'"); if (f.good()) { f >> suffix; if (f.bad()) @@ -277,13 +269,13 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizesFromKVFS() { else if (suffix == "K") info.size *= 1024; } - if (!ReadFromFile(StrCat(FPath, "type"), &info.type)) - PrintErrorAndDie("Failed to read from file ", FPath, "type"); - if (!ReadFromFile(StrCat(FPath, "level"), &info.level)) - PrintErrorAndDie("Failed to read from file ", FPath, "level"); + if (!ReadFromFile(StrCat(fpath, "type"), &info.type)) + PrintErrorAndDie("Failed to read from file ", fpath, "type"); + if (!ReadFromFile(StrCat(fpath, "level"), &info.level)) + PrintErrorAndDie("Failed to read from file ", fpath, "level"); std::string map_str; - if (!ReadFromFile(StrCat(FPath, "shared_cpu_map"), &map_str)) - PrintErrorAndDie("Failed to read from file ", FPath, "shared_cpu_map"); + if (!ReadFromFile(StrCat(fpath, "shared_cpu_map"), &map_str)) + PrintErrorAndDie("Failed to read from file ", fpath, "shared_cpu_map"); info.num_sharing = CountSetBitsInCPUMap(map_str); res.push_back(info); } @@ -294,26 +286,26 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizesFromKVFS() { #ifdef BENCHMARK_OS_MACOSX std::vector<CPUInfo::CacheInfo> GetCacheSizesMacOSX() { std::vector<CPUInfo::CacheInfo> res; - std::array<uint64_t, 4> CacheCounts{{0, 0, 0, 0}}; - GetSysctl("hw.cacheconfig", &CacheCounts); + std::array<int, 4> cache_counts{{0, 0, 0, 0}}; + GetSysctl("hw.cacheconfig", &cache_counts); struct { std::string name; std::string type; int level; - uint64_t num_sharing; - } Cases[] = {{"hw.l1dcachesize", "Data", 1, CacheCounts[1]}, - {"hw.l1icachesize", "Instruction", 1, CacheCounts[1]}, - {"hw.l2cachesize", "Unified", 2, CacheCounts[2]}, - {"hw.l3cachesize", "Unified", 3, CacheCounts[3]}}; - for (auto& C : Cases) { + int num_sharing; + } cases[] = {{"hw.l1dcachesize", "Data", 1, cache_counts[1]}, + {"hw.l1icachesize", "Instruction", 1, cache_counts[1]}, + {"hw.l2cachesize", "Unified", 2, cache_counts[2]}, + {"hw.l3cachesize", "Unified", 3, cache_counts[3]}}; + for (auto& c : cases) { int val; - if (!GetSysctl(C.name, &val)) continue; + if (!GetSysctl(c.name, &val)) continue; CPUInfo::CacheInfo info; - info.type = C.type; - info.level = C.level; + info.type = c.type; + info.level = c.level; info.size = val; - info.num_sharing = static_cast<int>(C.num_sharing); + info.num_sharing = c.num_sharing; res.push_back(std::move(info)); } return res; @@ -338,16 +330,16 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizesWindows() { for (; it != end; ++it) { if (it->Relationship != RelationCache) continue; using BitSet = std::bitset<sizeof(ULONG_PTR) * CHAR_BIT>; - BitSet B(it->ProcessorMask); + BitSet b(it->ProcessorMask); // To prevent duplicates, only consider caches where CPU 0 is specified - if (!B.test(0)) continue; - CInfo* Cache = &it->Cache; + if (!b.test(0)) continue; + const CInfo& cache = it->Cache; CPUInfo::CacheInfo C; - C.num_sharing = static_cast<int>(B.count()); - C.level = Cache->Level; - C.size = Cache->Size; + C.num_sharing = static_cast<int>(b.count()); + C.level = cache.Level; + C.size = cache.Size; C.type = "Unknown"; - switch (Cache->Type) { + switch (cache.Type) { case CacheUnified: C.type = "Unified"; break; @@ -418,7 +410,7 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizes() { std::string GetSystemName() { #if defined(BENCHMARK_OS_WINDOWS) std::string str; - const unsigned COUNT = MAX_COMPUTERNAME_LENGTH + 1; + static constexpr int COUNT = MAX_COMPUTERNAME_LENGTH + 1; TCHAR hostname[COUNT] = {'\0'}; DWORD DWCOUNT = COUNT; if (!GetComputerName(hostname, &DWCOUNT)) return std::string(""); @@ -456,8 +448,8 @@ std::string GetSystemName() { int GetNumCPUs() { #ifdef BENCHMARK_HAS_SYSCTL - int NumCPU = -1; - if (GetSysctl("hw.ncpu", &NumCPU)) return NumCPU; + int num_cpu = -1; + if (GetSysctl("hw.ncpu", &num_cpu)) return num_cpu; fprintf(stderr, "Err: %s\n", strerror(errno)); std::exit(EXIT_FAILURE); #elif defined(BENCHMARK_OS_WINDOWS) @@ -471,17 +463,17 @@ int GetNumCPUs() { // group #elif defined(BENCHMARK_OS_SOLARIS) // Returns -1 in case of a failure. - int NumCPU = sysconf(_SC_NPROCESSORS_ONLN); - if (NumCPU < 0) { + int num_cpu = sysconf(_SC_NPROCESSORS_ONLN); + if (num_cpu < 0) { fprintf(stderr, "sysconf(_SC_NPROCESSORS_ONLN) failed with error: %s\n", strerror(errno)); } - return NumCPU; + return num_cpu; #elif defined(BENCHMARK_OS_QNX) return static_cast<int>(_syspage_ptr->num_cpu); #else - int NumCPUs = 0; - int MaxID = -1; + int num_cpus = 0; + int max_id = -1; std::ifstream f("/proc/cpuinfo"); if (!f.is_open()) { std::cerr << "failed to open /proc/cpuinfo\n"; @@ -491,21 +483,21 @@ int GetNumCPUs() { std::string ln; while (std::getline(f, ln)) { if (ln.empty()) continue; - size_t SplitIdx = ln.find(':'); + std::size_t split_idx = ln.find(':'); std::string value; #if defined(__s390__) // s390 has another format in /proc/cpuinfo // it needs to be parsed differently - if (SplitIdx != std::string::npos) - value = ln.substr(Key.size() + 1, SplitIdx - Key.size() - 1); + if (split_idx != std::string::npos) + value = ln.substr(Key.size() + 1, split_idx - Key.size() - 1); #else - if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1); + if (split_idx != std::string::npos) value = ln.substr(split_idx + 1); #endif if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) { - NumCPUs++; + num_cpus++; if (!value.empty()) { - int CurID = benchmark::stoi(value); - MaxID = std::max(CurID, MaxID); + const int cur_id = benchmark::stoi(value); + max_id = std::max(cur_id, max_id); } } } @@ -519,12 +511,12 @@ int GetNumCPUs() { } f.close(); - if ((MaxID + 1) != NumCPUs) { + if ((max_id + 1) != num_cpus) { fprintf(stderr, "CPU ID assignments in /proc/cpuinfo seem messed up." " This is usually caused by a bad BIOS.\n"); } - return NumCPUs; + return num_cpus; #endif BENCHMARK_UNREACHABLE(); } @@ -569,7 +561,7 @@ double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) { return error_value; } - auto startsWithKey = [](std::string const& Value, std::string const& Key) { + auto StartsWithKey = [](std::string const& Value, std::string const& Key) { if (Key.size() > Value.size()) return false; auto Cmp = [&](char X, char Y) { return std::tolower(X) == std::tolower(Y); @@ -580,18 +572,18 @@ double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) { std::string ln; while (std::getline(f, ln)) { if (ln.empty()) continue; - size_t SplitIdx = ln.find(':'); + std::size_t split_idx = ln.find(':'); std::string value; - if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1); + if (split_idx != std::string::npos) value = ln.substr(split_idx + 1); // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only // accept positive values. Some environments (virtual machines) report zero, // which would cause infinite looping in WallTime_Init. - if (startsWithKey(ln, "cpu MHz")) { + if (StartsWithKey(ln, "cpu MHz")) { if (!value.empty()) { double cycles_per_second = benchmark::stod(value) * 1000000.0; if (cycles_per_second > 0) return cycles_per_second; } - } else if (startsWithKey(ln, "bogomips")) { + } else if (StartsWithKey(ln, "bogomips")) { if (!value.empty()) { bogo_clock = benchmark::stod(value) * 1000000.0; if (bogo_clock < 0.0) bogo_clock = error_value; @@ -613,7 +605,7 @@ double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) { if (bogo_clock >= 0.0) return bogo_clock; #elif defined BENCHMARK_HAS_SYSCTL - constexpr auto* FreqStr = + constexpr auto* freqStr = #if defined(BENCHMARK_OS_FREEBSD) || defined(BENCHMARK_OS_NETBSD) "machdep.tsc_freq"; #elif defined BENCHMARK_OS_OPENBSD @@ -625,14 +617,17 @@ double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) { #endif unsigned long long hz = 0; #if defined BENCHMARK_OS_OPENBSD - if (GetSysctl(FreqStr, &hz)) return hz * 1000000; + if (GetSysctl(freqStr, &hz)) return hz * 1000000; #else - if (GetSysctl(FreqStr, &hz)) return hz; + if (GetSysctl(freqStr, &hz)) return hz; #endif fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n", - FreqStr, strerror(errno)); + freqStr, strerror(errno)); + fprintf(stderr, + "This does not affect benchmark measurements, only the " + "metadata output.\n"); -#elif defined BENCHMARK_OS_WINDOWS +#elif defined BENCHMARK_OS_WINDOWS_WIN32 // In NT, read MHz from the registry. If we fail to do so or we're in win9x // then make a crude estimate. DWORD data, data_size = sizeof(data); @@ -677,7 +672,7 @@ double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) { (int64_t)(1000 * 1000)); #endif // If we've fallen through, attempt to roughly estimate the CPU clock rate. - const int estimate_time_ms = 1000; + static constexpr int estimate_time_ms = 1000; const auto start_ticks = cycleclock::Now(); SleepForMilliseconds(estimate_time_ms); return static_cast<double>(cycleclock::Now() - start_ticks); @@ -688,7 +683,7 @@ std::vector<double> GetLoadAvg() { defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD || \ defined BENCHMARK_OS_OPENBSD || defined BENCHMARK_OS_DRAGONFLY) && \ !defined(__ANDROID__) - constexpr int kMaxSamples = 3; + static constexpr int kMaxSamples = 3; std::vector<double> res(kMaxSamples, 0.0); const int nelem = getloadavg(res.data(), kMaxSamples); if (nelem < 1) { diff --git a/contrib/libs/benchmark/src/timers.cc b/contrib/libs/benchmark/src/timers.cc index 9a21cb1436b..97682bdcc7f 100644 --- a/contrib/libs/benchmark/src/timers.cc +++ b/contrib/libs/benchmark/src/timers.cc @@ -123,7 +123,7 @@ double ProcessCPUUsage() { // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) returns 0 on Emscripten. // Use Emscripten-specific API. Reported CPU time would be exactly the // same as total time, but this is ok because there aren't long-latency - // syncronous system calls in Emscripten. + // synchronous system calls in Emscripten. return emscripten_get_now() * 1e-3; #elif defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX) // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. diff --git a/library/python/svn_version/__init__.py b/library/python/svn_version/__init__.py index 7eeb9573e88..caaef65bfe3 100644 --- a/library/python/svn_version/__init__.py +++ b/library/python/svn_version/__init__.py @@ -1 +1,5 @@ -from .__svn_version import svn_version, commit_id, svn_revision, svn_last_revision, hash, svn_branch, svn_tag, patch_number, vcs # noqa +from .__svn_version import svn_version, commit_id, svn_revision, svn_last_revision, hash, svn_branch, svn_tag, patch_number, vcs, svn_timestamp + +__all__ = ( + 'svn_version', 'commit_id', 'svn_revision', 'svn_last_revision', 'hash', 'svn_branch', 'svn_tag', 'patch_number', 'vcs', 'svn_timestamp' +) diff --git a/library/python/svn_version/__svn_version.pyx b/library/python/svn_version/__svn_version.pyx index 95f74f525ea..8d119e7f0b4 100644 --- a/library/python/svn_version/__svn_version.pyx +++ b/library/python/svn_version/__svn_version.pyx @@ -10,6 +10,7 @@ cdef extern from "library/cpp/svnversion/svnversion.h": cdef const char* GetBranch() except +; cdef const char* GetTag() except +; cdef int GetArcadiaPatchNumber() except +; + cdef int GetProgramBuildTimestamp() except +; def svn_version(): return fu.bytes_to_native_str(GetProgramSvnVersion()) @@ -32,6 +33,9 @@ def svn_branch(): def svn_tag(): return fu.bytes_to_native_str(GetTag()) +def svn_timestamp(): + return GetProgramBuildTimestamp() + def patch_number(): return GetArcadiaPatchNumber() diff --git a/ydb/core/tx/datashard/datashard_ut_change_exchange.cpp b/ydb/core/tx/datashard/datashard_ut_change_exchange.cpp index 00fe8f76d40..f6ec6b55488 100644 --- a/ydb/core/tx/datashard/datashard_ut_change_exchange.cpp +++ b/ydb/core/tx/datashard/datashard_ut_change_exchange.cpp @@ -1112,6 +1112,14 @@ Y_UNIT_TEST_SUITE(Cdc) { } // Yds specific + Y_UNIT_TEST(DescribeStream) { + TTestYdsEnv env(SimpleTable(), KeysOnly(NKikimrSchemeOp::ECdcStreamFormatJson)); + + auto res = env.GetClient().DescribeStream("/Root/Table/Stream").ExtractValueSync(); + UNIT_ASSERT_C(res.IsSuccess(), res.GetIssues().ToString()); + UNIT_ASSERT_VALUES_EQUAL(res.GetResult().stream_description().stream_name(), "/Root/Table/Stream"); + } + Y_UNIT_TEST(UpdateStream) { TTestYdsEnv env(SimpleTable(), KeysOnly(NKikimrSchemeOp::ECdcStreamFormatJson)); diff --git a/ydb/services/lib/actors/pq_schema_actor.h b/ydb/services/lib/actors/pq_schema_actor.h index 337c125bce1..72d641cb8da 100644 --- a/ydb/services/lib/actors/pq_schema_actor.h +++ b/ydb/services/lib/actors/pq_schema_actor.h @@ -106,6 +106,10 @@ namespace NKikimr::NGRpcProxy::V1 { return path; } + const TMaybe<TString>& GetCdcStreamName() const { + return CdcStreamName; + } + protected: // TDerived must implement FillProposeRequest(TEvProposeTransaction&, const TActorContext& ctx, TString workingDir, TString name); void SendProposeRequest(const NActors::TActorContext &ctx) { @@ -200,6 +204,11 @@ namespace NKikimr::NGRpcProxy::V1 { if (static_cast<TDerived*>(this)->IsCdcStreamCompatible()) { Y_VERIFY(response.ListNodeEntry->Children.size() == 1); PrivateTopicName = response.ListNodeEntry->Children.at(0).Name; + + if (response.Self) { + CdcStreamName = response.Self->Info.GetName(); + } + return SendDescribeProposeRequest(ctx); } } @@ -302,6 +311,7 @@ namespace NKikimr::NGRpcProxy::V1 { bool IsDead = false; const TString TopicPath; TMaybe<TString> PrivateTopicName; + TMaybe<TString> CdcStreamName; }; //----------------------------------------------------------------------------------- diff --git a/ydb/services/persqueue_v1/actors/schema_actors.cpp b/ydb/services/persqueue_v1/actors/schema_actors.cpp index 94955b96c7a..845a3129c58 100644 --- a/ydb/services/persqueue_v1/actors/schema_actors.cpp +++ b/ydb/services/persqueue_v1/actors/schema_actors.cpp @@ -69,12 +69,13 @@ void TPQDescribeTopicActor::HandleCacheNavigateResponse(TEvTxProxySchemeCache::T Ydb::PersQueue::V1::DescribeTopicResult result; - auto settings = result.mutable_settings(); Ydb::Scheme::Entry *selfEntry = result.mutable_self(); - const auto& selfInfo = response.Self->Info; - selfEntry->set_name(path + "/" + selfInfo.GetName()); - selfEntry->set_type(static_cast<Ydb::Scheme::Entry::Type>(selfInfo.GetPathType())); - ConvertDirectoryEntry(selfInfo, selfEntry, true); + ConvertDirectoryEntry(response.Self->Info, selfEntry, true); + if (const auto& name = GetCdcStreamName()) { + selfEntry->set_name(*name); + } + + auto settings = result.mutable_settings(); if (response.PQGroupInfo) { const auto &pqDescr = response.PQGroupInfo->Description; settings->set_partitions_count(pqDescr.GetTotalGroupCount()); @@ -459,10 +460,11 @@ void TDescribeTopicActor::HandleCacheNavigateResponse(TEvTxProxySchemeCache::TEv Ydb::Topic::DescribeTopicResult result; Ydb::Scheme::Entry *selfEntry = result.mutable_self(); - const auto& selfInfo = response.Self->Info; - selfEntry->set_name(path + "/" + selfInfo.GetName()); - selfEntry->set_type(Ydb::Scheme::Entry::TOPIC); - ConvertDirectoryEntry(selfInfo, selfEntry, true); + ConvertDirectoryEntry(response.Self->Info, selfEntry, true); + if (const auto& name = GetCdcStreamName()) { + selfEntry->set_name(*name); + } + if (response.PQGroupInfo) { const auto &pqDescr = response.PQGroupInfo->Description; result.mutable_partitioning_settings()->set_min_active_partitions(pqDescr.GetTotalGroupCount()); diff --git a/ydb/services/persqueue_v1/actors/schema_actors.h b/ydb/services/persqueue_v1/actors/schema_actors.h index 4a4a12b3e70..b00b7d54fe8 100644 --- a/ydb/services/persqueue_v1/actors/schema_actors.h +++ b/ydb/services/persqueue_v1/actors/schema_actors.h @@ -42,7 +42,7 @@ public: class TPQDescribeTopicActor : public TPQGrpcSchemaBase<TPQDescribeTopicActor, NKikimr::NGRpcService::TEvPQDescribeTopicRequest> - , public TCdcStreamCompatible + , public TCdcStreamCompatible { using TBase = TPQGrpcSchemaBase<TPQDescribeTopicActor, TEvPQDescribeTopicRequest>; |