diff --git a/dbms/src/Common/Stopwatch.h b/dbms/src/Common/Stopwatch.h index 425bae95885..1762a2cdfea 100644 --- a/dbms/src/Common/Stopwatch.h +++ b/dbms/src/Common/Stopwatch.h @@ -30,7 +30,7 @@ inline UInt64 clock_gettime_ns(clockid_t clock_type = CLOCK_MONOTONIC) { }; clock_gettime(clock_type, &ts); - return UInt64(ts.tv_sec * 1000000000ULL + ts.tv_nsec); + return static_cast(ts.tv_sec * 1000000000ULL + ts.tv_nsec); } /// Sometimes monotonic clock may not be monotonic (due to bug in kernel?). @@ -64,14 +64,14 @@ class Stopwatch void start() { - start_ns = nanoseconds(); + start_ns = nanosecondsWithBound(start_ns); last_ns = start_ns; is_running = true; } void stop() { - stop_ns = nanoseconds(); + stop_ns = nanosecondsWithBound(start_ns); is_running = false; } @@ -82,14 +82,16 @@ class Stopwatch last_ns = 0; is_running = false; } + void restart() { start(); } - UInt64 elapsed() const { return is_running ? nanoseconds() - start_ns : stop_ns - start_ns; } + + UInt64 elapsed() const { return is_running ? nanosecondsWithBound(start_ns) - start_ns : stop_ns - start_ns; } UInt64 elapsedMilliseconds() const { return elapsed() / 1000000UL; } double elapsedSeconds() const { return static_cast(elapsed()) / 1000000000ULL; } UInt64 elapsedFromLastTime() { - const auto now_ns = nanoseconds(); + const auto now_ns = nanosecondsWithBound(last_ns); if (is_running) { auto rc = now_ns - last_ns; @@ -100,7 +102,7 @@ class Stopwatch { return stop_ns - last_ns; } - }; + } UInt64 elapsedMillisecondsFromLastTime() { return elapsedFromLastTime() / 1000000UL; } UInt64 elapsedSecondsFromLastTime() { return elapsedFromLastTime() / 1000000UL; } @@ -112,7 +114,9 @@ class Stopwatch clockid_t clock_type; bool is_running = false; - UInt64 nanoseconds() const { return clock_gettime_ns_adjusted(start_ns, clock_type); } + // Get current nano seconds, ensuring the return value is not + // less than `lower_bound`. + UInt64 nanosecondsWithBound(UInt64 lower_bound) const { return clock_gettime_ns_adjusted(lower_bound, clock_type); } }; diff --git a/dbms/src/TestUtils/FunctionTestUtils.cpp b/dbms/src/TestUtils/FunctionTestUtils.cpp index 343b378007a..810533db4d8 100644 --- a/dbms/src/TestUtils/FunctionTestUtils.cpp +++ b/dbms/src/TestUtils/FunctionTestUtils.cpp @@ -318,10 +318,13 @@ ColumnWithTypeAndName executeFunction( for (size_t i = 0; i < columns.size(); ++i) argument_column_numbers.push_back(i); + /// Replace `std::random_device` with `std::chrono::system_clock` here to avoid + /// exceptions like 'random_device failed to open /dev/urandom: Operation not permitted'. + /// The reason of exceptions is unknown, but the probability of its occurrence in unittests + /// TestDateTimeDayMonthYear.dayMonthYearTest is not low. + /// Since this function is just used for testing, using current timestamp as a random seed is not a problem. + std::mt19937 g(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())); /// shuffle input columns to assure function correctly use physical offsets instead of logical offsets - std::random_device rd; - std::mt19937 g(rd()); - std::shuffle(argument_column_numbers.begin(), argument_column_numbers.end(), g); const auto columns_reordered = toColumnsReordered(columns, argument_column_numbers);