]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/timer/src/cpu_timer.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / timer / src / cpu_timer.cpp
CommitLineData
7c673cae
FG
1// boost cpu_timer.cpp ---------------------------------------------------------------//
2
3// Copyright Beman Dawes 1994-2006, 2011
4
5// Distributed under the Boost Software License, Version 1.0. (See accompanying
6// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8// See http://www.boost.org/libs/timer for documentation.
9
10//--------------------------------------------------------------------------------------//
11
12// define BOOST_TIMER_SOURCE so that <boost/timer/config.hpp> knows
13// the library is being built (possibly exporting rather than importing code)
14#define BOOST_TIMER_SOURCE
15
16#include <boost/timer/timer.hpp>
17#include <boost/chrono/chrono.hpp>
18#include <boost/io/ios_state.hpp>
19#include <boost/throw_exception.hpp>
20#include <boost/cerrno.hpp>
92f5a8d4 21#include <boost/predef.h>
7c673cae
FG
22#include <cstring>
23#include <sstream>
24#include <cassert>
25
26# if defined(BOOST_WINDOWS_API)
27# include <windows.h>
28# elif defined(BOOST_POSIX_API)
29# include <unistd.h>
30# include <sys/times.h>
31# else
32# error unknown API
33# endif
34
35using boost::timer::nanosecond_type;
36using boost::timer::cpu_times;
37using boost::system::error_code;
38
39namespace
40{
41
42 void show_time(const cpu_times& times,
43 std::ostream& os, const std::string& fmt, short places)
44 // NOTE WELL: Will truncate least-significant digits to LDBL_DIG, which may
45 // be as low as 10, although will be 15 for many common platforms.
46 {
47 if (places > 9)
48 places = 9;
49 else if (places < 0)
50 places = boost::timer::default_places;
51
52 boost::io::ios_flags_saver ifs(os);
53 boost::io::ios_precision_saver ips(os);
54 os.setf(std::ios_base::fixed, std::ios_base::floatfield);
55 os.precision(places);
56
57 const double sec = 1000000000.0L;
58 nanosecond_type total = times.system + times.user;
59 double wall_sec = static_cast<double>(times.wall) / sec;
60 double total_sec = static_cast<double>(total) / sec;
61
62 for (const char* format = fmt.c_str(); *format; ++format)
63 {
64 if (*format != '%' || !*(format+1) || !std::strchr("wustp", *(format+1)))
65 os << *format; // anything except % followed by a valid format character
66 // gets sent to the output stream
67 else
68 {
69 ++format;
70 switch (*format)
71 {
72 case 'w':
73 os << wall_sec;
74 break;
75 case 'u':
76 os << static_cast<double>(times.user) / sec;
77 break;
78 case 's':
79 os << static_cast<double>(times.system) / sec;
80 break;
81 case 't':
82 os << total_sec;
83 break;
84 case 'p':
85 os.precision(1);
86 if (wall_sec > 0.001L && total_sec > 0.001L)
87 os << (total_sec/wall_sec) * 100.0;
88 else
89 os << "n/a";
90 os.precision(places);
91 break;
92 }
93 }
94 }
95 }
96
97# if defined(BOOST_POSIX_API)
98 boost::int_least64_t tick_factor() // multiplier to convert ticks
99 // to nanoseconds; -1 if unknown
100 {
101 static boost::int_least64_t tick_factor = 0;
102 if (!tick_factor)
103 {
104 if ((tick_factor = ::sysconf(_SC_CLK_TCK)) <= 0)
105 tick_factor = -1;
106 else
107 {
b32b8144 108 tick_factor = INT64_C(1000000000) / tick_factor; // compute factor
7c673cae
FG
109 if (!tick_factor)
110 tick_factor = -1;
111 }
112 }
113 return tick_factor;
114 }
115# endif
116
117 void get_cpu_times(boost::timer::cpu_times& current)
118 {
119 boost::chrono::duration<boost::int64_t, boost::nano>
120 x (boost::chrono::high_resolution_clock::now().time_since_epoch());
121 current.wall = x.count();
122
123# if defined(BOOST_WINDOWS_API)
124
92f5a8d4 125# if BOOST_PLAT_WINDOWS_DESKTOP || defined(__CYGWIN__)
7c673cae
FG
126 FILETIME creation, exit;
127 if (::GetProcessTimes(::GetCurrentProcess(), &creation, &exit,
128 (LPFILETIME)&current.system, (LPFILETIME)&current.user))
129 {
130 current.user *= 100; // Windows uses 100 nanosecond ticks
131 current.system *= 100;
132 }
133 else
92f5a8d4 134# endif
7c673cae
FG
135 {
136 current.system = current.user = boost::timer::nanosecond_type(-1);
137 }
138# else
139 tms tm;
140 clock_t c = ::times(&tm);
141 if (c == static_cast<clock_t>(-1)) // error
142 {
143 current.system = current.user = boost::timer::nanosecond_type(-1);
144 }
145 else
146 {
147 current.system = boost::timer::nanosecond_type(tm.tms_stime + tm.tms_cstime);
148 current.user = boost::timer::nanosecond_type(tm.tms_utime + tm.tms_cutime);
149 boost::int_least64_t factor;
150 if ((factor = tick_factor()) != -1)
151 {
152 current.user *= factor;
153 current.system *= factor;
154 }
155 else
156 {
157 current.user = current.system = boost::timer::nanosecond_type(-1);
158 }
159 }
160# endif
161 }
162
163 // CAUTION: must be identical to same constant in auto_timers_construction.cpp
164 const std::string default_fmt(" %ws wall, %us user + %ss system = %ts CPU (%p%)\n");
165
166} // unnamed namespace
167
168namespace boost
169{
170 namespace timer
171 {
172 // format ------------------------------------------------------------------------//
173
174 BOOST_TIMER_DECL
175 std::string format(const cpu_times& times, short places, const std::string& fmt)
176 {
177 std::stringstream ss;
178 ss.exceptions(std::ios_base::badbit | std::ios_base::failbit);
179 show_time(times, ss, fmt, places);
180 return ss.str();
181 }
182
183 BOOST_TIMER_DECL
184 std::string format(const cpu_times& times, short places)
185 {
186 return format(times, places, default_fmt);
187 }
188
189 // cpu_timer ---------------------------------------------------------------------//
190
191 void cpu_timer::start() BOOST_NOEXCEPT
192 {
193 m_is_stopped = false;
194 get_cpu_times(m_times);
195 }
196
197 void cpu_timer::stop() BOOST_NOEXCEPT
198 {
199 if (is_stopped())
200 return;
201 m_is_stopped = true;
202
203 cpu_times current;
204 get_cpu_times(current);
205 m_times.wall = (current.wall - m_times.wall);
206 m_times.user = (current.user - m_times.user);
207 m_times.system = (current.system - m_times.system);
208 }
209
210 cpu_times cpu_timer::elapsed() const BOOST_NOEXCEPT
211 {
212 if (is_stopped())
213 return m_times;
214 cpu_times current;
215 get_cpu_times(current);
216 current.wall -= m_times.wall;
217 current.user -= m_times.user;
218 current.system -= m_times.system;
219 return current;
220 }
221
222 void cpu_timer::resume() BOOST_NOEXCEPT
223 {
224 if (is_stopped())
225 {
226 cpu_times current (m_times);
227 start();
228 m_times.wall -= current.wall;
229 m_times.user -= current.user;
230 m_times.system -= current.system;
231 }
232 }
233
234 // auto_cpu_timer ----------------------------------------------------------------//
235
236 auto_cpu_timer::auto_cpu_timer(std::ostream& os, short places) // #5
237 : m_places(places), m_os(&os), m_format(default_fmt)
238 {
239 start();
240 }
241
242 void auto_cpu_timer::report()
243 {
244 show_time(elapsed(), ostream(), format_string(), places());
245 }
246
247 auto_cpu_timer::~auto_cpu_timer()
248 {
249 if (!is_stopped())
250 {
251 stop(); // the sooner we stop(), the better
b32b8144 252#ifndef BOOST_NO_EXCEPTIONS
7c673cae
FG
253 try
254 {
b32b8144 255#endif
7c673cae 256 report();
b32b8144 257#ifndef BOOST_NO_EXCEPTIONS
7c673cae
FG
258 }
259 catch (...) // eat any exceptions
260 {
261 }
b32b8144 262#endif
7c673cae
FG
263 }
264 }
265
266 } // namespace timer
267} // namespace boost