aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorilnaz <ilnaz@ydb.tech>2022-07-21 09:45:49 +0300
committerilnaz <ilnaz@ydb.tech>2022-07-21 09:45:49 +0300
commitfab0834c2c9d7652c3b4b3897654a85b3fbb7885 (patch)
tree34d27f24cfe9c87ce9e6ce9b8866cc122d9b8e34
parent6b94014b1082ce9c3c702bdc7051efd00658da1b (diff)
downloadydb-fab0834c2c9d7652c3b4b3897654a85b3fbb7885.tar.gz
Get rid of 'streamImpl' in responses
-rw-r--r--contrib/libs/benchmark/AUTHORS2
-rw-r--r--contrib/libs/benchmark/LICENSE32
-rw-r--r--contrib/libs/benchmark/README.md2
-rw-r--r--contrib/libs/benchmark/include/benchmark/benchmark.h187
-rw-r--r--contrib/libs/benchmark/include/benchmark/export.h42
-rw-r--r--contrib/libs/benchmark/src/benchmark.cc120
-rw-r--r--contrib/libs/benchmark/src/benchmark_api_internal.cc8
-rw-r--r--contrib/libs/benchmark/src/benchmark_api_internal.h3
-rw-r--r--contrib/libs/benchmark/src/benchmark_name.cc4
-rw-r--r--contrib/libs/benchmark/src/benchmark_register.cc36
-rw-r--r--contrib/libs/benchmark/src/benchmark_register.h4
-rw-r--r--contrib/libs/benchmark/src/benchmark_runner.cc81
-rw-r--r--contrib/libs/benchmark/src/benchmark_runner.h9
-rw-r--r--contrib/libs/benchmark/src/check.cc11
-rw-r--r--contrib/libs/benchmark/src/check.h7
-rw-r--r--contrib/libs/benchmark/src/commandlineflags.h39
-rw-r--r--contrib/libs/benchmark/src/console_reporter.cc8
-rw-r--r--contrib/libs/benchmark/src/cycleclock.h4
-rw-r--r--contrib/libs/benchmark/src/internal_macros.h7
-rw-r--r--contrib/libs/benchmark/src/json_reporter.cc6
-rw-r--r--contrib/libs/benchmark/src/perf_counters.cc42
-rw-r--r--contrib/libs/benchmark/src/perf_counters.h73
-rw-r--r--contrib/libs/benchmark/src/statistics.cc8
-rw-r--r--contrib/libs/benchmark/src/statistics.h5
-rw-r--r--contrib/libs/benchmark/src/string_util.h3
-rw-r--r--contrib/libs/benchmark/src/sysinfo.cc229
-rw-r--r--contrib/libs/benchmark/src/timers.cc2
-rw-r--r--library/python/svn_version/__init__.py6
-rw-r--r--library/python/svn_version/__svn_version.pyx4
-rw-r--r--ydb/core/tx/datashard/datashard_ut_change_exchange.cpp8
-rw-r--r--ydb/services/lib/actors/pq_schema_actor.h10
-rw-r--r--ydb/services/persqueue_v1/actors/schema_actors.cpp20
-rw-r--r--ydb/services/persqueue_v1/actors/schema_actors.h2
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>;