1 /* Copyright (c) 2003, 2006, 2007 MySQL AB
2 Use is subject to license terms
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 as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17 #include "DynArr256.hpp"
18 #include <stdio.h>
19 #include <assert.h>
20 #include <NdbOut.hpp>
21
22 #define DA256_BITS 5
23 #define DA256_MASK 31
24
25 struct DA256CL
26 {
27 Uint32 m_magic;
28 Uint32 m_data[15];
29 };
30
31 struct DA256Free
32 {
33 Uint32 m_magic;
34 Uint32 m_next_free;
35 };
36
37 struct DA256Node
38 {
39 struct DA256CL m_lines[17];
40 };
41
42 struct DA256Page
43 {
44 struct DA256CL m_header[2];
45 struct DA256Node m_nodes[30];
46 };
47
48 #define require(x) require_impl(x, __LINE__)
49 //#define DA256_USE_PX
50 //#define DA256_USE_PREFETCH
51 #define DA256_EXTRA_SAFE
52
53
54 #ifdef UNIT_TEST
55 #ifdef USE_CALLGRIND
56 #include <valgrind/callgrind.h>
57 #else
58 #define CALLGRIND_TOGGLE_COLLECT()
59 #endif
60 Uint32 allocatedpages = 0;
61 Uint32 allocatednodes = 0;
62 Uint32 releasednodes = 0;
63 #endif
64
65 inline
66 void
require_impl(bool x,int line)67 require_impl(bool x, int line)
68 {
69 if (!x)
70 {
71 ndbout_c("LINE: %d", line);
72 abort();
73 }
74 }
75
DynArr256Pool()76 DynArr256Pool::DynArr256Pool()
77 {
78 m_type_id = RNIL;
79 m_first_free = RNIL;
80 m_memroot = 0;
81 }
82
83 void
init(Uint32 type_id,const Pool_context & pc)84 DynArr256Pool::init(Uint32 type_id, const Pool_context & pc)
85 {
86 m_ctx = pc;
87 m_type_id = type_id;
88 m_memroot = (DA256Page*)m_ctx.get_memroot();
89 }
90
91 static const Uint32 g_max_sizes[5] = { 0, 256, 65536, 16777216, ~0 };
92
93 /**
94 * sz = 0 = 1 - 0 level
95 * sz = 1 = 256^1 - 1 level
96 * sz = 2 = 256^2 - 2 level
97 * sz = 3 = 256^3 - 3 level
98 * sz = 4 = 256^4 - 4 level
99 */
100 Uint32 *
get(Uint32 pos) const101 DynArr256::get(Uint32 pos) const
102 {
103 Uint32 sz = m_head.m_sz;
104 Uint32 ptrI = m_head.m_ptr_i;
105 DA256Page * memroot = m_pool.m_memroot;
106 Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
107
108 if (unlikely(pos >= g_max_sizes[sz]))
109 {
110 return 0;
111 }
112
113 #ifdef DA256_USE_PX
114 Uint32 px[4] = { (pos >> 24) & 255,
115 (pos >> 16) & 255,
116 (pos >> 8) & 255,
117 (pos >> 0) & 255 };
118 #endif
119
120 Uint32* retVal = &m_head.m_ptr_i;
121 for(; sz --;)
122 {
123 if (unlikely(ptrI == RNIL))
124 {
125 return 0;
126 }
127 #ifdef DA256_USE_PX
128 Uint32 p0 = px[sz];
129 #else
130 Uint32 shr = sz << 3;
131 Uint32 p0 = (pos >> shr) & 255;
132 #endif
133 Uint32 page_no = ptrI >> DA256_BITS;
134 Uint32 page_idx = ptrI & DA256_MASK;
135 DA256Page * page = memroot + page_no;
136
137 Uint32 *magic_ptr, p;
138 if (p0 != 255)
139 {
140 Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
141 Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
142
143 p = 0;
144 retVal = (ptr + 1 + p0 + line);
145 magic_ptr =(ptr + (p0 & ~15));
146 }
147 else
148 {
149 Uint32 b = (page_idx + 1) >> 4;
150 Uint32 * ptr = (Uint32*)(page->m_header+b);
151
152 p = page_idx - (b << 4) + b;
153 retVal = (ptr + 1 + p);
154 magic_ptr = ptr;
155 }
156
157 ptrI = *retVal;
158 Uint32 magic = *magic_ptr;
159
160 if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
161 goto err;
162 }
163
164 return retVal;
165 err:
166 require(false);
167 return 0;
168 }
169
170 Uint32 *
set(Uint32 pos)171 DynArr256::set(Uint32 pos)
172 {
173 Uint32 sz = m_head.m_sz;
174 Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
175 DA256Page * memroot = m_pool.m_memroot;
176
177 if (unlikely(pos >= g_max_sizes[sz]))
178 {
179 if (unlikely(!expand(pos)))
180 {
181 return 0;
182 }
183 sz = m_head.m_sz;
184 }
185
186 #ifdef DA256_USE_PX
187 Uint32 px[4] = { (pos >> 24) & 255,
188 (pos >> 16) & 255,
189 (pos >> 8) & 255,
190 (pos >> 0) & 255 };
191 #endif
192
193 Uint32 ptrI = m_head.m_ptr_i;
194 Uint32 *retVal = &m_head.m_ptr_i;
195 for(; sz --;)
196 {
197 #ifdef DA256_USE_PX
198 Uint32 p0 = px[sz];
199 #else
200 Uint32 shr = sz << 3;
201 Uint32 p0 = (pos >> shr) & 255;
202 #endif
203 if (ptrI == RNIL)
204 {
205 if (unlikely((ptrI = m_pool.seize()) == RNIL))
206 {
207 return 0;
208 }
209 * retVal = ptrI;
210 }
211
212 Uint32 page_no = ptrI >> DA256_BITS;
213 Uint32 page_idx = ptrI & DA256_MASK;
214 DA256Page * page = memroot + page_no;
215
216 Uint32 *magic_ptr, p;
217 if (p0 != 255)
218 {
219 Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
220 Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
221
222 p = 0;
223 magic_ptr = (ptr + (p0 & ~15));
224 retVal = (ptr + 1 + p0 + line);
225 }
226 else
227 {
228 Uint32 b = (page_idx + 1) >> 4;
229 Uint32 * ptr = (Uint32*)(page->m_header+b);
230
231 p = page_idx - (b << 4) + b;
232 magic_ptr = ptr;
233 retVal = (ptr + 1 + p);
234 }
235
236 ptrI = * retVal;
237 Uint32 magic = *magic_ptr;
238
239 if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
240 goto err;
241 }
242
243 return retVal;
244
245 err:
246 require(false);
247 return 0;
248 }
249
250 static
251 inline
252 void
initpage(DA256Page * p,Uint32 page_no,Uint32 type_id)253 initpage(DA256Page* p, Uint32 page_no, Uint32 type_id)
254 {
255 Uint32 i, j;
256 #ifdef DA256_USE_PREFETCH
257 #if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
258 #ifdef DA256_EXTRA_SAFE
259 for (i = 0; i<(30 * 17 + 2); i++)
260 {
261 __builtin_prefetch (p->m_header + i, 1);
262 }
263 #else
264 {
265 __builtin_prefetch (p->m_header + 0, 1);
266 __builtin_prefetch (p->m_header + 1, 1);
267 for (i = 0; i<30; i++)
268 {
269 __builtin_prefetch (p->m_nodes + i, 1);
270 }
271 }
272 #endif
273 #endif
274 #endif
275 DA256CL* cl;
276 for (i = 0; i<2; i++)
277 {
278 cl = p->m_header + i;
279 cl->m_magic = (~type_id << 16);
280 }
281
282 DA256Free* free;
283
284 for (i = 0; i<30; i++)
285 {
286 free = (DA256Free*)(p->m_nodes+i);
287 free->m_magic = type_id;
288 free->m_next_free = (page_no << DA256_BITS) + (i + 1);
289 #ifdef DA256_EXTRA_SAFE
290 DA256Node* node = p->m_nodes+i;
291 for (j = 0; j<17; j++)
292 node->m_lines[j].m_magic = type_id;
293 #endif
294 }
295
296 free = (DA256Free*)(p->m_nodes+29);
297 free->m_next_free = RNIL;
298 }
299
300 bool
expand(Uint32 pos)301 DynArr256::expand(Uint32 pos)
302 {
303 Uint32 i;
304 Uint32 idx = 0;
305 Uint32 alloc[5];
306 Uint32 sz = m_head.m_sz;
307
308 for (; pos >= g_max_sizes[sz]; sz++);
309
310 if (m_head.m_sz == 0)
311 {
312 m_head.m_sz = sz;
313 return true;
314 }
315
316 sz = m_head.m_sz;
317 for (; pos >= g_max_sizes[sz]; sz++)
318 {
319 Uint32 ptrI = m_pool.seize();
320 if (unlikely(ptrI == RNIL))
321 goto err;
322 alloc[idx++] = ptrI;
323 }
324
325 alloc[idx] = m_head.m_ptr_i;
326 m_head.m_sz = 1;
327 for (Uint32 i = 0; i<idx; i++)
328 {
329 m_head.m_ptr_i = alloc[i];
330 Uint32 * ptr = get(0);
331 * ptr = alloc[i + 1];
332 }
333
334 m_head.m_sz = sz;
335 m_head.m_ptr_i = alloc[0];
336
337 return true;
338
339 err:
340 for (i = 0; i<idx; i++)
341 m_pool.release(alloc[i]);
342 return false;
343 }
344
345 void
init(ReleaseIterator & iter)346 DynArr256::init(ReleaseIterator &iter)
347 {
348 iter.m_sz = 1;
349 iter.m_pos = 0;
350 iter.m_ptr_i[0] = RNIL;
351 iter.m_ptr_i[1] = m_head.m_ptr_i;
352 iter.m_ptr_i[2] = RNIL;
353 iter.m_ptr_i[3] = RNIL;
354 iter.m_ptr_i[4] = RNIL;
355 }
356
357 /**
358 * Iter is in next pos
359 *
360 * 0 - done
361 * 1 - data
362 * 2 - no data
363 */
364 Uint32
release(ReleaseIterator & iter,Uint32 * retptr)365 DynArr256::release(ReleaseIterator &iter, Uint32 * retptr)
366 {
367 Uint32 sz = iter.m_sz;
368 Uint32 ptrI = iter.m_ptr_i[sz];
369 Uint32 page_no = ptrI >> DA256_BITS;
370 Uint32 page_idx = ptrI & DA256_MASK;
371 Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
372 DA256Page * memroot = m_pool.m_memroot;
373 DA256Page * page = memroot + page_no;
374
375 if (ptrI != RNIL)
376 {
377 Uint32 p0 = iter.m_pos & 255;
378 for (; p0<256; p0++)
379 {
380 Uint32 *retVal, *magic_ptr, p;
381 if (p0 != 255)
382 {
383 Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
384 Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
385
386 p = 0;
387 retVal = (ptr + 1 + p0 + line);
388 magic_ptr =(ptr + (p0 & ~15));
389 }
390 else
391 {
392 Uint32 b = (page_idx + 1) >> 4;
393 Uint32 * ptr = (Uint32*)(page->m_header+b);
394
395 p = page_idx - (b << 4) + b;
396 retVal = (ptr + 1 + p);
397 magic_ptr = ptr;
398 }
399
400 Uint32 magic = *magic_ptr;
401 Uint32 val = *retVal;
402 if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
403 goto err;
404
405 if (sz == m_head.m_sz)
406 {
407 * retptr = val;
408 p0++;
409 if (p0 != 256)
410 {
411 /**
412 * Move next
413 */
414 iter.m_pos &= ~(Uint32)255;
415 iter.m_pos |= p0;
416 }
417 else
418 {
419 /**
420 * Move up
421 */
422 m_pool.release(ptrI);
423 iter.m_sz --;
424 iter.m_pos >>= 8;
425 }
426 return 1;
427 }
428 else if (val != RNIL)
429 {
430 iter.m_sz++;
431 iter.m_ptr_i[iter.m_sz] = val;
432 iter.m_pos = (p0 << 8);
433 * retVal = RNIL;
434 return 2;
435 }
436 }
437
438 assert(p0 == 256);
439 m_pool.release(ptrI);
440 iter.m_sz --;
441 iter.m_pos >>= 8;
442 return 2;
443 }
444
445 new (&m_head) Head();
446 return 0;
447
448 err:
449 require(false);
450 return false;
451 }
452
453 static
454 inline
455 bool
seizenode(DA256Page * page,Uint32 idx,Uint32 type_id)456 seizenode(DA256Page* page, Uint32 idx, Uint32 type_id)
457 {
458 Uint32 i;
459 Uint32 b = (idx + 1) >> 4;
460 Uint32 p = idx - (b << 4) + b;
461
462 DA256Node * ptr = (DA256Node*)(page->m_nodes + idx);
463
464 #ifdef DA256_USE_PREFETCH
465 #if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
466 __builtin_prefetch (page->m_header + b, 1);
467 for (i = 0; i<17; i++)
468 {
469 __builtin_prefetch (ptr->m_lines+i, 1);
470 }
471 #endif
472 #endif
473
474 #ifdef DA256_EXTRA_SAFE
475 Uint32 check = type_id;
476 #endif
477 type_id = ((~type_id) << 16) | 0xFFFF;
478
479 #ifdef DA256_EXTRA_SAFE
480 if (unlikely(((page->m_header + b)->m_magic & (1 << p)) != 0))
481 {
482 return false;
483 }
484 #endif
485
486 (page->m_header + b)->m_magic |= (1 << p);
487 (page->m_header + b)->m_data[p] = RNIL;
488 for (i = 0; i<17; i++)
489 {
490 DA256CL * line = ptr->m_lines + i;
491 #ifdef DA256_EXTRA_SAFE
492 if (unlikely(line->m_magic != check))
493 {
494 return false;
495 }
496 #endif
497 line->m_magic = type_id;
498 for (Uint32 j = 0; j<15; j++)
499 line->m_data[j] = RNIL;
500 }
501
502 #ifdef UNIT_TEST
503 allocatednodes++;
504 #endif
505 return true;
506 }
507
508 static
509 bool
releasenode(DA256Page * page,Uint32 idx,Uint32 type_id)510 releasenode(DA256Page* page, Uint32 idx, Uint32 type_id)
511 {
512 Uint32 i;
513 Uint32 b = (idx + 1) >> 4;
514 Uint32 p = idx - (b << 4) + b;
515
516 DA256Node * ptr = (DA256Node*)(page->m_nodes + idx);
517
518 #ifdef DA256_USE_PREFETCH
519 #if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
520 __builtin_prefetch (page->m_header + b, 1);
521 for (i = 0; i<17; i++)
522 {
523 __builtin_prefetch (ptr->m_lines+i, 1);
524 }
525 #endif
526 #endif
527
528 #ifdef DA256_EXTRA_SAFE
529 Uint32 check = ((~type_id) << 16) | 0xFFFF;
530 #endif
531
532 #ifdef DA256_EXTRA_SAFE
533 if (unlikely((((page->m_header + b)->m_magic & (1 << p)) == 0)))
534 {
535 return false;
536 }
537 #endif
538
539 (page->m_header + b)->m_magic ^= (1 << p);
540 for (i = 0; i<17; i++)
541 {
542 DA256CL * line = ptr->m_lines + i;
543 #ifdef DA256_EXTRA_SAFE
544 if (unlikely(line->m_magic != check))
545 {
546 return false;
547 }
548 #endif
549 line->m_magic = type_id;
550 }
551
552 #ifdef UNIT_TEST
553 releasednodes++;
554 #endif
555
556 return true;
557 }
558
559 Uint32
seize()560 DynArr256Pool::seize()
561 {
562 Uint32 ff = m_first_free;
563 Uint32 type_id = m_type_id;
564
565 DA256Page* page;
566 DA256Page * memroot = m_memroot;
567 if (ff == RNIL)
568 {
569 Uint32 page_no;
570 if (likely((page = (DA256Page*)m_ctx.alloc_page(type_id, &page_no)) != 0))
571 {
572 initpage(page, page_no, type_id);
573 #ifdef UNIT_TEST
574 allocatedpages++;
575 #endif
576 }
577 else
578 {
579 return RNIL;
580 }
581 ff = (page_no << DA256_BITS);
582 }
583 else
584 {
585 page = memroot + (ff >> DA256_BITS);
586 }
587
588 Uint32 idx = ff & DA256_MASK;
589 DA256Free * ptr = (DA256Free*)(page->m_nodes + idx);
590 if (likely(ptr->m_magic == type_id))
591 {
592 Uint32 next = ptr->m_next_free;
593 if (likely(seizenode(page, idx, type_id)))
594 {
595 m_first_free = next;
596 return ff;
597 }
598 }
599
600 //error:
601 require(false);
602 return 0;
603 }
604
605 void
release(Uint32 ptrI)606 DynArr256Pool::release(Uint32 ptrI)
607 {
608 Uint32 ff = m_first_free;
609 Uint32 type_id = m_type_id;
610
611 Uint32 page_no = ptrI >> DA256_BITS;
612 Uint32 page_idx = ptrI & DA256_MASK;
613 DA256Page * memroot = m_memroot;
614 DA256Page * page = memroot + page_no;
615
616 DA256Free * ptr = (DA256Free*)(page->m_nodes + page_idx);
617 if (likely(releasenode(page, page_idx, type_id)))
618 {
619 ptr->m_next_free = ff;
620 ptr->m_magic = type_id;
621 m_first_free = ptrI;
622 return;
623 }
624 require(false);
625 }
626
627 #ifdef UNIT_TEST
628
629 #include <NdbTick.h>
630 #include "ndbd_malloc_impl.hpp"
631 #include "SimulatedBlock.hpp"
632
633 Ndbd_mem_manager mm;
634 Configuration cfg;
635 Block_context ctx(cfg, mm);
636 struct BB : public SimulatedBlock
637 {
BBBB638 BB(int no, Block_context& ctx) : SimulatedBlock(no, ctx) {}
639 };
640
641 BB block(DBACC, ctx);
642
643 static
644 void
simple(DynArr256 & arr,int argc,char * argv[])645 simple(DynArr256 & arr, int argc, char* argv[])
646 {
647 ndbout_c("argc: %d", argc);
648 for (Uint32 i = 1; i<(Uint32)argc; i++)
649 {
650 Uint32 * s = arr.set(atoi(argv[i]));
651 {
652 bool found = false;
653 for (Uint32 j = 1; j<i; j++)
654 {
655 if (atoi(argv[i]) == atoi(argv[j]))
656 {
657 found = true;
658 break;
659 }
660 }
661 if (!found)
662 * s = i;
663 }
664
665 Uint32 * g = arr.get(atoi(argv[i]));
666 Uint32 v = g ? *g : ~0;
667 ndbout_c("p: %p %p %d", s, g, v);
668 }
669 }
670
671 static
672 void
basic(DynArr256 & arr,int argc,char * argv[])673 basic(DynArr256& arr, int argc, char* argv[])
674 {
675 #define MAXLEN 65536
676
677 Uint32 len = 0;
678 Uint32 save[2*MAXLEN];
679 for (Uint32 i = 0; i<MAXLEN; i++)
680 {
681 int op = (rand() % 100) > 50;
682 if (len == 0)
683 op = 1;
684 if (len == MAXLEN)
685 op = 0;
686 switch(op){
687 case 0:{ // get
688 Uint32 item = (rand() % len) << 1;
689 Uint32 idx = save[item];
690 Uint32 val = save[item+1];
691 //ndbout_c("get(%d)", idx);
692 Uint32 *p = arr.get(idx);
693 assert(p);
694 assert(* p == val);
695 break;
696 }
697 case 1:{ // set
698 Uint32 item = len << 1;
699 Uint32 idx = i; //rand() & 0xFFFFF; // & 0xFFFFF; //rand(); //(65536*i) / 10000;
700 Uint32 val = rand();
701 #if 0
702 for(Uint32 j = 0; j < item; j += 2)
703 {
704 if (save[j] == idx)
705 {
706 item = j;
707 break;
708 }
709 }
710 #endif
711 //ndbout_c("set(%d, %x)", idx, val);
712 Uint32 *p = arr.set(idx);
713 assert(* p);
714 if (item == (len << 1))
715 {
716 *p = val;
717 len++;
718 }
719 else
720 {
721 assert(* p == save[item+1]);
722 * p = val;
723 }
724 save[item] = idx;
725 save[item+1] = val;
726 }
727 }
728 }
729 }
730
731 unsigned long long
micro()732 micro()
733 {
734 struct timeval tv;
735 gettimeofday(&tv, 0);
736 unsigned long long ret = tv.tv_sec;
737 ret *= 1000000;
738 ret += tv.tv_usec;
739 return ret;
740 }
741
742 static
743 void
read(DynArr256 & arr,int argc,char ** argv)744 read(DynArr256& arr, int argc, char ** argv)
745 {
746 Uint32 cnt = 100000;
747 Uint64 mbytes = 16*1024;
748 Uint32 seed = time(0);
749 Uint32 seq = 0, seqmask = 0;
750
751 for (Uint32 i = 2; i<argc; i++)
752 {
753 if (strncmp(argv[i], "--mbytes=", sizeof("--mbytes=")-1) == 0)
754 {
755 mbytes = atoi(argv[i]+sizeof("--mbytes=")-1);
756 if (argv[i][strlen(argv[i])-1] == 'g' ||
757 argv[i][strlen(argv[i])-1] == 'G')
758 mbytes *= 1024;
759 }
760 else if (strncmp(argv[i], "--cnt=", sizeof("--cnt=")-1) == 0)
761 {
762 cnt = atoi(argv[i]+sizeof("--cnt=")-1);
763 }
764 else if (strncmp(argv[i], "--seq", sizeof("--seq")-1) == 0)
765 {
766 seq = 1;
767 }
768 }
769
770 /**
771 * Populate with 5Mb
772 */
773 Uint32 maxidx = (1024*mbytes+31) / 32;
774 Uint32 nodes = (maxidx+255) / 256;
775 Uint32 pages = (nodes + 29)/ 30;
776 ndbout_c("%lldmb data -> %d entries (%dkb)",
777 mbytes, maxidx, 32*pages);
778
779 for (Uint32 i = 0; i<maxidx; i++)
780 {
781 Uint32 *ptr = arr.set(i);
782 assert(ptr);
783 * ptr = i;
784 }
785
786 srand(seed);
787
788 if (seq)
789 {
790 seq = rand();
791 seqmask = ~(Uint32)0;
792 }
793
794 ndbout_c("Timing %d %s reads (seed: %u)", cnt,
795 seq ? "sequential" : "random", seed);
796
797 for (Uint32 i = 0; i<10; i++)
798 {
799 Uint32 sum0 = 0, sum1 = 0;
800 Uint64 start = micro();
801 for (Uint32 i = 0; i<cnt; i++)
802 {
803 Uint32 idx = ((rand() & (~seqmask)) + ((i + seq) & seqmask)) % maxidx;
804 Uint32 *ptr = arr.get(idx);
805 sum0 += idx;
806 sum1 += *ptr;
807 }
808 start = micro() - start;
809 float uspg = start; uspg /= cnt;
810 ndbout_c("Elapsed %lldus diff: %d -> %f us/get", start, sum0 - sum1, uspg);
811 }
812 }
813
814 static
815 void
write(DynArr256 & arr,int argc,char ** argv)816 write(DynArr256& arr, int argc, char ** argv)
817 {
818 Uint32 seq = 0, seqmask = 0;
819 Uint32 cnt = 100000;
820 Uint64 mbytes = 16*1024;
821 Uint32 seed = time(0);
822
823 for (Uint32 i = 2; i<argc; i++)
824 {
825 if (strncmp(argv[i], "--mbytes=", sizeof("--mbytes=")-1) == 0)
826 {
827 mbytes = atoi(argv[i]+sizeof("--mbytes=")-1);
828 if (argv[i][strlen(argv[i])-1] == 'g' ||
829 argv[i][strlen(argv[i])-1] == 'G')
830 mbytes *= 1024;
831 }
832 else if (strncmp(argv[i], "--cnt=", sizeof("--cnt=")-1) == 0)
833 {
834 cnt = atoi(argv[i]+sizeof("--cnt=")-1);
835 }
836 else if (strncmp(argv[i], "--seq", sizeof("--seq")-1) == 0)
837 {
838 seq = 1;
839 }
840 }
841
842 /**
843 * Populate with 5Mb
844 */
845 Uint32 maxidx = (1024*mbytes+31) / 32;
846 Uint32 nodes = (maxidx+255) / 256;
847 Uint32 pages = (nodes + 29)/ 30;
848 ndbout_c("%lldmb data -> %d entries (%dkb)",
849 mbytes, maxidx, 32*pages);
850
851 srand(seed);
852
853 if (seq)
854 {
855 seq = rand();
856 seqmask = ~(Uint32)0;
857 }
858
859 ndbout_c("Timing %d %s writes (seed: %u)", cnt,
860 seq ? "sequential" : "random", seed);
861 for (Uint32 i = 0; i<10; i++)
862 {
863 Uint64 start = micro();
864 for (Uint32 i = 0; i<cnt; i++)
865 {
866 Uint32 idx = ((rand() & (~seqmask)) + ((i + seq) & seqmask)) % maxidx;
867 Uint32 *ptr = arr.set(idx);
868 *ptr = i;
869 }
870 start = micro() - start;
871 float uspg = start; uspg /= cnt;
872 ndbout_c("Elapsed %lldus -> %f us/set", start, uspg);
873 DynArr256::ReleaseIterator iter;
874 arr.init(iter);
875 Uint32 val;
876 while(arr.release(iter, &val));
877 }
878 }
879
880 int
main(int argc,char ** argv)881 main(int argc, char** argv)
882 {
883 if (0)
884 {
885 for (Uint32 i = 0; i<30; i++)
886 {
887 Uint32 b = (i + 1) >> 4;
888 Uint32 p = i - (b << 4) + b;
889 printf("[ %d %d %d ]\n", i, b, p);
890 }
891 return 0;
892 }
893
894 Pool_context pc;
895 pc.m_block = █
896
897 Resource_limit rl;
898 rl.m_min = 0;
899 rl.m_max = 10000;
900 rl.m_resource_id = 0;
901 mm.set_resource_limit(rl);
902 if(!mm.init())
903 {
904 abort();
905 }
906
907 DynArr256Pool pool;
908 pool.init(0x2001, pc);
909
910 DynArr256::Head head;
911 DynArr256 arr(pool, head);
912
913 if (strcmp(argv[1], "--simple") == 0)
914 simple(arr, argc, argv);
915 else if (strcmp(argv[1], "--basic") == 0)
916 basic(arr, argc, argv);
917 else if (strcmp(argv[1], "--read") == 0)
918 read(arr, argc, argv);
919 else if (strcmp(argv[1], "--write") == 0)
920 write(arr, argc, argv);
921
922 DynArr256::ReleaseIterator iter;
923 arr.init(iter);
924 Uint32 cnt = 0, val;
925 while (arr.release(iter, &val)) cnt++;
926
927 ndbout_c("allocatedpages: %d allocatednodes: %d releasednodes: %d"
928 " releasecnt: %d",
929 allocatedpages,
930 allocatednodes,
931 releasednodes,
932 cnt);
933
934 return 0;
935 #if 0
936 printf("sizeof(DA256Page): %d\n", sizeof(DA256Page));
937
938 DA256Page page;
939
940 for (Uint32 i = 0; i<10000; i++)
941 {
942 Uint32 arg = rand() & 255;
943 Uint32 base = 0;
944 Uint32 idx = arg & 256;
945 printf("%d\n", arg);
946
947 assert(base <= 30);
948
949 if (idx == 255)
950 {
951 Uint32 b = (base + 1) >> 4;
952 Uint32 p = base - (b << 4) + b;
953 Uint32 magic = page.m_header[b].m_magic;
954 Uint32 retVal = page.m_header[b].m_data[p];
955
956 require(magic & (1 << p));
957 return retVal;
958 }
959 else
960 {
961 // 4 bit extra offset per idx
962 Uint32 line = idx / 15;
963 Uint32 off = idx % 15;
964
965 {
966 Uint32 pos = 1 + idx + line;
967 Uint32 magic = pos & ~15;
968
969 Uint32 * ptr = (Uint32*)&page.m_nodes[base];
970 assert((ptr + pos) == &page.m_nodes[base].m_lines[line].m_data[off]);
971 assert((ptr + magic) == &page.m_nodes[base].m_lines[line].m_magic);
972 }
973 }
974 }
975 #endif
976 }
977
978 Uint32 g_currentStartPhase;
979 Uint32 g_start_type;
980 NdbNodeBitmask g_nowait_nodes;
981
childExit(int code,Uint32 currentStartPhase)982 void childExit(int code, Uint32 currentStartPhase)
983 {
984 abort();
985 }
986
childAbort(int code,Uint32 currentStartPhase)987 void childAbort(int code, Uint32 currentStartPhase)
988 {
989 abort();
990 }
991
childReportError(int error)992 void childReportError(int error)
993 {
994 abort();
995 }
996
997 void
sendCmAppChg(Ndbcntr & cntr,Signal * signal,Uint32 startLevel)998 UpgradeStartup::sendCmAppChg(Ndbcntr& cntr, Signal* signal, Uint32 startLevel){
999 }
1000
1001 void
execCM_APPCHG(SimulatedBlock & block,Signal * signal)1002 UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){
1003 }
1004
1005 void
sendCntrMasterReq(Ndbcntr & cntr,Signal * signal,Uint32 n)1006 UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){
1007 }
1008
1009 void
execCNTR_MASTER_REPLY(SimulatedBlock & block,Signal * signal)1010 UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){
1011 }
1012
1013 #include <SimBlockList.hpp>
1014
1015 void
unload()1016 SimBlockList::unload()
1017 {
1018
1019 }
1020
1021 #endif
1022