src/core/lib/gprpp/time.cc
Go to the documentation of this file.
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
18 
19 #include <atomic>
20 #include <chrono>
21 #include <cstdint>
22 #include <limits>
23 #include <string>
24 #include <utility>
25 
26 #include "absl/strings/str_format.h"
27 
29 #include <grpc/support/log.h>
30 
31 namespace grpc_core {
32 
33 namespace {
34 
35 std::atomic<int64_t> g_process_epoch_seconds;
36 std::atomic<gpr_cycle_counter> g_process_epoch_cycles;
37 
38 GPR_ATTRIBUTE_NOINLINE std::pair<int64_t, gpr_cycle_counter> InitTime() {
39  gpr_cycle_counter cycles_start = 0;
40  gpr_cycle_counter cycles_end = 0;
41  int64_t process_epoch_seconds = 0;
42 
43  // Check the current time... if we end up with zero, try again after 100ms.
44  // If it doesn't advance after sleeping for 1100ms, crash the process.
45  for (int i = 0; i < 11; i++) {
46  cycles_start = gpr_get_cycle_counter();
48  cycles_end = gpr_get_cycle_counter();
49  process_epoch_seconds = now.tv_sec - 1;
50  if (process_epoch_seconds != 0) {
51  break;
52  }
54  }
55 
56  // Time does not seem to be increasing from zero...
57  GPR_ASSERT(process_epoch_seconds != 0);
58  int64_t expected = 0;
59  gpr_cycle_counter process_epoch_cycles = (cycles_start + cycles_end) / 2;
60  GPR_ASSERT(process_epoch_cycles != 0);
61  if (!g_process_epoch_seconds.compare_exchange_strong(
62  expected, process_epoch_seconds, std::memory_order_relaxed,
63  std::memory_order_relaxed)) {
64  process_epoch_seconds = expected;
65  do {
66  process_epoch_cycles =
67  g_process_epoch_cycles.load(std::memory_order_relaxed);
68  } while (process_epoch_cycles == 0);
69  } else {
70  g_process_epoch_cycles.store(process_epoch_cycles,
71  std::memory_order_relaxed);
72  }
73  return std::make_pair(process_epoch_seconds, process_epoch_cycles);
74 }
75 
76 gpr_timespec StartTime() {
77  int64_t sec = g_process_epoch_seconds.load(std::memory_order_relaxed);
78  if (GPR_UNLIKELY(sec == 0)) sec = InitTime().first;
79  return {sec, 0, GPR_CLOCK_MONOTONIC};
80 }
81 
82 gpr_cycle_counter StartCycleCounter() {
83  gpr_cycle_counter cycles =
84  g_process_epoch_cycles.load(std::memory_order_relaxed);
85  if (GPR_UNLIKELY(cycles == 0)) cycles = InitTime().second;
86  return cycles;
87 }
88 
89 gpr_timespec MillisecondsAsTimespec(int64_t millis, gpr_clock_type clock_type) {
90  // special-case infinities as Timestamp can be 32bit on some
91  // platforms while gpr_time_from_millis always takes an int64_t.
92  if (millis == std::numeric_limits<int64_t>::max()) {
93  return gpr_inf_future(clock_type);
94  }
95  if (millis == std::numeric_limits<int64_t>::min()) {
96  return gpr_inf_past(clock_type);
97  }
98 
99  if (clock_type == GPR_TIMESPAN) {
100  return gpr_time_from_millis(millis, GPR_TIMESPAN);
101  }
102  return gpr_time_add(gpr_convert_clock_type(StartTime(), clock_type),
104 }
105 
106 int64_t TimespanToMillisRoundUp(gpr_timespec ts) {
108  double x = GPR_MS_PER_SEC * static_cast<double>(ts.tv_sec) +
109  static_cast<double>(ts.tv_nsec) / GPR_NS_PER_MS +
110  static_cast<double>(GPR_NS_PER_SEC - 1) /
111  static_cast<double>(GPR_NS_PER_SEC);
112  if (x <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
114  }
115  if (x >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
117  }
118  return static_cast<int64_t>(x);
119 }
120 
121 int64_t TimespanToMillisRoundDown(gpr_timespec ts) {
123  double x = GPR_MS_PER_SEC * static_cast<double>(ts.tv_sec) +
124  static_cast<double>(ts.tv_nsec) / GPR_NS_PER_MS;
125  if (x <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
127  }
128  if (x >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
130  }
131  return static_cast<int64_t>(x);
132 }
133 
134 } // namespace
135 
137  return FromMillisecondsAfterProcessEpoch(TimespanToMillisRoundUp(gpr_time_sub(
138  gpr_convert_clock_type(ts, GPR_CLOCK_MONOTONIC), StartTime())));
139 }
140 
143  TimespanToMillisRoundDown(gpr_time_sub(
144  gpr_convert_clock_type(ts, GPR_CLOCK_MONOTONIC), StartTime())));
145 }
146 
149  TimespanToMillisRoundUp(gpr_cycle_counter_sub(c, StartCycleCounter())));
150 }
151 
154  TimespanToMillisRoundDown(gpr_cycle_counter_sub(c, StartCycleCounter())));
155 }
156 
158  return MillisecondsAsTimespec(millis_, clock_type);
159 }
160 
163  return "@∞";
164  }
166  return "@-∞";
167  }
168  return "@" + std::to_string(millis_) + "ms";
169 }
170 
172  return MillisecondsAsTimespec(millis_, GPR_TIMESPAN);
173 }
174 
176  return Duration::Milliseconds(TimespanToMillisRoundUp(t));
177 }
178 
181  return "∞";
182  }
184  return "-∞";
185  }
186  return std::to_string(millis_) + "ms";
187 }
188 
190  gpr_timespec ts = as_timespec();
191  return absl::StrFormat("%d.%09ds", ts.tv_sec, ts.tv_nsec);
192 }
193 
195  const {
196  return std::chrono::milliseconds(
199 }
200 
202  g_process_epoch_seconds.store(
204 }
205 
206 std::ostream& operator<<(std::ostream& out, Timestamp timestamp) {
207  return out << timestamp.ToString();
208 }
209 
210 std::ostream& operator<<(std::ostream& out, Duration duration) {
211  return out << duration.ToString();
212 }
213 
214 } // namespace grpc_core
gpr_timespec::tv_nsec
int32_t tv_nsec
Definition: gpr_types.h:52
GPR_TIMESPAN
@ GPR_TIMESPAN
Definition: gpr_types.h:45
gpr_timespec::tv_sec
int64_t tv_sec
Definition: gpr_types.h:51
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
now
static double now(void)
Definition: test/core/fling/client.cc:130
log.h
absl::StrFormat
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec< Args... > &format, const Args &... args)
Definition: abseil-cpp/absl/strings/str_format.h:338
grpc_core::TestOnlySetProcessEpoch
void TestOnlySetProcessEpoch(gpr_timespec epoch)
Definition: src/core/lib/gprpp/time.cc:201
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::Timestamp
Definition: src/core/lib/gprpp/time.h:62
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
grpc_event_engine::experimental::EventEngine::Duration
std::chrono::duration< int64_t, std::nano > Duration
Definition: event_engine.h:80
gpr_inf_future
GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type)
Definition: src/core/lib/gpr/time.cc:55
grpc_core::Duration::millis_
int64_t millis_
Definition: src/core/lib/gprpp/time.h:226
GPR_NS_PER_SEC
#define GPR_NS_PER_SEC
Definition: include/grpc/support/time.h:41
grpc_core::operator<<
std::ostream & operator<<(std::ostream &out, Timestamp timestamp)
Definition: src/core/lib/gprpp/time.cc:206
grpc_core::Duration::ToString
std::string ToString() const
Definition: src/core/lib/gprpp/time.cc:179
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
gpr_time_sub
GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b)
Definition: src/core/lib/gpr/time.cc:168
GPR_UNLIKELY
#define GPR_UNLIKELY(x)
Definition: impl/codegen/port_platform.h:770
gpr_sleep_until
GPRAPI void gpr_sleep_until(gpr_timespec until)
grpc_core::Timestamp::ToString
std::string ToString() const
Definition: src/core/lib/gprpp/time.cc:161
time.h
epoch
int64_t epoch(int year, int yday, int hour, int min, int sec)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:10172
GPR_CLOCK_MONOTONIC
@ GPR_CLOCK_MONOTONIC
Definition: gpr_types.h:36
grpc_core::Duration::FromTimespec
static Duration FromTimespec(gpr_timespec t)
Definition: src/core/lib/gprpp/time.cc:175
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
grpc_core::Duration::ToJsonString
std::string ToJsonString() const
Definition: src/core/lib/gprpp/time.cc:189
min
#define min(a, b)
Definition: qsort.h:83
gpr_now
GPRAPI gpr_timespec gpr_now(gpr_clock_type clock)
grpc_core::Timestamp::FromMillisecondsAfterProcessEpoch
static constexpr Timestamp FromMillisecondsAfterProcessEpoch(int64_t millis)
Definition: src/core/lib/gprpp/time.h:73
gpr_types.h
GPR_NS_PER_MS
#define GPR_NS_PER_MS
Definition: include/grpc/support/time.h:42
gpr_timespec::clock_type
gpr_clock_type clock_type
Definition: gpr_types.h:55
gpr_inf_past
GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type)
Definition: src/core/lib/gpr/time.cc:63
grpc_core::Duration::Milliseconds
static constexpr Duration Milliseconds(int64_t millis)
Definition: src/core/lib/gprpp/time.h:155
grpc_core::Clamp
T Clamp(T val, T min, T max)
Definition: useful.h:31
gpr_time_add
GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b)
Definition: src/core/lib/gpr/time.cc:135
gpr_convert_clock_type
GPRAPI gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type)
Definition: src/core/lib/gpr/time.cc:241
grpc_core::Timestamp::millis_
int64_t millis_
Definition: src/core/lib/gprpp/time.h:118
gpr_cycle_counter_sub
gpr_timespec gpr_cycle_counter_sub(gpr_cycle_counter a, gpr_cycle_counter b)
grpc_core::Timestamp::FromCycleCounterRoundDown
static Timestamp FromCycleCounterRoundDown(gpr_cycle_counter c)
Definition: src/core/lib/gprpp/time.cc:152
grpc_core::Duration::as_timespec
gpr_timespec as_timespec() const
Definition: src/core/lib/gprpp/time.cc:171
grpc_core::Timestamp::FromTimespecRoundDown
static Timestamp FromTimespecRoundDown(gpr_timespec t)
Definition: src/core/lib/gprpp/time.cc:141
grpc_core::Timestamp::FromCycleCounterRoundUp
static Timestamp FromCycleCounterRoundUp(gpr_cycle_counter c)
Definition: src/core/lib/gprpp/time.cc:147
gpr_time_from_millis
GPRAPI gpr_timespec gpr_time_from_millis(int64_t ms, gpr_clock_type clock_type)
Definition: src/core/lib/gpr/time.cc:119
GPR_MS_PER_SEC
#define GPR_MS_PER_SEC
Definition: include/grpc/support/time.h:39
gpr_timespec
Definition: gpr_types.h:50
grpc_core::Timestamp::FromTimespecRoundUp
static Timestamp FromTimespecRoundUp(gpr_timespec t)
Definition: src/core/lib/gprpp/time.cc:136
grpc_core::Duration
Definition: src/core/lib/gprpp/time.h:122
to_string
static bool to_string(zval *from)
Definition: protobuf/php/ext/google/protobuf/convert.c:333
grpc_core::Timestamp::as_timespec
gpr_timespec as_timespec(gpr_clock_type type) const
Definition: src/core/lib/gprpp/time.cc:157
GPR_ATTRIBUTE_NOINLINE
#define GPR_ATTRIBUTE_NOINLINE
Definition: impl/codegen/port_platform.h:684
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
gpr_clock_type
gpr_clock_type
Definition: gpr_types.h:34
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:36