Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #ifndef ELEKTRA_KDBTIMER_HPP
10 : #define ELEKTRA_KDBTIMER_HPP
11 :
12 : #include <algorithm>
13 : #include <iomanip>
14 : #include <iostream>
15 : #include <numeric>
16 : #include <sstream>
17 : #include <string>
18 : #include <sys/time.h>
19 : #include <vector>
20 :
21 : #ifdef __GNUC__
22 : #define TIMER_NOINLINE __attribute__ ((noinline))
23 : #endif
24 :
25 : class Timer
26 : {
27 : public:
28 : // options what to do at cleanup
29 : enum option_t
30 : {
31 : raw_data_cerr, ///< print name,data\n (default!)
32 : median_cerr, ///< print name,median\n
33 : quiet, ///< print nothing
34 : };
35 :
36 : // functions
37 0 : TIMER_NOINLINE void start ()
38 : {
39 0 : gettimeofday (&begin, nullptr);
40 : // clock_gettime(CLOCK_MONOTONIC, &begin);
41 0 : }
42 0 : TIMER_NOINLINE void stop ()
43 : {
44 0 : gettimeofday (&end, nullptr);
45 : // clock_gettime(CLOCK_MONOTONIC, &end);
46 :
47 : // force calculation in long long:
48 : // could use timersub here
49 0 : timer_t result = end.tv_sec - begin.tv_sec;
50 0 : result *= usec_factor;
51 0 : result += end.tv_usec - begin.tv_usec;
52 0 : results.push_back (result);
53 0 : }
54 : std::string getMedian () const;
55 : Timer (std::string name, option_t option = raw_data_cerr);
56 : ~Timer (); // print csv table at end
57 :
58 : // data
59 : struct timeval begin;
60 : struct timeval end;
61 : typedef long long timer_t;
62 : typedef std::vector<timer_t> results_t;
63 : results_t results;
64 : std::string name;
65 : option_t option;
66 : static const timer_t usec_factor = 1000000LL;
67 : };
68 :
69 0 : inline Timer::Timer (std::string name_, option_t option_) : begin (), end (), results (), name (std::move (name_)), option (option_)
70 : {
71 : }
72 :
73 0 : inline Timer::~Timer ()
74 : {
75 0 : switch (option)
76 : {
77 : case raw_data_cerr:
78 0 : for (auto result : results)
79 : {
80 : // clang-format off
81 0 : std::cerr << name << ","
82 0 : << result / Timer::usec_factor
83 : << "."
84 : << std::setw(6)
85 0 : << std::setfill('0')
86 0 : << result % Timer::usec_factor
87 0 : << std::endl;
88 : // clang-format on
89 : }
90 : break;
91 : case median_cerr:
92 0 : std::cerr << name << "," << getMedian () << std::endl;
93 0 : break;
94 : case quiet:
95 : break;
96 : }
97 0 : }
98 :
99 0 : std::string Timer::getMedian () const
100 : {
101 0 : Timer::results_t md = results;
102 0 : nth_element (md.begin (), md.begin () + md.size () / 2, md.end ());
103 0 : Timer::timer_t r = *(md.begin () + md.size () / 2);
104 0 : std::ostringstream os;
105 0 : os << r / Timer::usec_factor << "." << std::setw (6) << std::setfill ('0') << r % Timer::usec_factor;
106 0 : return os.str ();
107 : }
108 :
109 :
110 0 : inline std::ostream & operator<< (std::ostream & os, Timer const & t)
111 : {
112 : // clang-format off
113 0 : Timer::timer_t r = t.results.back();
114 0 : os.width(30);
115 0 : os.fill(' ');
116 0 : os << t.name << "\t";
117 0 : os << r / Timer::usec_factor
118 : << "."
119 : << std::setw(6)
120 0 : << std::setfill('0')
121 0 : << r % Timer::usec_factor
122 0 : << " sec";
123 0 : r = std::accumulate(t.results.begin(), t.results.end(), 0LL);
124 0 : os << "\t Sum: "
125 0 : << r / Timer::usec_factor
126 : << "."
127 : << std::setw(6)
128 0 : << std::setfill('0')
129 0 : << r % Timer::usec_factor
130 0 : << " sec";
131 0 : r = r / t.results.size();
132 0 : os << "\tAvg: "
133 0 : << r / Timer::usec_factor
134 : << "."
135 : << std::setw(6)
136 0 : << std::setfill('0')
137 0 : << r % Timer::usec_factor
138 0 : << " sec";
139 0 : r = *std::min_element(t.results.begin(), t.results.end());
140 0 : os << "\tMin: "
141 0 : << r / Timer::usec_factor
142 : << "."
143 : << std::setw(6)
144 0 : << std::setfill('0')
145 0 : << r % Timer::usec_factor
146 0 : << " sec";
147 0 : r = *std::max_element(t.results.begin(), t.results.end());
148 0 : os << "\tMax: "
149 0 : << r / Timer::usec_factor
150 : << "."
151 : << std::setw(6)
152 0 : << std::setfill('0')
153 0 : << r % Timer::usec_factor
154 0 : << " sec";
155 : os << "\tMedian: "
156 0 : << t.getMedian()
157 0 : << " sec"
158 0 : << std::endl;
159 : // clang-format on
160 0 : return os;
161 : }
162 :
163 : #endif
|