aboutsummaryrefslogtreecommitdiffstats
path: root/util/datetime
diff options
context:
space:
mode:
authoryegorskii <yegorskii@yandex-team.com>2022-07-26 11:02:24 +0300
committeryegorskii <yegorskii@yandex-team.com>2022-07-26 11:02:24 +0300
commit0e2671e6b9f8c0cc55bc8123b48e76d3a1eae832 (patch)
tree1879fc4640531151d7e5fd7bfd22dcde8f862124 /util/datetime
parent06d9fbac1232813e0109ce49b3b0f7d4447aa2c4 (diff)
downloadydb-0e2671e6b9f8c0cc55bc8123b48e76d3a1eae832.tar.gz
add functions without overflow
Diffstat (limited to 'util/datetime')
-rw-r--r--util/datetime/cputimer.cpp17
-rw-r--r--util/datetime/cputimer.h4
-rw-r--r--util/datetime/cputimer_ut.cpp10
3 files changed, 31 insertions, 0 deletions
diff --git a/util/datetime/cputimer.cpp b/util/datetime/cputimer.cpp
index a032dbd3df..32ccfd4740 100644
--- a/util/datetime/cputimer.cpp
+++ b/util/datetime/cputimer.cpp
@@ -49,10 +49,27 @@ TDuration CyclesToDuration(ui64 cycles) {
return TDuration::MicroSeconds(cycles * 1000000 / GetCyclesPerSecond());
}
+TDuration CyclesToDurationSafe(ui64 cycles)
+{
+ constexpr ui64 cyclesLimit = std::numeric_limits<ui64>::max() / 1000000;
+ if (cycles <= cyclesLimit) {
+ return CyclesToDuration(cycles);
+ }
+ return TDuration::MicroSeconds(cycles / GetCyclesPerSecond() * 1000000);
+}
+
ui64 DurationToCycles(TDuration duration) {
return duration.MicroSeconds() * GetCyclesPerSecond() / 1000000;
}
+ui64 DurationToCyclesSafe(TDuration duration)
+{
+ if (duration.MicroSeconds() <= std::numeric_limits<ui64>::max() / GetCyclesPerSecond()) {
+ return DurationToCycles(duration);
+ }
+ return duration.MicroSeconds() / 1000000 * GetCyclesPerSecond();
+}
+
TPrecisionTimer::TPrecisionTimer()
: Start(::GetCycleCount())
{
diff --git a/util/datetime/cputimer.h b/util/datetime/cputimer.h
index 7d38d5bdb3..b24d6fae8e 100644
--- a/util/datetime/cputimer.h
+++ b/util/datetime/cputimer.h
@@ -62,6 +62,10 @@ void SetCyclesPerSecond(ui64 cycles);
TDuration CyclesToDuration(ui64 cycles);
ui64 DurationToCycles(TDuration duration);
+// NBS-3400 - CyclesToDuration and DurationToCycles may overflow for long running events
+TDuration CyclesToDurationSafe(ui64 cycles);
+ui64 DurationToCyclesSafe(TDuration duration);
+
class TPrecisionTimer {
private:
ui64 Start = 0;
diff --git a/util/datetime/cputimer_ut.cpp b/util/datetime/cputimer_ut.cpp
new file mode 100644
index 0000000000..21a657d5c7
--- /dev/null
+++ b/util/datetime/cputimer_ut.cpp
@@ -0,0 +1,10 @@
+#include <library/cpp/testing/unittest/registar.h>
+
+#include "cputimer.h"
+
+Y_UNIT_TEST_SUITE(TestCpuTimerSuite) {
+ Y_UNIT_TEST(TestCyclesToDurationSafe) {
+ ui64 cycles = DurationToCyclesSafe(TDuration::Hours(24));
+ UNIT_ASSERT_VALUES_EQUAL(24, CyclesToDurationSafe(cycles).Hours());
+ }
+}