The Gaudi Framework  v33r1 (b1225454)
RdtscClock.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #pragma once
12 
13 #include <chrono>
14 #include <functional>
15 #include <ratio>
16 #include <thread>
17 #include <x86intrin.h>
18 
19 namespace Gaudi {
20  namespace Timers {
32  template <typename Precision = std::chrono::microseconds>
33  class RdtscClock {
34  public:
35  // to meet requirements of TrivialClock:
36  typedef typename Precision::rep rep;
37  typedef typename Precision::period period;
40 
41  static constexpr bool is_steady{true};
42 
43  // some sanity checks:
44  static_assert( period::num == 1, "The Precision of RdtscClock must be reducible to 1/N" );
46  "The Precision of RdtscClock must be at least std::chrono::milliseconds" );
47 
49  static rep calibrate() noexcept { return ticks_per_unit(); }
50 
51  static time_point now() noexcept { return time_point{duration( __rdtsc() / ticks_per_unit() )}; }
52 
53  private:
54  static rep ticks_per_unit() noexcept {
55  static rep ticks_per_unit = do_calibrate(); // local static guarantees thread-safety
56  return ticks_per_unit;
57  }
58 
59  static rep do_calibrate() noexcept {
60  // Calibration time and conversion factor to unit of Precision
61  static constexpr auto calibTime = std::chrono::milliseconds( 100 );
62  static constexpr auto toPrec = std::ratio_divide<std::milli, period>::num;
63 
64  // Calibrate against wall clock
66  auto t1 = __rdtsc();
67  std::this_thread::sleep_for( calibTime );
68  auto t2 = __rdtsc();
70 
71  // Calculate ticks per unit of Precision
72  auto dt_ref = std::chrono::duration_cast<std::chrono::milliseconds>( t2_ref - t1_ref ).count();
73  rep ticks_per_unit = ( t2 - t1 ) / ( dt_ref * toPrec );
74 
75  return ticks_per_unit;
76  }
77  };
78  } // namespace Timers
79 } // namespace Gaudi
Precision::rep rep
Definition: RdtscClock.h:36
static rep do_calibrate() noexcept
Definition: RdtscClock.h:59
static rep ticks_per_unit() noexcept
Definition: RdtscClock.h:54
T sleep_for(T... args)
static rep calibrate() noexcept
Calibrate the RDTSC clock against wall time.
Definition: RdtscClock.h:49
static time_point now() noexcept
Definition: RdtscClock.h:51
A std::chrono compatible Clock using rdtsc as its timing source.
Definition: RdtscClock.h:33
std::chrono::duration< rep, period > duration
Definition: RdtscClock.h:38
Precision::period period
Definition: RdtscClock.h:37
std::chrono::time_point< RdtscClock > time_point
Definition: RdtscClock.h:39
static constexpr bool is_steady
Definition: RdtscClock.h:41
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1