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