souffle  2.0.2-371-g6315b36
btree_set_test.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file btree_set_test.cpp
12  *
13  * A test case testing the B-trees utilization as sets.
14  *
15  ***********************************************************************/
16 
17 #include "tests/test.h"
18 
22 #include <algorithm>
23 #include <chrono>
24 #include <cstdlib>
25 #include <functional>
26 #include <iomanip>
27 #include <iostream>
28 #include <memory>
29 #include <random>
30 #include <set>
31 #include <string>
32 #include <system_error>
33 #include <tuple>
34 #include <unordered_set>
35 #include <vector>
36 #ifdef _OPENMP
37 #include <omp.h>
38 #endif
39 
40 namespace std {
41 
42 template <typename A, typename B>
43 struct hash<tuple<A, B>> {
44  std::size_t operator()(const tuple<A, B>& t) const {
45  auto a = std::hash<A>()(get<0>(t));
46  auto b = std::hash<B>()(get<1>(t));
47  // from http://www.boost.org/doc/libs/1_35_0/doc/html/boost/hash_combine_id241013.html
48  return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2));
49  }
50 };
51 
52 template <typename A, typename B>
53 std::ostream& operator<<(std::ostream& out, const tuple<A, B>& t) {
54  return out << "[" << get<0>(t) << "," << get<1>(t) << "]";
55 }
56 } // namespace std
57 
58 namespace souffle::test {
59 
60 TEST(BTreeSet, Basic) {
61  const bool DEBUG = false;
62 
63  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
64 
65  test_set t;
66 
67  EXPECT_EQ(3, test_set::max_keys_per_node);
68 
69  // check initial conditions
70  EXPECT_EQ(0u, t.size());
71  EXPECT_FALSE(t.contains(10));
72  EXPECT_FALSE(t.contains(12));
73  EXPECT_FALSE(t.contains(14));
74  EXPECT_EQ(0, t.getDepth());
75  EXPECT_EQ(0, t.getNumNodes());
76 
77  if (DEBUG) t.printTree();
78 
79  // add an element
80 
81  t.insert(12);
82  if (DEBUG) {
83  t.printTree();
84  std::cout << "\n";
85  }
86 
87  EXPECT_EQ(1u, t.size());
88  EXPECT_FALSE(t.contains(10));
89  EXPECT_TRUE(t.contains(12));
90  EXPECT_FALSE(t.contains(14));
91  EXPECT_EQ(1, t.getDepth());
92  EXPECT_EQ(1, t.getNumNodes());
93 
94  // add a larger element
95 
96  t.insert(14);
97  if (DEBUG) {
98  t.printTree();
99  std::cout << "\n";
100  }
101  EXPECT_EQ(2u, t.size());
102  EXPECT_FALSE(t.contains(10));
103  EXPECT_TRUE(t.contains(12));
104  EXPECT_TRUE(t.contains(14));
105  EXPECT_EQ(1, t.getDepth());
106  EXPECT_EQ(1, t.getNumNodes());
107 
108  // add a smaller element
109 
110  t.insert(10);
111  if (DEBUG) {
112  t.printTree();
113  std::cout << "\n";
114  }
115  EXPECT_EQ(3u, t.size());
116  EXPECT_TRUE(t.contains(10));
117  EXPECT_TRUE(t.contains(12));
118  EXPECT_TRUE(t.contains(14));
119  EXPECT_EQ(1, t.getDepth());
120  EXPECT_EQ(1, t.getNumNodes());
121 
122  // cause a split
123  t.insert(11);
124  if (DEBUG) {
125  t.printTree();
126  std::cout << "\n";
127  }
128  EXPECT_EQ(4u, t.size());
129  EXPECT_TRUE(t.contains(10));
130  EXPECT_TRUE(t.contains(11));
131  EXPECT_TRUE(t.contains(12));
132  EXPECT_TRUE(t.contains(14));
133 
134  if (DEBUG) {
135  t.printTree();
136  std::cout << "\n";
137  }
138 
139  EXPECT_EQ(4u, t.size());
140  t.insert(12);
141  EXPECT_EQ(4u, t.size());
142  t.insert(12);
143  EXPECT_EQ(4u, t.size());
144 
145  t.insert(10);
146  EXPECT_EQ(4u, t.size());
147 
148  if (DEBUG) {
149  t.printTree();
150  std::cout << "\n";
151  }
152 
153  t.insert(15);
154  EXPECT_EQ(5u, t.size());
155  EXPECT_EQ(2, t.getDepth());
156  EXPECT_EQ(3, t.getNumNodes());
157  if (DEBUG) {
158  t.printTree();
159  std::cout << "\n";
160  }
161 
162  t.insert(16);
163  EXPECT_EQ(6u, t.size());
164  if (DEBUG) {
165  t.printTree();
166  std::cout << "\n";
167  }
168 }
169 
170 TEST(BTreeSet, Duplicates) {
171  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
172 
173  test_set t;
174 
175  for (int i = 0; i < 10; i++) {
176  t.insert(0);
177  }
178 
179  EXPECT_EQ(1, t.size());
180 
181  EXPECT_EQ(0, *t.begin());
182 
183  // t.printTree();
184 }
185 
186 TEST(BTreeSet, Incremental) {
187  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
188 
189  test_set t;
190 
191  int N = 1000;
192 
193  for (int i = 0; i < N; i++) {
194  // std::cout << "\nBefore:\n";
195  // t.printTree();
196  // std::cout << "\n";
197  t.insert(i);
198  // std::cout << "\nAfter:\n";
199  // std::cout << "\n";
200  // t.printTree();
201  // std::cout << "\n";
202  // std::cout << "\n\n";
203 
204  for (int j = 0; j < N; j++) {
205  EXPECT_EQ(j <= i, t.contains(j)) << "i=" << i << ", j=" << j;
206  }
207  }
208 
209  t.printStats();
210 }
211 
212 TEST(BTreeSet, Decremental) {
213  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
214 
215  test_set t;
216 
217  int N = 1000;
218 
219  for (int i = N; i >= 0; i--) {
220  // std::cout << "\nBefore:\n";
221  // t.printTree();
222  // std::cout << "\n";
223  t.insert(i);
224  // std::cout << "\nAfter:\n";
225  // t.printTree();
226  // std::cout << "\n";
227  // std::cout << "\n\n";
228 
229  for (int j = 0; j < N; j++) {
230  EXPECT_EQ(j >= i, t.contains(j)) << "i=" << i << ", j=" << j;
231  }
232  }
233 }
234 
235 TEST(BTreeSet, Shuffled) {
236  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
237 
238  test_set t;
239 
240  int N = 10000;
241 
242  std::vector<int> data;
243  for (int i = 0; i < N; i++) {
244  data.push_back(i);
245  }
246  std::random_device rd;
247  std::mt19937 generator(rd());
248 
249  shuffle(data.begin(), data.end(), generator);
250 
251  for (int i = 0; i < N; i++) {
252  t.insert(data[i]);
253  }
254 
255  // t.printTree();
256 
257  for (int i = 0; i < N; i++) {
258  EXPECT_TRUE(t.contains(i)) << "i=" << i;
259  }
260 }
261 
262 TEST(BTreeSet, Copy) {
263  using test_set = btree_set<int>;
264 
265  test_set t;
266 
267  int N = 100000;
268 
269  std::vector<int> data;
270  for (int i = 0; i < N; i++) {
271  data.push_back(i);
272  }
273  std::random_device rd;
274  std::mt19937 generator(rd());
275 
276  shuffle(data.begin(), data.end(), generator);
277 
278  for (int i = 0; i < N; i++) {
279  t.insert(data[i]);
280  }
281 
282  EXPECT_EQ((size_t)N, t.size());
283 
284  for (int i = 0; i < N; i++) {
285  EXPECT_TRUE(t.find(i) != t.end()) << "i=" << i;
286  }
287 
288  test_set t2;
289  EXPECT_EQ((size_t)N, t.size());
290  EXPECT_EQ(0, t2.size());
291 
292  t2 = t;
293 
294  EXPECT_EQ((size_t)N, t.size());
295  EXPECT_EQ((size_t)N, t2.size());
296 
297  for (int i = 0; i < N; i++) {
298  EXPECT_TRUE(t.find(i) != t.end()) << "i=" << i;
299  }
300  for (int i = 0; i < N; i++) {
301  EXPECT_TRUE(t2.find(i) != t2.end()) << "i=" << i;
302  }
303 
304  EXPECT_FALSE(t.find(N + 1) != t.end());
305  EXPECT_FALSE(t2.find(N + 1) != t2.end());
306  t2.insert(N + 1);
307  EXPECT_FALSE(t.find(N + 1) != t.end());
308  EXPECT_TRUE(t2.find(N + 1) != t2.end());
309 
310  for (int i = 0; i < N; i++) {
311  EXPECT_NE(&*t.find(i), &*t2.find(i)) << "i=" << i;
312  }
313 }
314 
315 TEST(BTreeSet, Merge) {
316  using test_set = btree_set<int>;
317 
318  test_set a;
319  test_set b;
320 
321  a.insert(1);
322  a.insert(2);
323  a.insert(3);
324  a.insert(4);
325 
326  b.insert(2);
327  b.insert(4);
328  b.insert(6);
329 
330  EXPECT_NE(a, b);
331 
332  test_set c = a;
333  test_set d = b;
334 
335  EXPECT_NE(c, d);
336 }
337 
338 TEST(BTreeSet, IteratorEmpty) {
339  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
340  test_set t;
341 
342  EXPECT_EQ(t.begin(), t.end());
343 }
344 
345 TEST(BTreeSet, IteratorBasic) {
346  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
347  test_set t;
348 
349  int N = 10;
350 
351  for (int i = 0; i <= N; i++) {
352  t.insert(i);
353  }
354 
355  // t.printTree();
356 
357  auto it = t.begin();
358  auto e = t.end();
359 
360  EXPECT_NE(it, e);
361 
362  int last = -1;
363  for (int i : t) {
364  EXPECT_EQ(last + 1, i);
365  last = i;
366  }
367  EXPECT_EQ(last, N);
368 }
369 
370 TEST(BTreeSet, IteratorStress) {
371  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
372 
373  test_set t;
374 
375  int N = 1000;
376 
377  std::vector<int> data;
378  for (int i = 0; i < N; i++) {
379  data.push_back(i);
380  }
381  std::random_device rd;
382  std::mt19937 generator(rd());
383 
384  shuffle(data.begin(), data.end(), generator);
385 
386  int max = -1;
387  for (int i = 0; i < N; i++) {
388  EXPECT_EQ((size_t)i, t.size());
389 
390  int last = -1;
391  for (int i : t) {
392  EXPECT_LT(last, i);
393  last = i;
394  }
395  EXPECT_EQ(last, max);
396 
397  t.insert(data[i]);
398  max = (data[i] > max) ? data[i] : max;
399  }
400 }
401 
402 TEST(BTreeSet, BoundaryTest) {
403  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
404 
405  test_set t;
406 
407  for (int i = 0; i < 10; i++) {
408  t.insert(i);
409  }
410 
411  // t.printTree();
412 
413  auto a = t.lower_bound(5);
414  EXPECT_EQ(5, *a);
415 
416  auto b = t.upper_bound(5);
417  EXPECT_EQ(6, *b);
418 
419  // add duplicates
420 
421  t.insert(5);
422  t.insert(5);
423  t.insert(5);
424 
425  // t.printTree(); std::cout << "\n";
426 
427  // test again ..
428  a = t.lower_bound(5);
429  EXPECT_EQ(5, *a);
430 
431  b = t.upper_bound(5);
432  EXPECT_EQ(6, *b);
433 
434  // check the distance
435  EXPECT_EQ(++a, b);
436 }
437 
438 TEST(BTreeSet, BoundaryEmpty) {
439  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
440 
441  test_set t;
442 
443  EXPECT_EQ(t.end(), t.lower_bound(5));
444  EXPECT_EQ(t.end(), t.upper_bound(5));
445 
446  t.insert(4);
447 
448  EXPECT_EQ(t.lower_bound(3), t.upper_bound(3));
449  EXPECT_EQ(t.lower_bound(5), t.upper_bound(5));
450 
451  t.insert(6);
452  EXPECT_EQ(t.lower_bound(3), t.upper_bound(3));
453  EXPECT_EQ(t.lower_bound(5), t.upper_bound(5));
454 
455  t.insert(5);
456 
457  EXPECT_EQ(t.lower_bound(3), t.upper_bound(3));
458  EXPECT_NE(t.lower_bound(5), t.upper_bound(5));
459 }
460 
461 TEST(BTreeSet, Load) {
462  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
463 
464  for (int N = 0; N < 100; N++) {
465  // generate some ordered data
466  std::vector<int> data;
467 
468  for (int i = 0; i < N; i++) {
469  data.push_back(i);
470  }
471 
472  auto t = test_set::load(data.begin(), data.end());
473  // t.printTree();
474 
475  EXPECT_EQ(data.size(), t.size());
476  EXPECT_TRUE(t.check());
477 
478  int last = -1;
479  for (int c : t) {
480  EXPECT_EQ(last + 1, c);
481  last = c;
482  }
483  EXPECT_EQ(last, N - 1);
484  }
485 }
486 
487 TEST(BTreeSet, Clear) {
488  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
489 
490  test_set t;
491 
492  EXPECT_TRUE(t.empty());
493 
494  t.insert(5);
495 
496  EXPECT_FALSE(t.empty());
497  t.clear();
498  EXPECT_TRUE(t.empty());
499 
500  t.clear();
501  EXPECT_TRUE(t.empty());
502 }
503 
504 TEST(BTreeSet, ChunkSplit) {
505  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
506 
507  test_set t;
508 
509  // TODO: test for empty
510 
511  for (int i = 0; i < 100; i++) {
512  t.insert(i);
513  }
514 
515  // split chunks
516  auto chunks = t.getChunks(20);
517 
518  // EXPECT_EQ(20, chunks.size());
519 
520  for (const auto& cur : chunks) {
521  for (int i : cur) {
522  std::cout << i << ", ";
523  }
524  std::cout << "\n";
525  }
526 
527  int last = -1;
528  for (const auto& chunk : chunks) {
529  for (auto current : chunk) {
530  EXPECT_EQ(last + 1, current);
531  last = current;
532  }
533  }
534 }
535 
536 TEST(BTreeSet, ChunkSplitStress) {
537  using test_set = btree_set<int, detail::comparator<int>, std::allocator<int>, 16>;
538 
539  for (int i = 0; i < 1000; i++) {
540  // generate random sequence
541  std::vector<int> data;
542  for (int j = 0; j < i; j++) {
543  data.push_back(j);
544  }
545  std::random_device rd;
546  std::mt19937 generator(rd());
547 
548  shuffle(data.begin(), data.end(), generator);
549 
550  // fill tree
551  test_set t;
552 
553  for (int x : data) {
554  t.insert(x);
555  }
556 
557  for (int j = 1; j < 100; j++) {
558  auto chunks = t.getChunks(j);
559  // EXPECT_LT(chunks.size(), j * 2);
560 
561  if (chunks.empty()) continue;
562 
563  // check covered range
564  EXPECT_EQ(0, *chunks.front().begin());
565 
566  int last = -1;
567  for (const auto& chunk : chunks) {
568  for (auto current : chunk) {
569  EXPECT_EQ(last + 1, current);
570  last = current;
571  }
572  }
573 
574  EXPECT_EQ(i - 1, last);
575  }
576  }
577 }
578 
579 using Entry = std::tuple<int, int>;
580 
581 std::vector<Entry> getData(unsigned numEntries) {
582  std::vector<Entry> res(numEntries);
583  int k = 0;
584  for (unsigned i = 0; i < numEntries; i++) {
585  res[k++] = Entry(i / 100, i % 100);
586  }
587  std::random_device rd;
588  std::mt19937 generator(rd());
589 
590  shuffle(res.begin(), res.end(), generator);
591  return res;
592 }
593 
595 
596 time_point now() {
598 }
599 
600 long duration(const time_point& start, const time_point& end) {
601  return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
602 }
603 
604 template <typename Op>
605 long time(const std::string& name, const Op& operation) {
606  std::cout << "\t" << std::setw(30) << std::setiosflags(std::ios::left) << name
607  << std::resetiosflags(std::ios::left) << " ... " << std::flush;
608  auto a = now();
609  operation();
610  auto b = now();
611  long time = duration(a, b);
612  std::cout << " done [" << std::setw(5) << time << "ms]\n";
613  return time;
614 }
615 
616 template <typename C>
617 struct reserver {
618  void operator()(C&, unsigned) const {
619  // default: no action
620  }
621 };
622 
623 template <typename A, typename B, typename C, typename D>
624 struct reserver<std::unordered_set<A, B, C, D>> {
625  void operator()(std::unordered_set<A, B, C, D>& set, unsigned size) const {
626  set.reserve(size);
627  }
628 };
629 
630 #define checkPerformance(set_type, name, in, out) \
631  { \
632  std::cout << "Testing: " << name << " ..\n"; \
633  set_type set; \
634  time("filling set", [&]() { \
635  reserver<set_type>()(set, in.size()); \
636  for (const auto& cur : in) { \
637  set.insert(cur); \
638  } \
639  }); \
640  EXPECT_EQ(in.size(), set.size()); \
641  int counter = 0; \
642  time("full scan", [&]() { \
643  for (auto it = set.begin(); it != set.end(); ++it) { \
644  counter++; \
645  } \
646  }); \
647  EXPECT_EQ(in.size(), (size_t)counter); \
648  bool allPresent = true; \
649  time("membership in", [&]() { \
650  for (const auto& cur : in) { \
651  allPresent = (set.find(cur) != set.end()) && allPresent; \
652  } \
653  }); \
654  EXPECT_TRUE(allPresent); \
655  bool allMissing = true; \
656  time("membership out", [&]() { \
657  for (const auto& cur : out) { \
658  allMissing = (set.find(cur) == set.end()) && allMissing; \
659  } \
660  }); \
661  EXPECT_TRUE(allMissing); \
662  bool allFound = true; \
663  time("lower_boundaries", [&]() { \
664  for (const auto& cur : in) { \
665  allFound = (set.lower_bound(cur) == set.find(cur)) && allFound; \
666  } \
667  }); \
668  EXPECT_TRUE(allFound); \
669  allFound = true; \
670  time("upper_boundaries", [&]() { \
671  for (const auto& cur : in) { \
672  allFound = (set.upper_bound(cur) == (++set.find(cur))) && allFound; \
673  } \
674  }); \
675  EXPECT_TRUE(allFound); \
676  allFound = true; \
677  time("boundaries on missing elements", [&]() { \
678  for (const auto& cur : out) { \
679  allFound = (set.lower_bound(cur) == set.upper_bound(cur)) && allFound; \
680  } \
681  }); \
682  EXPECT_TRUE(allFound); \
683  set_type a(in.begin(), in.end()); \
684  set_type b(out.begin(), out.end()); \
685  time("merge two sets", [&]() { a.insert(b.begin(), b.end()); }); \
686  std::cout << "\tDone!\n\n"; \
687  }
688 
689 TEST(Performance, Basic) {
690  // int N = 1<<22;
691  int N = 1 << 18;
692 
693  // get list of tuples to be inserted
694  std::cout << "Generating Test-Data ...\n";
695  std::vector<Entry> in;
696  std::vector<Entry> out;
697  time("generating data", [&]() {
698  auto data = getData(2 * N);
699  for (std::size_t i = 0; i < data.size(); i += 2) {
700  in.push_back(data[i]);
701  out.push_back(data[i + 1]);
702  }
703  });
704 
705  using t1 = std::set<Entry>;
706  checkPerformance(t1, " -- warm up -- ", in, out);
707 
708  using t2 = btree_set<Entry, detail::comparator<Entry>, std::allocator<Entry>, 256, detail::linear_search>;
709  checkPerformance(t2, "souffle btree_set - 256 - linear", in, out);
710 
711  using t3 = btree_set<Entry, detail::comparator<Entry>, std::allocator<Entry>, 256, detail::binary_search>;
712  checkPerformance(t3, "souffle btree_set - 256 - binary", in, out);
713 }
714 
715 TEST(Performance, Load) {
716  // int N = 1<<24;
717  int N = 1 << 20;
718 
719  std::vector<int> data;
720  for (int i = 0; i < N; i++) {
721  data.push_back(i);
722  }
723 
724  // take time for conventional load
725  time("conventional load", [&]() { btree_set<int> t(data.begin(), data.end()); });
726 
727  // take time for structured load
728  time("bulk-load", [&]() { auto t = btree_set<int>::load(data.begin(), data.end()); });
729 }
730 
731 TEST(BTreeSet, Parallel) {
732  // const int N = 600000000;
733  // const int N = 100000;
734  // const int N = 10000;
735  const int N = 1000;
736  // const int N = 300;
737  // const int N = 100;
738 
739  // get a unordered list of test data
740  using entry_t = int;
741  std::vector<entry_t> list;
743 
744  for (int i = 0; i < N; i++) {
745  list.push_back(i);
746  }
747 
748  // the number of times duplicates show up in the input set
749  for (int dup = 1; dup < 4; dup++) {
750  // now duplicate this list
751  std::vector<entry_t> full;
752  for (int i = 0; i < dup; i++) {
753  for (const auto& cur : list) {
754  full.push_back(cur);
755  }
756  }
757 
758  // shuffle data
759  std::random_device rd;
760  std::mt19937 generator(rd());
761 
762  std::shuffle(full.begin(), full.end(), generator);
763 
764  // now insert all those values into a new set - in parallel
765  btree_set<entry_t> res;
766 #pragma omp parallel for // schedule(static,1)
767  for (auto it = full.begin(); it < full.end(); ++it) {
768  res.insert(*it);
769  }
770 
771  EXPECT_TRUE(res.check());
772 
773  // check resulting values
774  EXPECT_EQ(N, res.size());
775 
776  std::set<entry_t> should(full.begin(), full.end());
777  std::set<entry_t> is(res.begin(), res.end());
778 
779  for (const auto& cur : should) {
780  EXPECT_TRUE(res.contains(cur)) << "Missing: " << cur << "\n";
781  }
782 
783  for (const auto& cur : res) {
784  EXPECT_TRUE(should.find(cur) != should.end()) << "Additional: " << cur << "\n"
785  << "Contained: " << res.contains(cur) << "\n";
786  }
787 
788  std::vector<entry_t> extra;
789  for (const auto& cur : is) {
790  if (should.find(cur) == should.end()) extra.push_back(cur);
791  }
792  EXPECT_TRUE(extra.empty()) << "Extra elments: " << extra << "\n";
793 
794  std::vector<entry_t> missing;
795  for (const auto& cur : should) {
796  if (is.find(cur) == is.end()) missing.push_back(cur);
797  }
798  EXPECT_TRUE(missing.empty()) << "Missing elments: " << missing << "\n";
799  // << "All Elements: " << should << "\n";
800 
801  EXPECT_EQ(N, should.size());
802  EXPECT_EQ(N, is.size());
803  EXPECT_EQ(should, is);
804  }
805 }
806 
807 #ifdef _OPENMP
808 
809 TEST(BTreeSet, ParallelScaling) {
810  using test_set = btree_set<int>;
811  using op_context_type = test_set::operation_hints;
812 
813  // const int N = 60000000; // real benchmark
814  // const int N = 1000000; // to not run to long for unit testing
815  // const int N = 100000; // to not run to long for unit testing
816  const int N = 1000; // to not run to long for unit testing
817 
818  // create some random data
819  std::vector<int> data;
820  for (int i = 0; i < N; i++) {
821  data.push_back(i);
822  }
823  std::vector<int> data2 = data;
824  std::random_device rd;
825  std::mt19937 generator(rd());
826 
827  std::shuffle(data.begin(), data.end(), generator);
828  std::shuffle(data2.begin(), data2.end(), generator);
829 
830  for (int i = 1; i <= 8; i++) {
831  test_set t;
832 
833  omp_set_num_threads(i);
834 
835  double start = omp_get_wtime();
836 
837 #pragma omp parallel
838  {
839  op_context_type ctxt;
840 
841 #pragma omp for
842  for (int i = 0; i < N; i++) {
843  t.insert(data[i], ctxt);
844  t.insert(data2[i], ctxt);
845  }
846  }
847 
848  double end = omp_get_wtime();
849 
850  std::cout << "Number of threads: " << i << "[" << (end - start) << "ms]\n";
851 
852  // t.printTree();
853 
854  EXPECT_EQ(N, t.size());
855  int count = 0;
856  int last = -1;
857  for (int i : t) {
858  EXPECT_EQ(last + 1, i);
859  last = i;
860  count++;
861  }
862  EXPECT_EQ(N - 1, last);
863 
864  EXPECT_EQ(N, count);
865  }
866 }
867 
868 #endif
869 } // namespace souffle::test
BTree.h
TCB_SPAN_NAMESPACE_NAME::detail::size
constexpr auto size(const C &c) -> decltype(c.size())
Definition: span.h:198
DEBUG
#define DEBUG(Kind)
EXPECT_TRUE
#define EXPECT_TRUE(a)
Definition: test.h:189
souffle::detail::btree< Key, detail::comparator< Key >, std::allocator< Key >, 256, typename souffle::detail::default_strategy< Key >::type, true, detail::comparator< Key >, souffle::detail::updater< Key > >::end
iterator end() const
Definition: BTree.h:1729
souffle::btree_set
A b-tree based set implementation.
Definition: BTree.h:2241
souffle::detail::btree< Key, detail::comparator< Key >, std::allocator< Key >, 256, typename souffle::detail::default_strategy< Key >::type, true, detail::comparator< Key >, souffle::detail::updater< Key > >::check
bool check()
Checks the consistency of this tree.
Definition: BTree.h:2089
souffle::test::now
time_point now()
Definition: btree_multiset_test.cpp:402
checkPerformance
#define checkPerformance(set_type, name, in, out)
Definition: btree_set_test.cpp:630
souffle::btree_set::load
static btree_set load(const Iter &a, const Iter &b)
Definition: BTree.h:2284
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: test.h:191
e
l j a showGridBackground &&c b raw series this eventEmitter e
Definition: htmlJsChartistMin.h:15
souffle::test::time_point
std::chrono::high_resolution_clock::time_point time_point
Definition: btree_multiset_test.cpp:400
j
var j
Definition: htmlJsChartistMin.h:15
souffle::detail::btree::insert
bool insert(const Key &k)
Inserts the given key into this tree.
Definition: BTree.h:1328
souffle::detail::btree< Key, detail::comparator< Key >, std::allocator< Key >, 256, typename souffle::detail::default_strategy< Key >::type, true, detail::comparator< Key >, souffle::detail::updater< Key > >::begin
iterator begin() const
Definition: BTree.h:1724
souffle::now
time_point now()
Definition: MiscUtil.h:89
souffle::test::reserver< std::unordered_set< A, B, C, D > >::operator()
void operator()(std::unordered_set< A, B, C, D > &set, unsigned size) const
Definition: btree_set_test.cpp:625
i
size_t i
Definition: json11.h:663
souffle::filter
std::vector< A > filter(std::vector< A > xs, F &&f)
Filter a vector to include certain elements.
Definition: FunctionalUtil.h:155
ContainerUtil.h
souffle::test
Definition: binary_relation_test.cpp:43
souffle::test::count
int count(const C &c)
Definition: table_test.cpp:40
EXPECT_LT
#define EXPECT_LT(a, b)
Definition: test.h:199
test.h
souffle::detail::btree< Key, detail::comparator< Key >, std::allocator< Key >, 256, typename souffle::detail::default_strategy< Key >::type, true, detail::comparator< Key >, souffle::detail::updater< Key > >::size
size_type size() const
Definition: BTree.h:1321
souffle::time_point
std::chrono::high_resolution_clock::time_point time_point
Definition: MiscUtil.h:85
souffle::test::reserver::operator()
void operator()(C &, unsigned) const
Definition: btree_set_test.cpp:618
k
var k
Definition: htmlJsChartistMin.h:15
EXPECT_NE
#define EXPECT_NE(a, b)
Definition: test.h:195
souffle::test::duration
long duration(const time_point &start, const time_point &end)
Definition: btree_multiset_test.cpp:406
souffle::test::getData
std::vector< Entry > getData(unsigned numEntries)
Definition: btree_multiset_test.cpp:387
souffle::test::time
long time(const std::string &name, const Op &operation)
Definition: btree_multiset_test.cpp:411
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
std
Definition: Brie.h:3053
std::operator<<
ostream & operator<<(ostream &out, const array< T, E > &v)
Enables the generic printing of arrays assuming their element types are printable.
Definition: StreamUtil.h:233
souffle::detail::btree< Key, detail::comparator< Key >, std::allocator< Key >, 256, typename souffle::detail::default_strategy< Key >::type, true, detail::comparator< Key >, souffle::detail::updater< Key > >::contains
bool contains(const Key &k) const
Determines whether the given element is a member of this tree.
Definition: BTree.h:1756
souffle::test::Entry
std::tuple< int, int > Entry
Definition: btree_multiset_test.cpp:385
StreamUtil.h
d
else d
Definition: htmlJsChartistMin.h:15
TCB_SPAN_NAMESPACE_NAME::detail::data
constexpr auto data(C &c) -> decltype(c.data())
Definition: span.h:210
EXPECT_FALSE
#define EXPECT_FALSE(a)
Definition: test.h:190
souffle::test::TEST
TEST(EqRelTest, Scoping)
Definition: binary_relation_test.cpp:51