18 #include "DynArr256.hpp"
50 #define require(x) require_exit_or_core_with_printer((x), 0, ndbout_printer)
53 #define DA256_EXTRA_SAFE
58 #include <valgrind/callgrind.h>
60 #define CALLGRIND_TOGGLE_COLLECT()
62 Uint32 allocatedpages = 0;
63 Uint32 allocatednodes = 0;
64 Uint32 releasednodes = 0;
69 require_impl(
bool x,
int line)
73 ndbout_c(
"LINE: %d", line);
78 DynArr256Pool::DynArr256Pool()
86 DynArr256Pool::init(Uint32 type_id,
const Pool_context & pc)
92 DynArr256Pool::init(NdbMutex* m, Uint32 type_id,
const Pool_context & pc)
100 static const Uint32 g_max_sizes[5] = { 0, 256, 65536, 16777216, ~0 };
112 Uint32 sz = m_head.m_sz;
113 Uint32 ptrI = m_head.m_ptr_i;
115 Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
117 if (unlikely(pos >= g_max_sizes[sz]))
123 Uint32 px[4] = { (pos >> 24) & 255,
129 Uint32* retVal = &m_head.m_ptr_i;
132 if (unlikely(ptrI == RNIL))
139 Uint32 shr = sz << 3;
140 Uint32 p0 = (pos >> shr) & 255;
142 Uint32 page_no = ptrI >> DA256_BITS;
143 Uint32 page_idx = ptrI & DA256_MASK;
146 Uint32 *magic_ptr, p;
149 Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
150 Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
153 retVal = (ptr + 1 + p0 + line);
154 magic_ptr =(ptr + (p0 & ~15));
158 Uint32 b = (page_idx + 1) >> 4;
159 Uint32 * ptr = (Uint32*)(page->m_header+b);
161 p = page_idx - (b << 4) + b;
162 retVal = (ptr + 1 + p);
167 Uint32 magic = *magic_ptr;
169 if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
180 DynArr256::set(Uint32 pos)
182 Uint32 sz = m_head.m_sz;
183 Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
186 if (unlikely(pos >= g_max_sizes[sz]))
188 if (unlikely(!expand(pos)))
196 Uint32 px[4] = { (pos >> 24) & 255,
202 Uint32 ptrI = m_head.m_ptr_i;
203 Uint32 *retVal = &m_head.m_ptr_i;
209 Uint32 shr = sz << 3;
210 Uint32 p0 = (pos >> shr) & 255;
214 if (unlikely((ptrI = m_pool.seize()) == RNIL))
221 Uint32 page_no = ptrI >> DA256_BITS;
222 Uint32 page_idx = ptrI & DA256_MASK;
225 Uint32 *magic_ptr, p;
228 Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
229 Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
232 magic_ptr = (ptr + (p0 & ~15));
233 retVal = (ptr + 1 + p0 + line);
237 Uint32 b = (page_idx + 1) >> 4;
238 Uint32 * ptr = (Uint32*)(page->m_header+b);
240 p = page_idx - (b << 4) + b;
242 retVal = (ptr + 1 + p);
246 Uint32 magic = *magic_ptr;
248 if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
262 initpage(
DA256Page* p, Uint32 page_no, Uint32 type_id)
265 #ifdef DA256_USE_PREFETCH
266 #if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
267 #ifdef DA256_EXTRA_SAFE
268 for (i = 0; i<(30 * 17 + 2); i++)
270 __builtin_prefetch (p->m_header + i, 1);
274 __builtin_prefetch (p->m_header + 0, 1);
275 __builtin_prefetch (p->m_header + 1, 1);
276 for (i = 0; i<30; i++)
278 __builtin_prefetch (p->m_nodes + i, 1);
285 for (i = 0; i<2; i++)
287 cl = p->m_header +
i;
288 cl->m_magic = (~type_id << 16);
293 for (i = 0; i<30; i++)
296 free->m_magic = type_id;
297 free->m_next_free = (page_no << DA256_BITS) + (i + 1);
298 #ifdef DA256_EXTRA_SAFE
300 for (j = 0; j<17; j++)
301 node->m_lines[j].m_magic = type_id;
306 free->m_next_free = RNIL;
310 DynArr256::expand(Uint32 pos)
315 Uint32 sz = m_head.m_sz;
317 for (; pos >= g_max_sizes[sz]; sz++);
319 if (m_head.m_sz == 0)
326 for (; pos >= g_max_sizes[sz]; sz++)
328 Uint32 ptrI = m_pool.seize();
329 if (unlikely(ptrI == RNIL))
334 alloc[idx] = m_head.m_ptr_i;
336 for (i = 0; i<idx; i++)
338 m_head.m_ptr_i = alloc[
i];
339 Uint32 * ptr =
get(0);
340 * ptr = alloc[i + 1];
344 m_head.m_ptr_i = alloc[0];
349 for (i = 0; i<idx; i++)
350 m_pool.release(alloc[i]);
355 DynArr256::init(ReleaseIterator &iter)
359 iter.m_ptr_i[0] = RNIL;
360 iter.m_ptr_i[1] = m_head.m_ptr_i;
361 iter.m_ptr_i[2] = RNIL;
362 iter.m_ptr_i[3] = RNIL;
363 iter.m_ptr_i[4] = RNIL;
376 Uint32 sz = iter.m_sz;
377 Uint32 ptrI = iter.m_ptr_i[sz];
378 Uint32 page_no = ptrI >> DA256_BITS;
379 Uint32 page_idx = ptrI & DA256_MASK;
380 Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
386 Uint32 p0 = iter.m_pos & 255;
389 Uint32 *retVal, *magic_ptr, p;
392 Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
393 Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
396 retVal = (ptr + 1 + p0 + line);
397 magic_ptr =(ptr + (p0 & ~15));
401 Uint32 b = (page_idx + 1) >> 4;
402 Uint32 * ptr = (Uint32*)(page->m_header+b);
404 p = page_idx - (b << 4) + b;
405 retVal = (ptr + 1 + p);
409 Uint32 magic = *magic_ptr;
410 Uint32 val = *retVal;
411 if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
414 if (sz == m_head.m_sz)
423 iter.m_pos &= ~(Uint32)255;
431 m_pool.release(ptrI);
437 else if (val != RNIL)
440 iter.m_ptr_i[iter.m_sz] = val;
441 iter.m_pos = (p0 << 8);
448 m_pool.release(ptrI);
454 new (&m_head)
Head();
465 seizenode(
DA256Page* page, Uint32 idx, Uint32 type_id)
468 Uint32 b = (idx + 1) >> 4;
469 Uint32 p = idx - (b << 4) + b;
473 #ifdef DA256_USE_PREFETCH
474 #if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
475 __builtin_prefetch (page->m_header + b, 1);
476 for (i = 0; i<17; i++)
478 __builtin_prefetch (ptr->m_lines+i, 1);
483 #ifdef DA256_EXTRA_SAFE
484 Uint32 check = type_id;
486 type_id = ((~type_id) << 16) | 0xFFFF;
488 #ifdef DA256_EXTRA_SAFE
489 if (unlikely(((page->m_header + b)->m_magic & (1 << p)) != 0))
495 (page->m_header + b)->m_magic |= (1 << p);
496 (page->m_header + b)->m_data[p] = RNIL;
497 for (i = 0; i<17; i++)
500 #ifdef DA256_EXTRA_SAFE
501 if (unlikely(line->m_magic != check))
506 line->m_magic = type_id;
507 for (Uint32 j = 0; j<15; j++)
508 line->m_data[j] = RNIL;
519 releasenode(
DA256Page* page, Uint32 idx, Uint32 type_id)
522 Uint32 b = (idx + 1) >> 4;
523 Uint32 p = idx - (b << 4) + b;
527 #ifdef DA256_USE_PREFETCH
528 #if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
529 __builtin_prefetch (page->m_header + b, 1);
530 for (i = 0; i<17; i++)
532 __builtin_prefetch (ptr->m_lines+i, 1);
537 #ifdef DA256_EXTRA_SAFE
538 Uint32 check = ((~type_id) << 16) | 0xFFFF;
541 #ifdef DA256_EXTRA_SAFE
542 if (unlikely((((page->m_header + b)->m_magic & (1 << p)) == 0)))
548 (page->m_header + b)->m_magic ^= (1 << p);
549 for (i = 0; i<17; i++)
552 #ifdef DA256_EXTRA_SAFE
553 if (unlikely(line->m_magic != check))
558 line->m_magic = type_id;
569 DynArr256Pool::seize()
571 Uint32 type_id = m_type_id;
576 Uint32 ff = m_first_free;
582 initpage(page, page_no, type_id);
591 ff = (page_no << DA256_BITS);
595 page = memroot + (ff >> DA256_BITS);
598 Uint32 idx = ff & DA256_MASK;
600 if (likely(ptr->m_magic == type_id))
602 Uint32 next = ptr->m_next_free;
603 if (likely(seizenode(page, idx, type_id)))
616 DynArr256Pool::release(Uint32 ptrI)
618 Uint32 type_id = m_type_id;
620 Uint32 page_no = ptrI >> DA256_BITS;
621 Uint32 page_idx = ptrI & DA256_MASK;
626 if (likely(releasenode(page, page_idx, type_id)))
628 ptr->m_magic = type_id;
630 Uint32 ff = m_first_free;
631 ptr->m_next_free = ff;
641 #include "ndbd_malloc_impl.hpp"
642 #include "SimulatedBlock.hpp"
656 simple(
DynArr256 & arr,
int argc,
char* argv[])
658 ndbout_c(
"argc: %d", argc);
659 for (Uint32 i = 1; i<(Uint32)argc; i++)
661 Uint32 * s = arr.set(atoi(argv[i]));
664 for (Uint32 j = 1; j<
i; j++)
666 if (atoi(argv[i]) == atoi(argv[j]))
676 Uint32 * g = arr.
get(atoi(argv[i]));
677 Uint32 v = g ? *g : ~0;
678 ndbout_c(
"p: %p %p %d", s, g, v);
684 basic(
DynArr256& arr,
int argc,
char* argv[])
689 Uint32 save[2*MAXLEN];
690 for (Uint32 i = 0; i<MAXLEN; i++)
692 int op = (rand() % 100) > 50;
699 Uint32 item = (rand() % len) << 1;
700 Uint32 idx = save[item];
701 Uint32 val = save[item+1];
703 Uint32 *p = arr.
get(idx);
709 Uint32 item = len << 1;
713 for(Uint32 j = 0; j < item; j += 2)
723 Uint32 *p = arr.set(idx);
725 if (item == (len << 1))
732 assert(* p == save[item+1]);
746 gettimeofday(&tv, 0);
747 unsigned long long ret = tv.tv_sec;
755 read(
DynArr256& arr,
int argc,
char ** argv)
758 Uint64 mbytes = 16*1024;
759 Uint32 seed = time(0);
760 Uint32 seq = 0, seqmask = 0;
762 for (Uint32 i = 2; i<argc; i++)
764 if (strncmp(argv[i],
"--mbytes=",
sizeof(
"--mbytes=")-1) == 0)
766 mbytes = atoi(argv[i]+
sizeof(
"--mbytes=")-1);
767 if (argv[i][strlen(argv[i])-1] ==
'g' ||
768 argv[i][strlen(argv[i])-1] ==
'G')
771 else if (strncmp(argv[i],
"--cnt=",
sizeof(
"--cnt=")-1) == 0)
773 cnt = atoi(argv[i]+
sizeof(
"--cnt=")-1);
775 else if (strncmp(argv[i],
"--seq",
sizeof(
"--seq")-1) == 0)
784 Uint32 maxidx = (1024*mbytes+31) / 32;
785 Uint32 nodes = (maxidx+255) / 256;
786 Uint32 pages = (nodes + 29)/ 30;
787 ndbout_c(
"%lldmb data -> %d entries (%dkb)",
788 mbytes, maxidx, 32*pages);
790 for (Uint32 i = 0; i<maxidx; i++)
792 Uint32 *ptr = arr.set(i);
802 seqmask = ~(Uint32)0;
805 ndbout_c(
"Timing %d %s reads (seed: %u)", cnt,
806 seq ?
"sequential" :
"random", seed);
808 for (Uint32 i = 0; i<10; i++)
810 Uint32 sum0 = 0, sum1 = 0;
811 Uint64 start = micro();
812 for (Uint32 i = 0; i<cnt; i++)
814 Uint32 idx = ((rand() & (~seqmask)) + ((i + seq) & seqmask)) % maxidx;
815 Uint32 *ptr = arr.
get(idx);
819 start = micro() - start;
820 float uspg = start; uspg /= cnt;
821 ndbout_c(
"Elapsed %lldus diff: %d -> %f us/get", start, sum0 - sum1, uspg);
827 write(
DynArr256& arr,
int argc,
char ** argv)
829 Uint32 seq = 0, seqmask = 0;
831 Uint64 mbytes = 16*1024;
832 Uint32 seed = time(0);
834 for (Uint32 i = 2; i<argc; i++)
836 if (strncmp(argv[i],
"--mbytes=",
sizeof(
"--mbytes=")-1) == 0)
838 mbytes = atoi(argv[i]+
sizeof(
"--mbytes=")-1);
839 if (argv[i][strlen(argv[i])-1] ==
'g' ||
840 argv[i][strlen(argv[i])-1] ==
'G')
843 else if (strncmp(argv[i],
"--cnt=",
sizeof(
"--cnt=")-1) == 0)
845 cnt = atoi(argv[i]+
sizeof(
"--cnt=")-1);
847 else if (strncmp(argv[i],
"--seq",
sizeof(
"--seq")-1) == 0)
856 Uint32 maxidx = (1024*mbytes+31) / 32;
857 Uint32 nodes = (maxidx+255) / 256;
858 Uint32 pages = (nodes + 29)/ 30;
859 ndbout_c(
"%lldmb data -> %d entries (%dkb)",
860 mbytes, maxidx, 32*pages);
867 seqmask = ~(Uint32)0;
870 ndbout_c(
"Timing %d %s writes (seed: %u)", cnt,
871 seq ?
"sequential" :
"random", seed);
872 for (Uint32 i = 0; i<10; i++)
874 Uint64 start = micro();
875 for (Uint32 i = 0; i<cnt; i++)
877 Uint32 idx = ((rand() & (~seqmask)) + ((i + seq) & seqmask)) % maxidx;
878 Uint32 *ptr = arr.set(idx);
881 start = micro() - start;
882 float uspg = start; uspg /= cnt;
883 ndbout_c(
"Elapsed %lldus -> %f us/set", start, uspg);
887 while(arr.
release(iter, &val));
892 main(
int argc,
char** argv)
896 for (Uint32 i = 0; i<30; i++)
898 Uint32 b = (i + 1) >> 4;
899 Uint32 p = i - (b << 4) + b;
900 printf(
"[ %d %d %d ]\n", i, b, p);
911 rl.m_resource_id = 0;
919 pool.init(0x2001, pc);
924 if (strcmp(argv[1],
"--simple") == 0)
925 simple(arr, argc, argv);
926 else if (strcmp(argv[1],
"--basic") == 0)
927 basic(arr, argc, argv);
928 else if (strcmp(argv[1],
"--read") == 0)
929 read(arr, argc, argv);
930 else if (strcmp(argv[1],
"--write") == 0)
931 write(arr, argc, argv);
936 while (arr.
release(iter, &val)) cnt++;
938 ndbout_c(
"allocatedpages: %d allocatednodes: %d releasednodes: %d"
947 printf(
"sizeof(DA256Page): %d\n",
sizeof(
DA256Page));
951 for (Uint32 i = 0; i<10000; i++)
953 Uint32 arg = rand() & 255;
955 Uint32 idx = arg & 256;
962 Uint32 b = (base + 1) >> 4;
963 Uint32 p = base - (b << 4) + b;
964 Uint32 magic = page.m_header[b].m_magic;
965 Uint32 retVal = page.m_header[b].m_data[p];
967 require(magic & (1 << p));
973 Uint32 line = idx / 15;
974 Uint32 off = idx % 15;
977 Uint32 pos = 1 + idx + line;
978 Uint32 magic = pos & ~15;
980 Uint32 * ptr = (Uint32*)&page.m_nodes[base];
981 assert((ptr + pos) == &page.m_nodes[base].m_lines[line].m_data[off]);
982 assert((ptr + magic) == &page.m_nodes[base].m_lines[line].m_magic);
989 Uint32 g_currentStartPhase;
994 UpgradeStartup::sendCmAppChg(
Ndbcntr& cntr,
Signal* signal, Uint32 startLevel){
1002 UpgradeStartup::sendCntrMasterReq(
Ndbcntr& cntr,
Signal* signal, Uint32
n){
1009 #include <SimBlockList.hpp>
1012 SimBlockList::unload()