The Gaudi Framework  master (37c0b60a)
RdtscClock.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2020 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 #ifndef __x86_64__
14 # error "<Gaudi/Timers/RdtscClock.h> is only supported on x86"
15 #else // not __x86_64__
16 
17 # include <chrono>
18 # include <functional>
19 # include <ratio>
20 # include <thread>
21 # include <x86intrin.h>
22 
23 namespace Gaudi {
24  namespace Timers {
36  template <typename Precision = std::chrono::microseconds>
37  class RdtscClock {
38  public:
39  // to meet requirements of TrivialClock:
40  typedef typename Precision::rep rep;
41  typedef typename Precision::period period;
42  typedef std::chrono::duration<rep, period> duration;
43  typedef std::chrono::time_point<RdtscClock> time_point;
44 
45  static constexpr bool is_steady{ true };
46 
47  // some sanity checks:
48  static_assert( period::num == 1, "The Precision of RdtscClock must be reducible to 1/N" );
50  "The Precision of RdtscClock must be at least std::chrono::milliseconds" );
51 
53  static rep calibrate() noexcept { return ticks_per_unit(); }
54 
55  static time_point now() noexcept { return time_point{ duration( __rdtsc() / ticks_per_unit() ) }; }
56 
57  private:
58  static rep ticks_per_unit() noexcept {
59  static rep ticks_per_unit = do_calibrate(); // local static guarantees thread-safety
60  return ticks_per_unit;
61  }
62 
63  static rep do_calibrate() noexcept {
64  // Calibration time and conversion factor to unit of Precision
65  static constexpr auto calibTime = std::chrono::milliseconds( 100 );
66  static constexpr auto toPrec = std::ratio_divide<std::milli, period>::num;
67 
68  // Calibrate against wall clock
70  auto t1 = __rdtsc();
71  std::this_thread::sleep_for( calibTime );
72  auto t2 = __rdtsc();
74 
75  // Calculate ticks per unit of Precision
76  auto dt_ref = std::chrono::duration_cast<std::chrono::milliseconds>( t2_ref - t1_ref ).count();
77  rep ticks_per_unit = ( t2 - t1 ) / ( dt_ref * toPrec );
78 
79  return ticks_per_unit;
80  }
81  };
82  } // namespace Timers
83 } // namespace Gaudi
84 #endif
std::this_thread::sleep_for
T sleep_for(T... args)
std::ratio_less_equal
std::chrono::duration
TemplatedAlg
Definition: TemplatedAlg.cpp:22
std::chrono::time_point
Gaudi
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition: __init__.py:1
std::ratio_divide
t1
TemplatedAlg< int, std::vector< std::string > > t1
Definition: TemplatedAlg.cpp:40
std::chrono::high_resolution_clock::now
T now(T... args)