File indexing completed on 2025-08-06 08:17:27
0001 #ifndef PHOOL_PHTIMER_H
0002 #define PHOOL_PHTIMER_H
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <unistd.h>
0013 #include <exception>
0014 #include <iostream>
0015 #include <sstream>
0016 #include <string>
0017
0018 #define rdtsc(low, high) \
0019 __asm__ __volatile__("rdtsc" \
0020 : "=a"(low), "=d"(high))
0021
0022
0023
0024
0025 class PHTimer
0026 {
0027 public:
0028
0029 enum State
0030 {
0031 STOP = 0,
0032 RUN = 1
0033 };
0034
0035
0036 State get_state(void) const
0037 {
0038 return _state;
0039 }
0040
0041
0042 explicit PHTimer(const std::string& name = "Generic Timer")
0043 : _name(name)
0044 , _state(STOP)
0045 , _start_time(get_clock_counts())
0046 , _stop_time(get_clock_counts())
0047 {
0048 _stop_time._low++;
0049 }
0050
0051
0052 void stop()
0053 {
0054 if (_state == STOP) return;
0055 _stop_time = get_clock_counts();
0056 _state = STOP;
0057 _ncycle++;
0058 _accumulated_time += elapsed();
0059 }
0060
0061
0062 void restart()
0063 {
0064 _start_time = get_clock_counts();
0065 _state = RUN;
0066 }
0067
0068
0069 void print(std::ostream& os = std::cout) const
0070 {
0071 double elapse(elapsed());
0072 PRINT(os, "Timing for " + _name);
0073 os << "time (ms): " << elapse << std::endl;
0074 PRINT();
0075 }
0076
0077
0078 void print_stat(std::ostream& os = std::cout) const
0079 {
0080
0081 if (_ncycle)
0082 {
0083 os << _name << ": accumulated time (ms): " << _accumulated_time << std::endl;
0084 os << _name << ": per event time (ms): " << _accumulated_time / _ncycle << std::endl;
0085 }
0086 else
0087 {
0088 os << _name << ": timer never started.\n";
0089 }
0090 PRINT(os, "**");
0091 }
0092
0093
0094 void set_name(const std::string& name)
0095 {
0096 _name = name;
0097 }
0098
0099
0100 const std::string& get_name(void) const
0101 {
0102 return _name;
0103 }
0104
0105
0106 double get_accumulated_time(void) const
0107 {
0108 return _accumulated_time;
0109 }
0110
0111
0112 unsigned int get_ncycle(void) const
0113 {
0114 return _ncycle;
0115 }
0116
0117
0118 double get_time_per_cycle(void) const
0119 {
0120 return _accumulated_time / _ncycle;
0121 }
0122
0123
0124 double elapsed(void) const
0125 {
0126 return 1000.0 * get_difference(
0127 (_state == RUN) ? get_clock_counts() : _stop_time,
0128 _start_time);
0129 }
0130
0131
0132 void test(double time, std::ostream& os = std::cout)
0133 {
0134 std::ostringstream tmp;
0135 tmp << "Test for " << _name << " - " << time << "ms";
0136 PRINT(os, tmp.str());
0137 restart();
0138 usleep((unsigned int) (time * 1000));
0139 print(os);
0140 }
0141
0142
0143 static void PRINT(std::ostream& os = std::cout, const std::string& message = "");
0144
0145 private:
0146
0147 class Frequency
0148 {
0149 public:
0150
0151 Frequency()
0152 {
0153 try
0154 {
0155 set_cpu_freq();
0156 }
0157 catch (std::exception& e)
0158 {
0159 std::cout << e.what() << std::endl;
0160 }
0161 _period = 1.0 / _frequency;
0162 }
0163
0164
0165 operator double() const
0166 {
0167 return _frequency;
0168 }
0169
0170
0171 double period() const
0172 {
0173 return _period;
0174 }
0175
0176 private:
0177
0178 double _frequency;
0179
0180
0181 double _period;
0182
0183
0184 void set_cpu_freq(const std::string& cpuinfopath = "/proc/cpuinfo");
0185 };
0186
0187
0188 struct time_struct
0189 {
0190
0191 time_struct(void) = default;
0192
0193
0194 unsigned long _low{0};
0195
0196
0197 unsigned long _high{0};
0198 };
0199
0200
0201 static time_struct get_clock_counts(void)
0202 {
0203 time_struct t;
0204 rdtsc(t._low, t._high);
0205 return t;
0206 }
0207
0208
0209 static double get_difference(
0210 const time_struct&,
0211 const time_struct&);
0212
0213
0214 static Frequency _frequency;
0215
0216
0217 static const double _twopower32;
0218
0219
0220 std::string _name;
0221
0222
0223 State _state;
0224
0225
0226 time_struct _start_time;
0227
0228
0229 time_struct _stop_time;
0230
0231
0232 double _accumulated_time{0};
0233
0234
0235 unsigned int _ncycle{0};
0236 };
0237
0238 #endif