MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pfs_timer.cc
Go to the documentation of this file.
1 /* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
21 #include "my_global.h"
22 #include "pfs_timer.h"
23 #include "my_rdtsc.h"
24 
25 enum_timer_name idle_timer= TIMER_NAME_MICROSEC;
26 enum_timer_name wait_timer= TIMER_NAME_CYCLE;
27 enum_timer_name stage_timer= TIMER_NAME_NANOSEC;
28 enum_timer_name statement_timer= TIMER_NAME_NANOSEC;
30 
31 static ulonglong cycle_v0;
32 static ulonglong nanosec_v0;
33 static ulonglong microsec_v0;
34 static ulonglong millisec_v0;
35 static ulonglong tick_v0;
36 
37 static ulong cycle_to_pico; /* 1000 at 1 GHz, 333 at 3GHz, 250 at 4GHz */
38 static ulong nanosec_to_pico; /* In theory, 1 000 */
39 static ulong microsec_to_pico; /* In theory, 1 000 000 */
40 static ulong millisec_to_pico; /* In theory, 1 000 000 000, fits in uint32 */
41 static ulonglong tick_to_pico; /* 1e10 at 100 Hz, 1.666e10 at 60 Hz */
42 
43 /* Indexed by enum enum_timer_name */
44 static struct time_normalizer to_pico_data[FIRST_TIMER_NAME + COUNT_TIMER_NAME]=
45 {
46  { 0, 0}, /* unused */
47  { 0, 0}, /* cycle */
48  { 0, 0}, /* nanosec */
49  { 0, 0}, /* microsec */
50  { 0, 0}, /* millisec */
51  { 0, 0} /* tick */
52 };
53 
54 static inline ulong round_to_ulong(double value)
55 {
56  return (ulong) (value + 0.5);
57 }
58 
59 static inline ulonglong round_to_ulonglong(double value)
60 {
61  return (ulonglong) (value + 0.5);
62 }
63 
64 void init_timers(void)
65 {
66  double pico_frequency= 1.0e12;
67 
68  my_timer_init(&pfs_timer_info);
69 
70  cycle_v0= my_timer_cycles();
71  nanosec_v0= my_timer_nanoseconds();
72  microsec_v0= my_timer_microseconds();
73  millisec_v0= my_timer_milliseconds();
74  tick_v0= my_timer_ticks();
75 
76  if (pfs_timer_info.cycles.frequency > 0)
77  cycle_to_pico= round_to_ulong(pico_frequency/
78  (double)pfs_timer_info.cycles.frequency);
79  else
80  cycle_to_pico= 0;
81 
82  if (pfs_timer_info.nanoseconds.frequency > 0)
83  nanosec_to_pico= round_to_ulong(pico_frequency/
84  (double)pfs_timer_info.nanoseconds.frequency);
85  else
86  nanosec_to_pico= 0;
87 
88  if (pfs_timer_info.microseconds.frequency > 0)
89  microsec_to_pico= round_to_ulong(pico_frequency/
90  (double)pfs_timer_info.microseconds.frequency);
91  else
92  microsec_to_pico= 0;
93 
94  if (pfs_timer_info.milliseconds.frequency > 0)
95  millisec_to_pico= round_to_ulong(pico_frequency/
96  (double)pfs_timer_info.milliseconds.frequency);
97  else
98  millisec_to_pico= 0;
99 
100  if (pfs_timer_info.ticks.frequency > 0)
101  tick_to_pico= round_to_ulonglong(pico_frequency/
102  (double)pfs_timer_info.ticks.frequency);
103  else
104  tick_to_pico= 0;
105 
106  to_pico_data[TIMER_NAME_CYCLE].m_v0= cycle_v0;
107  to_pico_data[TIMER_NAME_CYCLE].m_factor= cycle_to_pico;
108 
109  to_pico_data[TIMER_NAME_NANOSEC].m_v0= nanosec_v0;
110  to_pico_data[TIMER_NAME_NANOSEC].m_factor= nanosec_to_pico;
111 
112  to_pico_data[TIMER_NAME_MICROSEC].m_v0= microsec_v0;
113  to_pico_data[TIMER_NAME_MICROSEC].m_factor= microsec_to_pico;
114 
115  to_pico_data[TIMER_NAME_MILLISEC].m_v0= millisec_v0;
116  to_pico_data[TIMER_NAME_MILLISEC].m_factor= millisec_to_pico;
117 
118  to_pico_data[TIMER_NAME_TICK].m_v0= tick_v0;
119  to_pico_data[TIMER_NAME_TICK].m_factor= tick_to_pico;
120 
121  /*
122  Depending on the platform and build options,
123  some timers may not be available.
124  Pick best replacements.
125  */
126 
127  /*
128  For STAGE and STATEMENT, a timer with a fixed frequency is better.
129  The prefered timer is nanosecond, or lower resolutions.
130  */
131 
132  if (nanosec_to_pico != 0)
133  {
134  /* Normal case. */
135  stage_timer= TIMER_NAME_NANOSEC;
136  statement_timer= TIMER_NAME_NANOSEC;
137  }
138  else if (microsec_to_pico != 0)
139  {
140  /* Windows. */
141  stage_timer= TIMER_NAME_MICROSEC;
142  statement_timer= TIMER_NAME_MICROSEC;
143  }
144  else if (millisec_to_pico != 0)
145  {
146  /* Robustness, no known cases. */
147  stage_timer= TIMER_NAME_MILLISEC;
148  statement_timer= TIMER_NAME_MILLISEC;
149  }
150  else if (tick_to_pico != 0)
151  {
152  /* Robustness, no known cases. */
153  stage_timer= TIMER_NAME_TICK;
154  statement_timer= TIMER_NAME_TICK;
155  }
156  else
157  {
158  /* Robustness, no known cases. */
159  stage_timer= TIMER_NAME_CYCLE;
160  statement_timer= TIMER_NAME_CYCLE;
161  }
162 
163  /*
164  For IDLE, a timer with a fixed frequency is critical,
165  as the CPU clock may slow down a lot if the server is completely idle.
166  The prefered timer is microsecond, or lower resolutions.
167  */
168 
169  if (microsec_to_pico != 0)
170  {
171  /* Normal case. */
172  idle_timer= TIMER_NAME_MICROSEC;
173  }
174  else if (millisec_to_pico != 0)
175  {
176  /* Robustness, no known cases. */
177  idle_timer= TIMER_NAME_MILLISEC;
178  }
179  else if (tick_to_pico != 0)
180  {
181  /* Robustness, no known cases. */
182  idle_timer= TIMER_NAME_TICK;
183  }
184  else
185  {
186  /* Robustness, no known cases. */
187  idle_timer= TIMER_NAME_CYCLE;
188  }
189 }
190 
192 {
193  switch (timer_name)
194  {
195  case TIMER_NAME_CYCLE:
196  return my_timer_cycles();
197  case TIMER_NAME_NANOSEC:
198  return my_timer_nanoseconds();
199  case TIMER_NAME_MICROSEC:
200  return my_timer_microseconds();
201  case TIMER_NAME_MILLISEC:
202  return my_timer_milliseconds();
203  case TIMER_NAME_TICK:
204  return my_timer_ticks();
205  default:
206  DBUG_ASSERT(false);
207  }
208  return 0;
209 }
210 
212 {
213  switch (timer_name)
214  {
215  case TIMER_NAME_CYCLE:
216  *fct= my_timer_cycles;
217  return my_timer_cycles();
218  case TIMER_NAME_NANOSEC:
219  *fct= my_timer_nanoseconds;
220  return my_timer_nanoseconds();
221  case TIMER_NAME_MICROSEC:
222  *fct= my_timer_microseconds;
223  return my_timer_microseconds();
224  case TIMER_NAME_MILLISEC:
225  *fct= my_timer_milliseconds;
226  return my_timer_milliseconds();
227  case TIMER_NAME_TICK:
228  *fct= my_timer_ticks;
229  return my_timer_ticks();
230  default:
231  *fct= NULL;
232  DBUG_ASSERT(false);
233  }
234  return 0;
235 }
236 
238 {
239  ulonglong result;
240 
241  switch (timer_name)
242  {
243  case TIMER_NAME_CYCLE:
244  result= (my_timer_cycles() - cycle_v0) * cycle_to_pico;
245  break;
246  case TIMER_NAME_NANOSEC:
247  result= (my_timer_nanoseconds() - nanosec_v0) * nanosec_to_pico;
248  break;
249  case TIMER_NAME_MICROSEC:
250  result= (my_timer_microseconds() - microsec_v0) * microsec_to_pico;
251  break;
252  case TIMER_NAME_MILLISEC:
253  result= (my_timer_milliseconds() - millisec_v0) * millisec_to_pico;
254  break;
255  case TIMER_NAME_TICK:
256  result= (my_timer_ticks() - tick_v0) * tick_to_pico;
257  break;
258  default:
259  result= 0;
260  DBUG_ASSERT(false);
261  }
262  return result;
263 }
264 
266 {
267  uint index= static_cast<uint> (timer_name);
268 
269  DBUG_ASSERT(index >= FIRST_TIMER_NAME);
270  DBUG_ASSERT(index <= LAST_TIMER_NAME);
271 
272  return & to_pico_data[index];
273 }
274 
275 void time_normalizer::to_pico(ulonglong start, ulonglong end,
276  ulonglong *pico_start, ulonglong *pico_end, ulonglong *pico_wait)
277 {
278  if (start == 0)
279  {
280  *pico_start= 0;
281  *pico_end= 0;
282  *pico_wait= 0;
283  }
284  else
285  {
286  *pico_start= (start - m_v0) * m_factor;
287  if (end == 0)
288  {
289  *pico_end= 0;
290  *pico_wait= 0;
291  }
292  else
293  {
294  *pico_end= (end - m_v0) * m_factor;
295  *pico_wait= (end - start) * m_factor;
296  }
297  }
298 }
299