MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testCopy.cpp
1 /*
2  Copyright (C) 2003-2006 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 
20 #include <ndb_global.h>
21 #include <NdbOut.hpp>
22 #include <NdbTick.h>
23 
24 #ifdef __NDB_FORTE6
25 #define HAND
26 bool hand = true;
27 #else
28 bool hand = false;
29 #endif
30 
31 struct Data7 {
32  Uint32 data[7];
33 
34 #ifdef HAND
35  inline Data7& operator=(const Data7 & o){
36  Uint32 t0 = o.data[0];
37  Uint32 t1 = o.data[1];
38  Uint32 t2 = o.data[2];
39  Uint32 t3 = o.data[3];
40  Uint32 t4 = o.data[4];
41  Uint32 t5 = o.data[5];
42  Uint32 t6 = o.data[6];
43  data[0] = t0;
44  data[1] = t1;
45  data[2] = t2;
46  data[3] = t3;
47  data[4] = t4;
48  data[5] = t5;
49  data[6] = t6;
50  return * this;
51  }
52 #endif
53 };
54 
55 struct Data25 {
56  Uint32 data[25];
57 };
58 
59 struct TestSignal {
60 
61  Data7 head;
62  Data25 data;
63 };
64 
65 Uint32 g_time = 3000;
66 Uint32 g_count = 8*2048;
67 
68 TestSignal g_signal;
69 TestSignal * g_jobBuffer;
70 
71 template<Uint32 LEN>
72 inline
73 void
74 MEMCOPY(Uint32 * to, const Uint32 * from){
75  Uint32 t0 ;
76  Uint32 t1 ;
77  Uint32 t2 ;
78  Uint32 t3 ;
79  Uint32 len = LEN;
80  while(len > 4){
81  t0 = from[0];
82  t1 = from[1];
83  t2 = from[2];
84  t3 = from[3];
85 
86  to[0] = t0;
87  to[1] = t1;
88  to[2] = t2;
89  to[3] = t3;
90 
91 
92  to += 4;
93  from += 4;
94  len -= 4;
95  }
96 
97  //ndbout_c("len = %d", len);
98 
99  t0 = from[0];
100  t1 = from[1];
101  t2 = from[2];
102  switch(len & 3){
103  case 3:
104  //ndbout_c("3");
105  to[2] = t2;
106  case 2:
107  //ndbout_c("2");
108  to[1] = t1;
109  case 1:
110  //ndbout_c("1");
111  to[0] = t0;
112  }
113 
114 }
115 
116 inline
117 void
118 MEMCOPY_NO_WORDS(Uint32 * to, const Uint32 * from, Uint32 len){
119  Uint32 t0 ;
120  Uint32 t1 ;
121  Uint32 t2 ;
122  Uint32 t3 ;
123  while(len > 4){
124  t0 = from[0];
125  t1 = from[1];
126  t2 = from[2];
127  t3 = from[3];
128 
129  to[0] = t0;
130  to[1] = t1;
131  to[2] = t2;
132  to[3] = t3;
133 
134 
135  to += 4;
136  from += 4;
137  len -= 4;
138  }
139 
140  //ndbout_c("len = %d", len);
141 
142  t0 = from[0];
143  t1 = from[1];
144  t2 = from[2];
145  switch(len & 3){
146  case 3:
147  //ndbout_c("3");
148  to[2] = t2;
149  case 2:
150  //ndbout_c("2");
151  to[1] = t1;
152  case 1:
153  //ndbout_c("1");
154  to[0] = t0;
155  }
156 }
157 
158 inline
159 void
160 copy1(Uint32 i, TestSignal & ts){
161  TestSignal & dst = g_jobBuffer[i];
162 
163  Uint32 t0 = ts.head.data[0];
164  Uint32 t1 = ts.head.data[1];
165  Uint32 t2 = ts.head.data[2];
166  Uint32 t3 = ts.head.data[3];
167  Uint32 t4 = ts.head.data[4];
168  Uint32 t5 = ts.head.data[5];
169  Uint32 t6 = ts.head.data[6];
170 
171  dst.head.data[0] = t0;
172  dst.head.data[1] = t1;
173  dst.head.data[2] = t2;
174  dst.head.data[3] = t3;
175  dst.head.data[4] = t4;
176  dst.head.data[5] = t5;
177  dst.head.data[6] = t6;
178 }
179 
180 
181 
182 inline
183 void
184 copy2(Uint32 i, TestSignal & ts){
185  TestSignal & dst = g_jobBuffer[i];
186 
187  Uint32 t0 = ts.head.data[0];
188  Uint32 t1 = ts.head.data[1];
189  Uint32 t2 = ts.head.data[2];
190  Uint32 t3 = ts.head.data[3];
191 
192  dst.head.data[0] = t0;
193  dst.head.data[1] = t1;
194  dst.head.data[2] = t2;
195  dst.head.data[3] = t3;
196 
197  Uint32 t4 = ts.head.data[4];
198  Uint32 t5 = ts.head.data[5];
199  Uint32 t6 = ts.head.data[6];
200 
201  dst.head.data[4] = t4;
202  dst.head.data[5] = t5;
203  dst.head.data[6] = t6;
204 }
205 
206 inline
207 void
208 copy3(Uint32 i, TestSignal & ts){
209  TestSignal & dst = g_jobBuffer[i];
210 
211  dst.head = ts.head;
212 }
213 
214 inline
215 void
216 copy4(Uint32 i, TestSignal & ts){
217  TestSignal & dst = g_jobBuffer[i];
218 
219  memcpy(&dst.head.data[0], &ts.head.data[0], sizeof(Data7));
220 }
221 
222 inline
223 void
224 copy5(Uint32 i, TestSignal & ts){
225  TestSignal & dst = g_jobBuffer[i];
226 
227  MEMCOPY_NO_WORDS(&dst.head.data[0], &ts.head.data[0], 7);
228 }
229 
230 inline
231 void
232 copy6(Uint32 i, TestSignal & ts){
233  TestSignal & dst = g_jobBuffer[i];
234 
235  MEMCOPY<7>(&dst.head.data[0], &ts.head.data[0]);
236 }
237 
238 inline
239 void
240 copy7(Uint32 i, TestSignal & ts){
241  TestSignal & dst = g_jobBuffer[i];
242 
243 #if (__GNUC__ >= 3 ) || (__GNUC__ == 2 && __GNUC_MINOR >= 95)
244  __builtin_memcpy(&dst.head.data[0], &ts.head.data[0], sizeof(Data7));
245 #else
246  dst.head = ts.head;
247 #endif
248 }
249 
250 template<void (* C)(Uint32 i, TestSignal & ts)>
251 int
252 doTime(Uint32 ms){
253 
254  Uint64 ms1, ms2;
255  const Uint32 count = g_count;
256  for(Uint32 i = 0; i<count; i++)
257  C(i, g_signal);
258  for(Uint32 i = 0; i<count; i++)
259  C(i, g_signal);
260 
261  Uint32 laps = 0;
262 
263  ms1 = NdbTick_CurrentMillisecond();
264  do {
265  for(int j = 100; j>= 0; j--)
266  for(Uint32 i = 0; i<count; i++){
267  C(i, g_signal);
268  }
269  ms2 = NdbTick_CurrentMillisecond();
270  laps += 100;
271  } while((ms2 - ms1) < ms);
272 
273  return laps;
274 }
275 
276 
277 template<void (* C)(Uint32 i, TestSignal & ts)>
278 void doCopyLap(Uint32 laps, const char * title){
279 
280  Uint64 ms1, ms2;
281  const Uint32 count = g_count;
282  for(Uint32 i = 0; i<count; i++)
283  C(i, g_signal);
284  laps--;
285  for(Uint32 i = 0; i<count; i++)
286  C(i, g_signal);
287  laps--;
288 
289  Uint32 div = laps;
290 
291  ms1 = NdbTick_CurrentMillisecond();
292  while(laps > 0){
293  for(Uint32 i = 0; i<count; i++){
294 #if (__GNUC__ == 3 && __GNUC_MINOR >= 1)
295  _builtin_prefetch(&g_jobBuffer[i], 1, 0);
296 #endif
297  C(i, g_signal);
298  }
299  laps--;
300  }
301  ms2 = NdbTick_CurrentMillisecond();
302 
303  ms2 -= ms1;
304  Uint32 diff = ms2;
305  ndbout_c("%s : %d laps in %d millis => %d copies/sec",
306  title, div, diff, (1000*div*g_count+(diff/2))/diff);
307 }
308 
309 int
310 main(int argc, const char ** argv){
311 
312  if(argc > 1)
313  g_count = atoi(argv[1]);
314 
315  if(argc > 2)
316  g_time = atoi(argv[2]);
317 
318  ndbout_c("Using %d entries => %d kB ",
319  g_count,
320  g_count * sizeof(TestSignal) / 1024);
321  ndbout_c("Testing for %d ms", g_time);
322 
323  ndbout_c("Using %s copy-constructor",
324  (hand ? "hand written" : "compiler generated"));
325 
326  g_jobBuffer = new TestSignal[g_count + 1];
327  for(int i = 0; i<10; i++)
328  memset(g_jobBuffer, 0, g_count * sizeof(TestSignal));
329 
330  int laps = doTime<copy2>(g_time);
331  ndbout_c("Laps = %d", laps);
332 
333  doCopyLap<copy2>(laps, "4 t-variables");
334  doCopyLap<copy3>(laps, "copy constr. ");
335  doCopyLap<copy1>(laps, "7 t-variables");
336  doCopyLap<copy4>(laps, "mem copy ");
337  doCopyLap<copy5>(laps, "mem copy hand");
338  doCopyLap<copy6>(laps, "mem copy temp");
339  doCopyLap<copy7>(laps, "mem copy gcc ");
340 
341  delete[] g_jobBuffer;
342  return 0;
343 }