1 /* Copyright (c) 2009, 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, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23
24 /*
25 rdtsc3 -- multi-platform timer code
26 pgulutzan@mysql.com, 2005-08-29
27 modified 2008-11-02
28
29 When you run rdtsc3, it will print the contents of
30 "my_timer_info". The display indicates
31 what timer routine is best for a given platform.
32
33 For example, this is the display on production.mysql.com,
34 a 2.8GHz Xeon with Linux 2.6.17, gcc 3.3.3:
35
36 cycles nanoseconds microseconds milliseconds ticks
37 ------------- ------------- ------------- ------------- -------------
38 1 11 13 18 17
39 2815019607 1000000000 1000000 1049 102
40 1 1000 1 1 1
41 88 4116 3888 4092 2044
42
43 The first line shows routines, e.g. 1 = MY_TIMER_ROUTINE_ASM_X86.
44 The second line shows frequencies, e.g. 2815019607 is nearly 2.8GHz.
45 The third line shows resolutions, e.g. 1000 = very poor resolution.
46 The fourth line shows overheads, e.g. ticks takes 2044 cycles.
47 */
48
49 // First include (the generated) my_config.h, to get correct platform defines.
50 #include "my_config.h"
51 #include <gtest/gtest.h>
52
53 #include "my_global.h"
54 #include "my_rdtsc.h"
55
56 namespace mysys_my_rdtsc_unittest {
57
58 const int LOOP_COUNT= 100;
59
60 class RDTimeStampCounter : public ::testing::Test
61 {
62 protected:
SetUp()63 void SetUp()
64 {
65 test_init();
66 }
67 void test_init();
68
69 MY_TIMER_INFO myt;
70 };
71
72
test_init()73 void RDTimeStampCounter::test_init()
74 {
75 my_timer_init(&myt);
76
77 /*
78 diag("----- Routine ---------------");
79 diag("myt.cycles.routine : %13llu", myt.cycles.routine);
80 diag("myt.nanoseconds.routine : %13llu", myt.nanoseconds.routine);
81 diag("myt.microseconds.routine : %13llu", myt.microseconds.routine);
82 diag("myt.milliseconds.routine : %13llu", myt.milliseconds.routine);
83 diag("myt.ticks.routine : %13llu", myt.ticks.routine);
84
85 diag("----- Frequency -------------");
86 diag("myt.cycles.frequency : %13llu", myt.cycles.frequency);
87 diag("myt.nanoseconds.frequency : %13llu", myt.nanoseconds.frequency);
88 diag("myt.microseconds.frequency : %13llu", myt.microseconds.frequency);
89 diag("myt.milliseconds.frequency : %13llu", myt.milliseconds.frequency);
90 diag("myt.ticks.frequency : %13llu", myt.ticks.frequency);
91
92 diag("----- Resolution ------------");
93 diag("myt.cycles.resolution : %13llu", myt.cycles.resolution);
94 diag("myt.nanoseconds.resolution : %13llu", myt.nanoseconds.resolution);
95 diag("myt.microseconds.resolution : %13llu", myt.microseconds.resolution);
96 diag("myt.milliseconds.resolution : %13llu", myt.milliseconds.resolution);
97 diag("myt.ticks.resolution : %13llu", myt.ticks.resolution);
98
99 diag("----- Overhead --------------");
100 diag("myt.cycles.overhead : %13llu", myt.cycles.overhead);
101 diag("myt.nanoseconds.overhead : %13llu", myt.nanoseconds.overhead);
102 diag("myt.microseconds.overhead : %13llu", myt.microseconds.overhead);
103 diag("myt.milliseconds.overhead : %13llu", myt.milliseconds.overhead);
104 diag("myt.ticks.overhead : %13llu", myt.ticks.overhead);
105 */
106 }
107
108
TEST_F(RDTimeStampCounter,TestCycle)109 TEST_F(RDTimeStampCounter, TestCycle)
110 {
111 ulonglong t1= my_timer_cycles();
112 ulonglong t2;
113 int i;
114 int backward= 0;
115 int nonzero= 0;
116
117 for (i=0 ; i < LOOP_COUNT ; i++)
118 {
119 t2= my_timer_cycles();
120 if (t1 >= t2)
121 backward++;
122 if (t2 != 0)
123 nonzero++;
124 t1= t2;
125 }
126
127 /* Expect at most 1 backward, the cycle value can overflow */
128 EXPECT_TRUE((backward <= 1)) << "The cycle timer is strictly increasing";
129
130 if (myt.cycles.routine != 0)
131 EXPECT_TRUE((nonzero != 0)) << "The cycle timer is implemented";
132 else
133 EXPECT_TRUE((nonzero == 0))
134 << "The cycle timer is not implemented and returns 0";
135 }
136
137
TEST_F(RDTimeStampCounter,TestNanosecond)138 TEST_F(RDTimeStampCounter, TestNanosecond)
139 {
140 ulonglong t1= my_timer_nanoseconds();
141 ulonglong t2;
142 int i;
143 int backward= 0;
144 int nonzero= 0;
145
146 for (i=0 ; i < LOOP_COUNT ; i++)
147 {
148 t2= my_timer_nanoseconds();
149 if (t1 > t2)
150 backward++;
151 if (t2 != 0)
152 nonzero++;
153 t1= t2;
154 }
155
156 EXPECT_TRUE((backward == 0)) << "The nanosecond timer is increasing";
157
158 if (myt.nanoseconds.routine != 0)
159 EXPECT_TRUE((nonzero != 0)) << "The nanosecond timer is implemented";
160 else
161 EXPECT_TRUE((nonzero == 0))
162 << "The nanosecond timer is not implemented and returns 0";
163 }
164
165
TEST_F(RDTimeStampCounter,TestMicrosecond)166 TEST_F(RDTimeStampCounter, TestMicrosecond)
167 {
168 ulonglong t1= my_timer_microseconds();
169 ulonglong t2;
170 int i;
171 int backward= 0;
172 int nonzero= 0;
173
174 for (i=0 ; i < LOOP_COUNT ; i++)
175 {
176 t2= my_timer_microseconds();
177 if (t1 > t2)
178 backward++;
179 if (t2 != 0)
180 nonzero++;
181 t1= t2;
182 }
183
184 EXPECT_TRUE((backward == 0)) << "The microsecond timer is increasing";
185
186 if (myt.microseconds.routine != 0)
187 EXPECT_TRUE((nonzero != 0)) << "The microsecond timer is implemented";
188 else
189 EXPECT_TRUE((nonzero == 0))
190 << "The microsecond timer is not implemented and returns 0";
191 }
192
193
TEST_F(RDTimeStampCounter,TestMillisecond)194 TEST_F(RDTimeStampCounter, TestMillisecond)
195 {
196 ulonglong t1= my_timer_milliseconds();
197 ulonglong t2;
198 int i;
199 int backward= 0;
200 int nonzero= 0;
201
202 for (i=0 ; i < LOOP_COUNT ; i++)
203 {
204 t2= my_timer_milliseconds();
205 if (t1 > t2)
206 backward++;
207 if (t2 != 0)
208 nonzero++;
209 t1= t2;
210 }
211
212 EXPECT_TRUE((backward == 0)) << "The millisecond timer is increasing";
213
214 if (myt.milliseconds.routine != 0)
215 EXPECT_TRUE((nonzero != 0)) << "The millisecond timer is implemented";
216 else
217 EXPECT_TRUE((nonzero == 0))
218 << "The millisecond timer is not implemented and returns 0";
219 }
220
221
TEST_F(RDTimeStampCounter,TestTick)222 TEST_F(RDTimeStampCounter, TestTick)
223 {
224 ulonglong t1= my_timer_ticks();
225 ulonglong t2;
226 int i;
227 int backward= 0;
228 int nonzero= 0;
229
230 for (i=0 ; i < LOOP_COUNT ; i++)
231 {
232 t2= my_timer_ticks();
233 if (t1 > t2)
234 backward++;
235 if (t2 != 0)
236 nonzero++;
237 t1= t2;
238 }
239
240 EXPECT_TRUE((backward == 0)) << "The tick timer is increasing";
241
242 if (myt.ticks.routine != 0)
243 EXPECT_TRUE((nonzero != 0)) << "The tick timer is implemented";
244 else
245 EXPECT_TRUE((nonzero == 0))
246 << "The tick timer is not implemented and returns 0";
247 }
248
249
250 }
251