YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/monotime.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
33
#include "yb/util/monotime.h"
34
35
#include <glog/logging.h>
36
37
#include "yb/gutil/casts.h"
38
#include "yb/gutil/stringprintf.h"
39
#include "yb/gutil/sysinfo.h"
40
41
#include "yb/util/result.h"
42
#include "yb/util/thread_restrictions.h"
43
44
#if defined(__APPLE__)
45
#include "yb/gutil/walltime.h"
46
#endif
47
48
using namespace std::literals;
49
50
namespace yb {
51
52
#define MAX_MONOTONIC_SECONDS \
53
  (((1ULL<<63) - 1ULL) /(int64_t)MonoTime::kNanosecondsPerSecond)
54
55
namespace {
56
57
20.6M
bool SafeToAdd64(int64_t a, int64_t b) {
58
20.6M
  bool negativeA = a < 0;
59
20.6M
  bool negativeB = b < 0;
60
20.6M
  if (negativeA != negativeB) {
61
471
    return true;
62
471
  }
63
20.6M
  bool negativeSum = (a + b) < 0;
64
20.6M
  return negativeSum == negativeA;
65
20.6M
}
66
67
} // namespace
68
69
///
70
/// MonoDelta
71
///
72
73
const MonoDelta::NanoDeltaType MonoDelta::kUninitialized =
74
    std::numeric_limits<NanoDeltaType>::min();
75
const MonoDelta MonoDelta::kMin = MonoDelta(std::numeric_limits<NanoDeltaType>::min() + 1);
76
const MonoDelta MonoDelta::kMax = MonoDelta(std::numeric_limits<NanoDeltaType>::max());
77
const MonoDelta MonoDelta::kZero = MonoDelta(0);
78
79
template <class V>
80
303M
MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) {
81
303M
  CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul);
82
303M
  int64_t delta = value * mul;
83
303M
  return MonoDelta::FromNanoseconds(delta);
84
303M
}
yb::MonoDelta yb::MonoDeltaByMultiplication<double>(double, long long)
Line
Count
Source
80
1.86M
MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) {
81
1.86M
  CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul);
82
1.86M
  int64_t delta = value * mul;
83
1.86M
  return MonoDelta::FromNanoseconds(delta);
84
1.86M
}
yb::MonoDelta yb::MonoDeltaByMultiplication<long long>(long long, long long)
Line
Count
Source
80
301M
MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) {
81
301M
  CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul);
82
301M
  int64_t delta = value * mul;
83
301M
  return MonoDelta::FromNanoseconds(delta);
