]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/Cycles.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2014 UnitedStack <haomai@unitedstack.com>
8 * Author: Haomai Wang <haomaiwang@gmail.com>
10 * This is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License version 2.1, as published by the Free Software
13 * Foundation. See file COPYING.
16 /* Copyright (c) 2011-2014 Stanford University
18 * Permission to use, copy, modify, and distribute this software for any
19 * purpose with or without fee is hereby granted, provided that the above
20 * copyright notice and this permission notice appear in all copies.
22 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
23 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
25 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
27 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
28 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34 double Cycles::cycles_per_sec
= 0;
37 * Perform once-only overall initialization for the Cycles class, such
38 * as calibrating the clock frequency. This method must be called
39 * before using the Cycles module.
41 * It is not initialized by default because the timing loops cause
42 * general process startup times to balloon
43 * (http://tracker.ceph.com/issues/15225).
47 if (cycles_per_sec
!= 0)
50 // Skip initialization if rtdsc is not implemented
54 // Compute the frequency of the fine-grained CPU timer: to do this,
55 // take parallel time readings using both rdtsc and gettimeofday.
56 // After 10ms have elapsed, take the ratio between these readings.
58 struct timeval start_time
, stop_time
;
62 // There is one tricky aspect, which is that we could get interrupted
63 // between calling gettimeofday and reading the cycle counter, in which
64 // case we won't have corresponding readings. To handle this (unlikely)
65 // case, compute the overall result repeatedly, and wait until we get
66 // two successive calculations that are within 0.1% of each other.
69 if (gettimeofday(&start_time
, NULL
) != 0) {
70 ceph_abort_msg("couldn't read clock");
72 uint64_t start_cycles
= rdtsc();
74 if (gettimeofday(&stop_time
, NULL
) != 0) {
75 ceph_abort_msg("couldn't read clock");
77 uint64_t stop_cycles
= rdtsc();
78 micros
= (stop_time
.tv_usec
- start_time
.tv_usec
) +
79 (stop_time
.tv_sec
- start_time
.tv_sec
)*1000000;
81 cycles_per_sec
= static_cast<double>(stop_cycles
- start_cycles
);
82 cycles_per_sec
= 1000000.0*cycles_per_sec
/ static_cast<double>(micros
);
86 double delta
= cycles_per_sec
/1000.0;
87 if ((old_cycles
> (cycles_per_sec
- delta
)) &&
88 (old_cycles
< (cycles_per_sec
+ delta
))) {
91 old_cycles
= cycles_per_sec
;
96 * Return the number of CPU cycles per second.
98 double Cycles::per_second()
100 return get_cycles_per_sec();
104 * Given an elapsed time measured in cycles, return a floating-point number
105 * giving the corresponding time in seconds.
107 * Difference between the results of two calls to rdtsc.
108 * \param cycles_per_sec
109 * Optional parameter to specify the frequency of the counter that #cycles
110 * was taken from. Useful when converting a remote machine's tick counter
111 * to seconds. The default value of 0 will use the local processor's
112 * computed counter frequency.
114 * The time in seconds corresponding to cycles.
116 double Cycles::to_seconds(uint64_t cycles
, double cycles_per_sec
)
118 if (cycles_per_sec
== 0)
119 cycles_per_sec
= get_cycles_per_sec();
120 return static_cast<double>(cycles
)/cycles_per_sec
;
124 * Given a time in seconds, return the number of cycles that it
128 * \param cycles_per_sec
129 * Optional parameter to specify the frequency of the counter that #cycles
130 * was taken from. Useful when converting a remote machine's tick counter
131 * to seconds. The default value of 0 will use the local processor's
132 * computed counter frequency.
134 * The approximate number of cycles corresponding to #seconds.
136 uint64_t Cycles::from_seconds(double seconds
, double cycles_per_sec
)
138 if (cycles_per_sec
== 0)
139 cycles_per_sec
= get_cycles_per_sec();
140 return (uint64_t) (seconds
*cycles_per_sec
+ 0.5);
144 * Given an elapsed time measured in cycles, return an integer
145 * giving the corresponding time in microseconds. Note: to_seconds()
146 * is faster than this method.
148 * Difference between the results of two calls to rdtsc.
149 * \param cycles_per_sec
150 * Optional parameter to specify the frequency of the counter that #cycles
151 * was taken from. Useful when converting a remote machine's tick counter
152 * to seconds. The default value of 0 will use the local processor's
153 * computed counter frequency.
155 * The time in microseconds corresponding to cycles (rounded).
157 uint64_t Cycles::to_microseconds(uint64_t cycles
, double cycles_per_sec
)
159 return to_nanoseconds(cycles
, cycles_per_sec
) / 1000;
163 * Given an elapsed time measured in cycles, return an integer
164 * giving the corresponding time in nanoseconds. Note: to_seconds()
165 * is faster than this method.
167 * Difference between the results of two calls to rdtsc.
168 * \param cycles_per_sec
169 * Optional parameter to specify the frequency of the counter that #cycles
170 * was taken from. Useful when converting a remote machine's tick counter
171 * to seconds. The default value of 0 will use the local processor's
172 * computed counter frequency.
174 * The time in nanoseconds corresponding to cycles (rounded).
176 uint64_t Cycles::to_nanoseconds(uint64_t cycles
, double cycles_per_sec
)
178 if (cycles_per_sec
== 0)
179 cycles_per_sec
= get_cycles_per_sec();
180 return (uint64_t) (1e09
*static_cast<double>(cycles
)/cycles_per_sec
+ 0.5);
184 * Given a number of nanoseconds, return an approximate number of
185 * cycles for an equivalent time length.
187 * Number of nanoseconds.
188 * \param cycles_per_sec
189 * Optional parameter to specify the frequency of the counter that #cycles
190 * was taken from. Useful when converting a remote machine's tick counter
191 * to seconds. The default value of 0 will use the local processor's
192 * computed counter frequency.
194 * The approximate number of cycles for the same time length.
197 Cycles::from_nanoseconds(uint64_t ns
, double cycles_per_sec
)
199 if (cycles_per_sec
== 0)
200 cycles_per_sec
= get_cycles_per_sec();
201 return (uint64_t) (static_cast<double>(ns
)*cycles_per_sec
/1e09
+ 0.5);
205 * Busy wait for a given number of microseconds.
206 * Callers should use this method in most reasonable cases as opposed to
207 * usleep for accurate measurements. Calling usleep may put the the processor
208 * in a low power mode/sleep state which reduces the clock frequency.
209 * So, each time the process/thread wakes up from usleep, it takes some time
210 * to ramp up to maximum frequency. Thus meausrements often incur higher
213 * Number of microseconds.
216 Cycles::sleep(uint64_t us
)
218 uint64_t stop
= Cycles::rdtsc() + Cycles::from_nanoseconds(1000*us
);
219 while (Cycles::rdtsc() < stop
);