1 /*
2 Copyright (c) 2006, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25
26 #include "ArrayPool.hpp"
27 #include "WOPool.hpp"
28 #include "RWPool.hpp"
29 #include <NdbTick.h>
30 #include "ndbd_malloc_impl.hpp"
31 #include "SimulatedBlock.hpp"
32
33 #ifdef USE_CALLGRIND
34 #include <valgrind/callgrind.h>
35 #else
36 #define CALLGRIND_TOGGLE_COLLECT()
37 #endif
38
39 #define T_TEST_AP (1 << 0)
40 #define T_TEST_WO (1 << 1)
41 #define T_TEST_RW (1 << 2)
42
43 #define T_SEIZE (1 << 0)
44 #define T_RELEASE (1 << 1)
45 #define T_G_RELEASE (1 << 2)
46 #define T_R_RELEASE (1 << 3)
47 #define T_R_G_RELEASE (1 << 4)
48 #define T_MIX (1 << 5)
49 #define T_GETPTR (1 << 6)
50 #define T_FIFO (1 << 7)
51
52 const char *test_names[] = {
53 "seize",
54 "release",
55 "get+rel",
56 "r-rel",
57 "r-get+rel",
58 "mix",
59 "getptr",
60 "fifo",
61 0
62 };
63
64 Uint32 pools = ~0;
65 Uint32 tests = ~0;
66 Uint32 records = ~0;
67 Uint32 sizes = 7;
68 unsigned int seed;
69 Ndbd_mem_manager mm;
70 Configuration cfg;
71 Block_context ctx(cfg, mm);
72 struct BB : public SimulatedBlock
73 {
BBBB74 BB(int no, Block_context& ctx) : SimulatedBlock(no, ctx) {}
75 };
76
77 BB block(DBACC, ctx);
78
79 template <typename T>
80 void
init(ArrayPool<T> & pool,Uint32 cnt)81 init(ArrayPool<T> & pool, Uint32 cnt)
82 {
83 pool.setSize(cnt + 1, true);
84 }
85
86 template <typename T>
87 void
init(RecordPool<T,WOPool> & pool,Uint32 cnt)88 init(RecordPool<T, WOPool> & pool, Uint32 cnt)
89 {
90 Pool_context pc;
91 pc.m_block = █
92 pool.wo_pool_init(0x2001, pc);
93 }
94
95 template <typename T>
96 void
init(RecordPool<T,RWPool> & pool,Uint32 cnt)97 init(RecordPool<T, RWPool> & pool, Uint32 cnt)
98 {
99 Pool_context pc;
100 pc.m_block = █
101 pool.init(0x2001, pc);
102 }
103
104 template <typename T, typename R>
105 void
test_pool(R & pool,Uint32 cnt,Uint32 loops)106 test_pool(R& pool, Uint32 cnt, Uint32 loops)
107 {
108 Ptr<T> ptr;
109 Uint32 *arr = (Uint32*)alloca(cnt * sizeof(Uint32));
110 memset(arr, 0, cnt * sizeof(Uint32));
111 if (tests & T_SEIZE)
112 {
113 Uint64 sum = 0;
114 for(Uint32 i = 0; i<loops; i++)
115 { // seize
116 Uint64 start = NdbTick_CurrentMillisecond();
117 CALLGRIND_TOGGLE_COLLECT();
118 for(Uint32 j = 0; j<cnt; j++)
119 {
120 bool b = pool.seize(ptr);
121 arr[j] = ptr.i;
122 ptr.p->do_stuff();
123 assert(b);
124 }
125 CALLGRIND_TOGGLE_COLLECT();
126 Uint64 stop = NdbTick_CurrentMillisecond();
127
128 for(Uint32 j = 0; j<cnt; j++)
129 {
130 ptr.i = arr[j];
131 pool.getPtr(ptr);
132 ptr.p->do_stuff();
133 pool.release(ptr.i);
134 arr[j] = RNIL;
135 }
136 sum += (stop - start);
137 }
138 printf(" ; %lld", sum); fflush(stdout);
139 }
140
141 if (tests & T_RELEASE)
142 { // release
143 Uint64 sum = 0;
144 for(Uint32 i = 0; i<loops; i++)
145 {
146 for(Uint32 j = 0; j<cnt; j++)
147 {
148 bool b = pool.seize(ptr);
149 arr[j] = ptr.i;
150 ptr.p->do_stuff();
151 }
152
153 Uint64 start = NdbTick_CurrentMillisecond();
154 CALLGRIND_TOGGLE_COLLECT();
155 for(Uint32 j = 0; j<cnt; j++)
156 {
157 pool.release(arr[j]);
158 arr[j] = RNIL;
159 }
160 CALLGRIND_TOGGLE_COLLECT();
161 Uint64 stop = NdbTick_CurrentMillisecond();
162
163 sum += (stop - start);
164 }
165 printf(" ; %lld", sum); fflush(stdout);
166 }
167
168 if (tests & T_G_RELEASE)
169 { // getptr + release
170 Uint64 sum = 0;
171 for(Uint32 i = 0; i<loops; i++)
172 {
173 for(Uint32 j = 0; j<cnt; j++)
174 {
175 bool b = pool.seize(ptr);
176 arr[j] = ptr.i;
177 ptr.p->do_stuff();
178 }
179
180 Uint64 start = NdbTick_CurrentMillisecond();
181 CALLGRIND_TOGGLE_COLLECT();
182 for(Uint32 j = 0; j<cnt; j++)
183 {
184 pool.getPtr(ptr, arr[j]);
185 ptr.p->do_stuff();
186 pool.release(ptr);
187 arr[j] = RNIL;
188 }
189 CALLGRIND_TOGGLE_COLLECT();
190 Uint64 stop = NdbTick_CurrentMillisecond();
191
192 sum += (stop - start);
193 }
194 printf(" ; %lld", sum); fflush(stdout);
195 }
196
197 if (tests & T_R_RELEASE)
198 { // release reverse
199 Uint64 sum = 0;
200 for(Uint32 i = 0; i<loops; i++)
201 {
202 for(Uint32 j = 0; j<cnt; j++)
203 {
204 bool b = pool.seize(ptr);
205 arr[j] = ptr.i;
206 ptr.p->do_stuff();
207 }
208
209 Uint64 start = NdbTick_CurrentMillisecond();
210 CALLGRIND_TOGGLE_COLLECT();
211 for(Uint32 j = 0; j<cnt; j++)
212 {
213 pool.release(arr[cnt - j - 1]);
214 arr[cnt - j - 1] = RNIL;
215 }
216 CALLGRIND_TOGGLE_COLLECT();
217 Uint64 stop = NdbTick_CurrentMillisecond();
218
219 sum += (stop - start);
220 }
221 printf(" ; %lld", sum); fflush(stdout);
222 }
223
224 if (tests & T_R_G_RELEASE)
225 { // getptr + release
226 Uint64 sum = 0;
227 for(Uint32 i = 0; i<loops; i++)
228 {
229 for(Uint32 j = 0; j<cnt; j++)
230 {
231 bool b = pool.seize(ptr);
232 arr[j] = ptr.i;
233 ptr.p->do_stuff();
234 }
235
236 Uint64 start = NdbTick_CurrentMillisecond();
237 CALLGRIND_TOGGLE_COLLECT();
238 for(Uint32 j = 0; j<cnt; j++)
239 {
240 pool.getPtr(ptr, arr[cnt - j - 1]);
241 ptr.p->do_stuff();
242 pool.release(ptr);
243 arr[cnt - j - 1] = RNIL;
244 }
245 CALLGRIND_TOGGLE_COLLECT();
246 Uint64 stop = NdbTick_CurrentMillisecond();
247
248 sum += (stop - start);
249 }
250 printf(" ; %lld", sum); fflush(stdout);
251 }
252
253 if (tests & T_MIX)
254 {
255 Uint64 sum = 0;
256 Uint64 start = NdbTick_CurrentMillisecond();
257 Uint32 lseed = seed;
258 CALLGRIND_TOGGLE_COLLECT();
259 for(Uint32 i = 0; i<loops * cnt; i++)
260 {
261 int pos = rand_r(&lseed) % cnt;
262 ptr.i = arr[pos];
263 if (ptr.i == RNIL)
264 {
265 pool.seize(ptr);
266 arr[pos] = ptr.i;
267 assert(ptr.i != RNIL);
268 ptr.p->do_stuff();
269 }
270 else
271 {
272 pool.getPtr(ptr);
273 ptr.p->do_stuff();
274 pool.release(ptr);
275 arr[pos] = RNIL;
276 }
277 }
278 CALLGRIND_TOGGLE_COLLECT();
279 Uint64 stop = NdbTick_CurrentMillisecond();
280
281 for(Uint32 j = 0; j<cnt; j++)
282 {
283 ptr.i = arr[j];
284 if (ptr.i != RNIL)
285 {
286 pool.getPtr(ptr);
287 pool.release(ptr.i);
288 }
289 arr[j] = RNIL;
290 }
291
292 sum += (stop - start);
293 printf(" ; %lld", sum); fflush(stdout);
294 }
295
296 if (tests & T_GETPTR)
297 {
298 Uint32 lseed = seed;
299 for(Uint32 j = 0; j<cnt; j++)
300 {
301 bool b = pool.seize(ptr);
302 arr[j] = ptr.i;
303 ptr.p->do_stuff();
304 assert(b);
305 }
306
307 Uint64 sum = 0;
308 Uint64 start = NdbTick_CurrentMillisecond();
309 CALLGRIND_TOGGLE_COLLECT();
310 for(Uint32 i = 0; i<loops * cnt; i++)
311 {
312 int pos = rand_r(&lseed) % cnt;
313 ptr.i = arr[pos];
314 pool.getPtr(ptr);
315 ptr.p->do_stuff();
316 }
317 CALLGRIND_TOGGLE_COLLECT();
318 Uint64 stop = NdbTick_CurrentMillisecond();
319
320 for(Uint32 j = 0; j<cnt; j++)
321 {
322 ptr.i = arr[j];
323 pool.getPtr(ptr);
324 ptr.p->do_stuff();
325 pool.release(ptr.i);
326 arr[j] = RNIL;
327 }
328
329 sum += (stop - start);
330 printf(" ; %lld", sum); fflush(stdout);
331 }
332
333 if (tests & T_FIFO)
334 { // fifo
335 Uint64 sum = 0;
336 Uint64 start = NdbTick_CurrentMillisecond();
337 CALLGRIND_TOGGLE_COLLECT();
338 for(Uint32 i = 0; i<loops; i++)
339 {
340 Uint32 head = RNIL;
341 Uint32 last = RNIL;
342
343 Uint64 sum = 0;
344 for(Uint32 j = 0; j<cnt; j++)
345 {
346 pool.seize(ptr);
347 ptr.p->do_stuff();
348 ptr.p->m_nextList = RNIL;
349 if (head == RNIL)
350 {
351 head = ptr.i;
352 }
353 else
354 {
355 T* t = pool.getPtr(last);
356 t->m_nextList = ptr.i;
357 }
358 last = ptr.i;
359 }
360
361 while (head != RNIL)
362 {
363 pool.getPtr(ptr, head);
364 ptr.p->do_stuff();
365 head = ptr.p->m_nextList;
366 pool.release(ptr);
367 }
368 }
369 CALLGRIND_TOGGLE_COLLECT();
370 Uint64 stop = NdbTick_CurrentMillisecond();
371 sum += (stop - start);
372 printf(" ; %lld", sum); fflush(stdout);
373 }
374
375 ndbout_c("");
376 }
377
378 template <Uint32 sz>
379 struct Rec {
380 Uint32 m_data;
381 Uint32 m_magic;
382 Uint32 nextPool;
383 Uint32 m_nextList;
384 char m_cdata[sz-16];
385
do_stuffRec386 void do_stuff() {
387 Uint32 sum = 0;
388 Uint32 *ptr = (Uint32*)this;
389 for(Uint32 i = 0; i<(sz >> 2); i++)
390 sum += * ptr ++;
391 m_data = sum;
392 }
393 };
394
395 typedef Rec<32> Rec32;
396 typedef Rec<36> Rec36;
397 typedef Rec<56> Rec56;
398 typedef Rec<224> Rec224;
399
400 template <typename T>
test_ap(Uint32 cnt,Uint32 loop)401 void test_ap(Uint32 cnt, Uint32 loop)
402 {
403 printf("AP ; %d ; %d", sizeof(T), (cnt * sizeof(T))>>10); fflush(stdout);
404 ArrayPool<T> pool;
405 init(pool, cnt);
406 test_pool<T, ArrayPool<T> >(pool, cnt, loop);
407 }
408
409 template <typename T>
test_rw(Uint32 cnt,Uint32 loop)410 void test_rw(Uint32 cnt, Uint32 loop)
411 {
412 printf("RW ; %d ; %d", sizeof(T), (cnt * sizeof(T))>>10); fflush(stdout);
413 RecordPool<T, RWPool> pool;
414 init(pool, cnt);
415 test_pool<T, RecordPool<T, RWPool> >(pool, cnt, loop);
416 }
417
418 template <typename T>
test_wo(Uint32 cnt,Uint32 loop)419 void test_wo(Uint32 cnt, Uint32 loop)
420 {
421 printf("WO ; %d ; %d", sizeof(T), (cnt * sizeof(T))>>10); fflush(stdout);
422 RecordPool<T, WOPool> pool;
423 init(pool, cnt);
424 test_pool<T, RecordPool<T, WOPool> >(pool, cnt, loop);
425 }
426
427 #include <EventLogger.hpp>
428 extern EventLogger * g_eventLogger;
429
430 int
main(int argc,char ** argv)431 main(int argc, char **argv)
432 {
433 Uint32 loops = 300000;
434 for (Uint32 i = 1 ; i<argc ; i++)
435 {
436 if (argc > i+1 && strcmp(argv[i], "-pools") == 0)
437 {
438 pools = 0;
439 for (Uint32 j = 0; j<strlen(argv[i+1]); j++)
440 {
441 char c = argv[i+1][j];
442 if (c >= '0' && c <= '9')
443 pools |= 1 << (c - '0');
444 else
445 pools |= 1 << (10 + (c - 'a'));
446 }
447 }
448 else if (argc > i+1 && strcmp(argv[i], "-tests") == 0)
449 {
450 tests = 0;
451 for (Uint32 j = 0; j<strlen(argv[i+1]); j++)
452 {
453 char c = argv[i+1][j];
454 if (c >= '0' && c <= '9')
455 tests |= 1 << (c - '0');
456 else
457 tests |= 1 << (10 + (c - 'a'));
458 }
459 }
460 else if (argc > i+1 && strcmp(argv[i], "-sizes") == 0)
461 {
462 sizes = 0;
463 for (Uint32 j = 0; j<strlen(argv[i+1]); j++)
464 {
465 char c = argv[i+1][j];
466 if (c >= '0' && c <= '9')
467 sizes |= 1 << (c - '0');
468 else
469 sizes |= 1 << (10 + (c - 'a'));
470 }
471 }
472 else if (argc > i+1 && strcmp(argv[i], "-records") == 0)
473 {
474 records = 0;
475 for (Uint32 j = 0; j<strlen(argv[i+1]); j++)
476 {
477 char c = argv[i+1][j];
478 if (c >= '0' && c <= '9')
479 records |= 1 << (c - '0');
480 else
481 records |= 1 << (10 + (c - 'a'));
482 }
483 }
484 else if (argc > i+1 && strcmp(argv[i], "-loop") == 0)
485 {
486 loops = atoi(argv[i+1]);
487 }
488 }
489
490 Resource_limit rl;
491 rl.m_min = 0;
492 rl.m_max = 10000;
493 rl.m_resource_id = 0;
494 mm.set_resource_limit(rl);
495 if(!mm.init())
496 {
497 abort();
498 }
499
500 seed = time(0);
501 Uint32 sz = 0;
502 Uint32 cnt = 256;
503
504 printf("pool ; rs ; ws");
505 for (Uint32 i = 0; test_names[i] && i<31; i++)
506 if (tests & (1 << i))
507 printf(" ; %s", test_names[i]);
508 ndbout_c("");
509
510 while(cnt <= 1000000)
511 {
512 Uint32 loop = 768 * loops / cnt;
513 if (sizes & (1 << sz))
514 {
515 if (records & 1)
516 {
517 if (pools & T_TEST_AP)
518 test_ap<Rec32>(cnt, loop);
519 if (pools & T_TEST_WO)
520 test_wo<Rec32>(cnt, loop);
521 if (pools & T_TEST_RW)
522 test_rw<Rec32>(cnt, loop);
523 }
524 if (records & 2)
525 {
526 if (pools & T_TEST_AP)
527 test_ap<Rec36>(cnt, loop);
528 if (pools & T_TEST_WO)
529 test_wo<Rec36>(cnt, loop);
530 if (pools & T_TEST_RW)
531 test_rw<Rec36>(cnt, loop);
532 }
533 if (records & 4)
534 {
535 if (pools & T_TEST_AP)
536 test_ap<Rec56>(cnt, loop);
537 if (pools & T_TEST_WO)
538 test_wo<Rec56>(cnt, loop);
539 if (pools & T_TEST_RW)
540 test_rw<Rec56>(cnt, loop);
541 }
542 if (records & 8)
543 {
544 if (pools & T_TEST_AP)
545 test_ap<Rec224>(cnt, loop);
546 if (pools & T_TEST_WO)
547 test_wo<Rec224>(cnt, loop);
548 if (pools & T_TEST_RW)
549 test_rw<Rec224>(cnt, loop);
550 }
551 }
552
553 cnt += (512 << sz);
554 sz++;
555 }
556 }
557
558 Uint32 g_currentStartPhase;
559 Uint32 g_start_type;
560 NdbNodeBitmask g_nowait_nodes;
561
562 void
sendCmAppChg(Ndbcntr & cntr,Signal * signal,Uint32 startLevel)563 UpgradeStartup::sendCmAppChg(Ndbcntr& cntr, Signal* signal, Uint32 startLevel){
564 }
565
566 void
execCM_APPCHG(SimulatedBlock & block,Signal * signal)567 UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){
568 }
569
570 void
sendCntrMasterReq(Ndbcntr & cntr,Signal * signal,Uint32 n)571 UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){
572 }
573
574 void
execCNTR_MASTER_REPLY(SimulatedBlock & block,Signal * signal)575 UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){
576 }
577
578 #include <SimBlockList.hpp>
579
580 #define JAM_FILE_ID 267
581
582
583 void
unload()584 SimBlockList::unload()
585 {
586
587 }
588
589 #define INSTANCE(X) \
590 template void test_ap<X>(unsigned, unsigned);\
591 template void test_wo<X>(unsigned, unsigned);\
592 template void test_rw<X>(unsigned, unsigned);\
593 template void test_pool<X, ArrayPool<X> >(ArrayPool<X>&, unsigned, unsigned);\
594 template void test_pool<X, RecordPool<X, RWPool> >(RecordPool<X, RWPool>&, unsigned, unsigned); \
595 template void test_pool<X, RecordPool<X, WOPool> >(RecordPool<X, WOPool>&, unsigned, unsigned);\
596 template void init<X>(ArrayPool<X>&, unsigned);\
597 template void init<X>(RecordPool<X, RWPool>&, unsigned);\
598 template void init<X>(RecordPool<X, WOPool>&, unsigned)
599
600 INSTANCE(Rec32);
601 INSTANCE(Rec36);
602 INSTANCE(Rec56);
603 INSTANCE(Rec224);
604
605