quill
StopWatch.h
1 
7 #pragma once
8 
9 #include <chrono>
10 #include <cstddef>
11 #include <cstdint>
12 #include <cstring>
13 
14 #include "quill/backend/RdtscClock.h"
15 #include "quill/core/Attributes.h"
16 #include "quill/core/ChronoTimeUtils.h"
17 #include "quill/core/Codec.h"
18 #include "quill/core/Common.h"
19 #include "quill/core/DynamicFormatArgStore.h"
20 #include "quill/core/Rdtsc.h"
21 
22 #include "quill/bundled/fmt/format.h"
23 #include "quill/std/Chrono.h"
24 
25 QUILL_BEGIN_NAMESPACE
26 
27 QUILL_BEGIN_EXPORT
28 
29 namespace detail
30 {
49 template <ClockSourceType ClockType>
50 class StopWatch
51 {
52 public:
53  static_assert((ClockType == ClockSourceType::Tsc) || (ClockType == ClockSourceType::System),
54  "Invalid ClockType");
55 
60  {
61  if constexpr (ClockType == ClockSourceType::Tsc)
62  {
63  _ns_per_tick = RdtscClock::RdtscTicks::instance().ns_per_tick();
64  _start_tp = rdtsc();
65  }
66  else
67  {
68  _start_tp = detail::get_steady_time_ns();
69  }
70  }
71 
76  [[nodiscard]] std::chrono::duration<double> elapsed() const
77  {
78  return elapsed_as<std::chrono::duration<double>>();
79  }
80 
85  template <typename T>
86  [[nodiscard]] T elapsed_as() const
87  {
88  if constexpr (ClockType == ClockSourceType::Tsc)
89  {
90  return std::chrono::duration_cast<T>(std::chrono::nanoseconds{
91  static_cast<uint64_t>(static_cast<double>(rdtsc() - _start_tp) * _ns_per_tick)});
92  }
93  else
94  {
95  return std::chrono::duration_cast<T>(std::chrono::nanoseconds{detail::get_steady_time_ns() - _start_tp});
96  }
97  }
98 
102  void reset()
103  {
104  if constexpr (ClockType == ClockSourceType::Tsc)
105  {
106  _start_tp = rdtsc();
107  }
108  else
109  {
110  _start_tp = detail::get_steady_time_ns();
111  }
112  }
113 
114 private:
115  double _ns_per_tick{0};
116  uint64_t _start_tp{0};
117 };
118 } // namespace detail
119 
124 
129 
130 QUILL_END_EXPORT
131 
132 QUILL_END_NAMESPACE
133 
134 QUILL_BEGIN_EXPORT
135 
143 template <quill::ClockSourceType ClockType>
144 struct quill::Codec<quill::detail::StopWatch<ClockType>>
145 {
146  static size_t compute_encoded_size(quill::detail::SizeCacheVector&,
147  quill::detail::StopWatch<ClockType> const&) noexcept
148  {
149  return sizeof(double);
150  }
151 
152  static void encode(std::byte*& buffer, quill::detail::SizeCacheVector const&, uint32_t&,
153  quill::detail::StopWatch<ClockType> const& sw) noexcept
154  {
155  // Sample the elapsed time on the frontend thread at the log call site.
156  double const elapsed_seconds = sw.elapsed().count();
157  std::memcpy(buffer, &elapsed_seconds, sizeof(elapsed_seconds));
158  buffer += sizeof(elapsed_seconds);
159  }
160 
161  static double decode_arg(std::byte*& buffer)
162  {
163  double elapsed_seconds;
164  std::memcpy(&elapsed_seconds, buffer, sizeof(elapsed_seconds));
165  buffer += sizeof(elapsed_seconds);
166  return elapsed_seconds;
167  }
168 
169  static void decode_and_store_arg(std::byte*& buffer, quill::DynamicFormatArgStore* args_store)
170  {
171  args_store->push_back(decode_arg(buffer));
172  }
173 };
174 
175 QUILL_END_EXPORT
StopWatch()
Constructor.
Definition: StopWatch.h:59
Definition: MegaEventCodecFuzzer.cpp:101
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:28
std::chrono::duration< double > elapsed() const
Returns the elapsed time since construction.
Definition: StopWatch.h:76
QUILL_NODISCARD QUILL_ATTRIBUTE_HOT uint64_t rdtsc() noexcept
Get the TSC counter.
Definition: Rdtsc.h:105
T elapsed_as() const
Returns the elapsed time since construction as the specified duration type.
Definition: StopWatch.h:86
void reset()
Resets the stopwatch, starting the measurement from the current time.
Definition: StopWatch.h:102
QUILL_ATTRIBUTE_HOT void encode(std::byte *&buffer, SizeCacheVector const &conditional_arg_size_cache, Args &&... args)
Encodes multiple arguments into a buffer.
Definition: Codec.h:397
QUILL_NODISCARD QUILL_ATTRIBUTE_HOT uint64_t get_steady_time_ns() noexcept
Mirrors std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::steady_clock::now().time_since_epoch()).count().
Definition: ChronoTimeUtils.h:90
A stopwatch utility for measuring elapsed time since construction.
Definition: StopWatch.h:50