EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHTimer.h
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHTimer.h
1 #ifndef PHOOL_PHTIMER_H
2 #define PHOOL_PHTIMER_H
3 
12 #include <unistd.h>
13 #include <exception>
14 #include <iostream>
15 #include <string>
16 #include <sstream>
17 
18 #define rdtsc(low, high) \
19  __asm__ __volatile__("rdtsc" \
20  : "=a"(low), "=d"(high))
21 
23 
24 
25 class PHTimer
26 {
27  public:
29  enum State
30  {
31  STOP = 0,
32  RUN = 1
33  };
34 
36  State get_state(void) const
37  {
38  return _state;
39  }
40 
42  explicit PHTimer(const std::string& name = "Generic Timer")
43  : _name(name)
44  , _state(STOP)
48  , _ncycle(0)
49  {
50  _stop_time._low++;
51  }
52 
54  void stop()
55  {
56  if (_state == STOP) return;
58  _state = STOP;
59  _ncycle++;
61  }
62 
64  void restart()
65  {
67  _state = RUN;
68  }
69 
71  void print(std::ostream& os = std::cout) const
72  {
73  double elapse(elapsed());
74  PRINT(os, "Timing for " + _name);
75  os << "time (ms): " << elapse << std::endl;
76  PRINT();
77  }
78 
80  void print_stat(std::ostream& os = std::cout) const
81  {
82  // PRINT(os, std::string("Stats for " + _name));
83  if (_ncycle)
84  {
85  os << _name << ": accumulated time (ms): " << _accumulated_time << std::endl;
86  os << _name << ": per event time (ms): " << _accumulated_time / _ncycle << std::endl;
87  }
88  else
89  {
90  os << _name << ": timer never started.\n";
91  }
92  PRINT(os, "**");
93  }
94 
96  void set_name(const std::string& name)
97  {
98  _name = name;
99  }
100 
102  std::string get_name(void) const
103  {
104  return _name;
105  }
106 
108  double get_accumulated_time(void) const
109  {
110  return _accumulated_time;
111  }
112 
114  unsigned int get_ncycle(void) const
115  {
116  return _ncycle;
117  }
118 
120  double get_time_per_cycle(void) const
121  {
122  return _accumulated_time / _ncycle;
123  }
124 
126  double elapsed(void) const
127  {
128  return 1000.0 * get_difference(
130  _start_time);
131  }
132 
134  void test(double time, std::ostream& os = std::cout)
135  {
136  std::ostringstream tmp;
137  tmp << "Test for " << _name << " - " << time << "ms";
138  PRINT(os, tmp.str());
139  restart();
140  usleep((unsigned int) (time * 1000));
141  print(os);
142  }
143 
145  static void PRINT(std::ostream& os = std::cout, const std::string& message = "");
146 
147  private:
149  class Frequency
150  {
151  public:
154  {
155  try
156  {
157  set_cpu_freq();
158  }
159  catch (std::exception& e)
160  {
161  std::cerr << e.what() << std::endl;
162  }
163  _period = 1.0 / _frequency;
164  }
165 
167  operator double() const
168  {
169  return _frequency;
170  }
171 
173  double period() const
174  {
175  return _period;
176  }
177 
178  private:
180  double _frequency;
181 
183  double _period;
184 
186  void set_cpu_freq(const std::string &cpuinfopath = "/proc/cpuinfo");
187  };
188 
190  struct time_struct
191  {
194  : _low(0)
195  , _high(0)
196  {
197  }
198 
200  unsigned long _low;
201 
203  unsigned long _high;
204  };
205 
208  {
209  time_struct t;
210  rdtsc(t._low, t._high);
211  return t;
212  }
213 
215  static double get_difference(
216  const time_struct&,
217  const time_struct&);
218 
221 
223  static const double _twopower32;
224 
226  std::string _name;
227 
230 
233 
236 
239 
241  unsigned int _ncycle;
242 };
243 
244 #endif