84
301M
}
85
86
16
MonoDelta MonoDelta::FromMinutes(double minutes) {
87
16
  return MonoDeltaByMultiplication(minutes, MonoTime::kNanosecondsPerMinute);
88
16
}
89
90
1.86M
MonoDelta MonoDelta::FromSeconds(double seconds) {
91
1.86M
  return MonoDeltaByMultiplication(seconds, MonoTime::kNanosecondsPerSecond);
92
1.86M
}
93
94
277M
MonoDelta MonoDelta::FromMilliseconds(int64_t ms) {
95
277M
  return MonoDeltaByMultiplication(ms, MonoTime::kNanosecondsPerMillisecond);
96
277M
}
97
98
24.0M
MonoDelta MonoDelta::FromMicroseconds(int64_t us) {
99
24.0M
  return MonoDeltaByMultiplication(us, MonoTime::kNanosecondsPerMicrosecond);
100
24.0M
}
101
102
303M
MonoDelta MonoDelta::FromNanoseconds(int64_t ns) {
103
303M
  return MonoDelta(ns);
104
303M
}
105
106
434M
MonoDelta::MonoDelta() noexcept : nano_delta_(kUninitialized) {
107
434M
}
108
109
6.33G
bool MonoDelta::Initialized() const {
110
6.33G
  return nano_delta_ != kUninitialized;
111
6.33G
}
112
113
199M
bool MonoDelta::LessThan(const MonoDelta &rhs) const {
114
199M
  DCHECK(Initialized());
115
199M
  DCHECK(rhs.Initialized());
116
199M
  return nano_delta_ < rhs.nano_delta_;
117
199M
}
118
119
1.45k
bool MonoDelta::MoreThan(const MonoDelta &rhs) const {
120
1.45k
  DCHECK(Initialized());
121
1.45k
  DCHECK(rhs.Initialized());
122
1.45k
  return nano_delta_ > rhs.nano_delta_;
123
1.45k
}
124
125
635M
bool MonoDelta::Equals(const MonoDelta &rhs) const {
126
635M
  DCHECK(Initialized());
127
635M
  DCHECK(rhs.Initialized());
128
635M
  return nano_delta_ == rhs.nano_delta_;
129
635M
}
130
131
72.5M
bool MonoDelta::IsNegative() const {
132
72.5M
  DCHECK(Initialized());
133
72.5M
  return nano_delta_ < 0;
134
72.5M
}
135
136
2.67M
std::string MonoDelta::ToString() const {
137
2.67M
  return Initialized() ? 
StringPrintf("%.3fs", ToSeconds())2.51M
:
"<uninitialized>"161k
;
138
2.67M
}
139
140
MonoDelta::MonoDelta(int64_t delta)
141
308M
  : nano_delta_(delta) {
142
308M
}
143
144
1.19G
double MonoDelta::ToSeconds() const {
145
1.19G
  DCHECK(Initialized());
146
1.19G
  double d(nano_delta_);
147
1.19G
  d /= MonoTime::kNanosecondsPerSecond;
148
1.19G
  return d;
149
1.19G
}
150
151
84
double MonoDelta::ToMinutes() const {
152
84
  auto seconds = ToSeconds();
153
84
  return seconds / MonoTime::kSecondsPerMinute;
154
84
}
155
156
930M
int64_t MonoDelta::ToNanoseconds() const {
157
930M
  DCHECK(Initialized());
158
930M
  return nano_delta_;
159
930M
}
160
161
745M
std::chrono::steady_clock::duration MonoDelta::ToSteadyDuration() const {
162
745M
  return std::chrono::nanoseconds(ToNanoseconds());
163
745M
}
164
165
771M
int64_t MonoDelta::ToMicroseconds() const {
166
771M
  DCHECK(Initialized());
167
771M
  return nano_delta_ / MonoTime::kNanosecondsPerMicrosecond;
168
771M
}
169
170
361M
int64_t MonoDelta::ToMilliseconds() const {
171
361M
  DCHECK(Initialized());
172
361M
  return nano_delta_ / MonoTime::kNanosecondsPerMillisecond;
173
361M
}
174
175
20.5M
MonoDelta& MonoDelta::operator+=(const MonoDelta& rhs) {
176
20.5M
  DCHECK(Initialized());
177
20.5M
  DCHECK(rhs.Initialized());
178
20.5M
  DCHECK(SafeToAdd64(nano_delta_, rhs.nano_delta_));
179
20.5M
  DCHECK(nano_delta_ + rhs.nano_delta_ != kUninitialized);
180
20.5M
  nano_delta_ += rhs.nano_delta_;
181
20.5M
  return *this;
182
20.5M
}
183
184
100k
MonoDelta& MonoDelta::operator-=(const MonoDelta& rhs) {
185
100k
  DCHECK(Initialized());
186
100k
  DCHECK(rhs.Initialized());
187
100k
  DCHECK(SafeToAdd64(nano_delta_, -rhs.nano_delta_));
188
100k
  DCHECK(nano_delta_ - rhs.nano_delta_ != kUninitialized);
189
100k
  nano_delta_ -= rhs.nano_delta_;
190
100k
  return *this;
191
100k
}
192
193
371M
MonoDelta& MonoDelta::operator*=(int64_t mul) {
194
371M
  DCHECK(Initialized());
195
  DCHECK
(mul == 0 || (nano_delta_ * mul / mul == nano_delta_)) // Check for overflow103k
196
103k
      << "Mul: " << mul << ", nano_delta_: " << nano_delta_;
197
371M
  DCHECK(nano_delta_ * mul != kUninitialized);
198
371M
  nano_delta_ *= mul;
199
371M
  return *this;
200
371M
}
201
202
24
MonoDelta& MonoDelta::operator/=(int64_t divisor) {
203
24
  DCHECK(Initialized());
204
24
  DCHECK_NE(divisor, 0);
205
24
  nano_delta_ /= divisor;
206
24
  return *this;
207
24
}
208
209
7.50M
void MonoDelta::ToTimeVal(struct timeval *tv) const {
210
7.50M
  DCHECK(Initialized());
211
7.50M
  tv->tv_sec = nano_delta_ / MonoTime::kNanosecondsPerSecond;
212
7.50M
  tv->tv_usec = narrow_cast<int32_t>(
213
7.50M
      (nano_delta_ - tv->tv_sec * MonoTime::kNanosecondsPerSecond)
214
7.50M
      / MonoTime::kNanosecondsPerMicrosecond);
215
216
  // tv_usec must be between 0 and 999999.
217
  // There is little use for negative timevals so wrap it in PREDICT_FALSE.
218
7.50M
  if (PREDICT_FALSE(tv->tv_usec < 0)) {
219
1
    --(tv->tv_sec);
220
1
    tv->tv_usec += MonoTime::kMicrosecondsPerSecond;
221
1
  }
222
223
  // Catch positive corner case where we "round down" and could potentially set a timeout of 0.
224
  // Make it 1 usec.
225
7.50M
  if (PREDICT_FALSE(tv->tv_usec == 0 && tv->tv_sec == 0 && nano_delta_ > 0)) {
226
1
    tv->tv_usec = 1;
227
1
  }
228
229
  // Catch negative corner case where we "round down" and could potentially set a timeout of 0.
230
  // Make it -1 usec (but normalized, so tv_usec is not negative).
231
7.50M
  if (PREDICT_FALSE(tv->tv_usec == 0 && tv->tv_sec == 0 && nano_delta_ < 0)) {
232
1
    tv->tv_sec = -1;
233
1
    tv->tv_usec = 999999;
234
1
  }
235
7.50M
}
236
237
238
102M
void MonoDelta::NanosToTimeSpec(int64_t nanos, struct timespec* ts) {
239
102M
  ts->tv_sec = nanos / MonoTime::kNanosecondsPerSecond;
240
102M
  ts->tv_nsec = nanos - (ts->tv_sec * MonoTime::kNanosecondsPerSecond);
241
242
  // tv_nsec must be between 0 and 999999999.
243
  // There is little use for negative timespecs so wrap it in PREDICT_FALSE.
244
102M
  if (PREDICT_FALSE(ts->tv_nsec < 0)) {
245
1
    --(ts->tv_sec);
246
1
    ts->tv_nsec += MonoTime::kNanosecondsPerSecond;
247
1
  }
248
102M
}
249
250
102M
void MonoDelta::ToTimeSpec(struct timespec *ts) const {
251
102M
  DCHECK(Initialized());
252
102M
  NanosToTimeSpec(nano_delta_, ts);
253
102M
}
254
255
///
256
/// MonoTime
257
///
258
259
const MonoTime MonoTime::kMin = MonoTime::Min();
260
const MonoTime MonoTime::kMax = MonoTime::Max();
261
const MonoTime MonoTime::kUninitialized = MonoTime();
262
263
1.46G
MonoTime MonoTime::Now() {
264
1.46G
  return MonoTime(std::chrono::steady_clock::now());
265
1.46G
}
266
267
272k
MonoTime MonoTime::Max() {
268
272k
  return MonoTime(std::chrono::steady_clock::time_point::max());
269
272k
}
270
271
2.47M
MonoTime MonoTime::Min() {
272
2.47M
  return MonoTime(std::chrono::steady_clock::time_point(std::chrono::steady_clock::duration(1)));
273
2.47M
}
274
275
4.07k
bool MonoTime::IsMax() const {
276
4.07k
  return Equals(kMax);
277
4.07k
}
278
279
4.07k
bool MonoTime::IsMin() const {
280
4.07k
  return Equals(kMin);
281
4.07k
}
282
283
462k
const MonoTime& MonoTime::Earliest(const MonoTime& a, const MonoTime& b) {
284
462k
  return std::min(a, b);
285
462k
}
286
287
762M
MonoDelta MonoTime::GetDeltaSince(const MonoTime &rhs) const {
288
762M
  DCHECK(Initialized());
289
762M
  DCHECK(rhs.Initialized());
290
762M
  return MonoDelta(value_ - rhs.value_);
291
762M
}
292
293
219M
void MonoTime::AddDelta(const MonoDelta &delta) {
294
219M
  DCHECK(Initialized());
295
219M
  DCHECK(delta.Initialized());
296
219M
  if (delta == MonoDelta::kMax) {
297
0
    value_ = kMax.value_;
298
219M
  } else {
299
219M
    value_ += delta.ToSteadyDuration();
300
219M
  }
301
219M
}
302
303
1
void MonoTime::SubtractDelta(const MonoDelta &delta) {
304
1
  DCHECK(Initialized());
305
1
  DCHECK(delta.Initialized());
306
1
  if (delta == MonoDelta::kMin) {
307
0
    value_ = kMin.value_;
308
1
  } else {
309
1
    value_ -= delta.ToSteadyDuration();
310
1
  }
311
1
}
312
313
61.2M
bool MonoTime::ComesBefore(const MonoTime &rhs) const {
314
61.2M
  DCHECK(Initialized());
315
61.2M
  DCHECK(rhs.Initialized());
316
61.2M
  return value_ < rhs.value_;
317
61.2M
}
318
319
4.07k
std::string MonoTime::ToString() const {
320
4.07k
  if (!Initialized())
321
0
    return "MonoTime::kUninitialized";
322
4.07k
  if (IsMax())
323
0
    return "MonoTime::kMax";
324
4.07k
  if (IsMin())
325
0
    return "MonoTime::kMin";
326
4.07k
  return StringPrintf("%.3fs", ToSeconds());
327
4.07k
}
328
329
628k
bool MonoTime::Equals(const MonoTime& other) const {
330
628k
  return value_ == other.value_;
331
628k
}
332
333
4.06k
double MonoTime::ToSeconds() const {
334
4.06k
  return yb::ToSeconds(value_.time_since_epoch());
335
4.06k
}
336
337
0
void MonoTime::MakeAtLeast(MonoTime rhs) {
338
0
  if (rhs.Initialized() && (!Initialized() || value_ < rhs.value_)) {
339
0
    value_ = rhs.value_;
340
0
  }
341
0
}
342
343
// ------------------------------------------------------------------------------------------------
344
345
0
std::string FormatForComparisonFailureMessage(const MonoDelta& op, const MonoDelta& other) {
346
0
  return op.ToString();
347
0
}
348
349
50.2M
void SleepFor(const MonoDelta& delta) {
350
50.2M
  ThreadRestrictions::AssertWaitAllowed();
351
50.2M
  base::SleepForNanoseconds(delta.ToNanoseconds());
352
50.2M
}
353
354
4.93G
CoarseMonoClock::time_point CoarseMonoClock::now() {
355
4.93G
#if defined(__APPLE__)
356
4.93G
  int64_t nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(
357
4.93G
      std::chrono::steady_clock::now().time_since_epoch()).count();
358
# else
359
  struct timespec ts;
360
  PCHECK(clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0);
361
  CHECK_LT(ts.tv_sec, MAX_MONOTONIC_SECONDS);
362
  int64_t nanos = static_cast<int64_t>(ts.tv_sec) * MonoTime::kNanosecondsPerSecond + ts.tv_nsec;
363
#endif // defined(__APPLE__)
364
4.93G
  return time_point(duration(nanos));
365
4.93G
}
366
367
template <>
368
66.7k
CoarseMonoClock::Duration ClockResolution<CoarseMonoClock>() {
369
66.7k
#if defined(__APPLE__)
370
66.7k
  return std::chrono::duration_cast<CoarseMonoClock::Duration>(
371
66.7k
      std::chrono::steady_clock::duration(1));
372
#else
373
  struct timespec res;
374
  if (clock_getres(CLOCK_MONOTONIC_COARSE, &res) == 0) {
375
    auto resolution = std::chrono::seconds(res.tv_sec) + std::chrono::nanoseconds(res.tv_nsec);
376
    return std::chrono::duration_cast<CoarseMonoClock::Duration>(resolution);
377
  }
378
  return CoarseMonoClock::Duration(1);
379
#endif // defined(__APPLE__)
380
66.7k
}
381
382
166k
std::string ToString(CoarseMonoClock::TimePoint time_point) {
383
166k
  return MonoDelta(time_point.time_since_epoch()).ToString();
384
166k
}
385
386
184M
CoarseTimePoint ToCoarse(MonoTime monotime) {
387
184M
  return CoarseTimePoint(monotime.ToSteadyTimePoint().time_since_epoch());
388
184M
}
389
390
1.91M
std::chrono::steady_clock::time_point ToSteady(CoarseTimePoint time_point) {
391
1.91M
  return std::chrono::steady_clock::time_point(time_point.time_since_epoch());
392
1.91M
}
393
394
} // namespace yb