32 #include <system_error> 
   34 #include <unordered_set> 
   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));
 
   48         return a ^ (
b + 0x9e3779b9 + (a << 6) + (a >> 2));
 
   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) << 
"]";
 
   61     const bool DEBUG = 
false;
 
   67     EXPECT_EQ(3, test_set::max_keys_per_node);
 
   77     if (
DEBUG) t.printTree();
 
  175     for (
int i = 0; 
i < 10; 
i++) {
 
  193     for (
int i = 0; 
i < N; 
i++) {
 
  204         for (
int j = 0; 
j < N; 
j++) {
 
  219     for (
int i = N; 
i >= 0; 
i--) {
 
  229         for (
int j = 0; 
j < N; 
j++) {
 
  242     std::vector<int> 
data;
 
  243     for (
int i = 0; 
i < N; 
i++) {
 
  246     std::random_device rd;
 
  247     std::mt19937 generator(rd());
 
  249     shuffle(
data.begin(), 
data.end(), generator);
 
  251     for (
int i = 0; 
i < N; 
i++) {
 
  257     for (
int i = 0; 
i < N; 
i++) {
 
  269     std::vector<int> 
data;
 
  270     for (
int i = 0; 
i < N; 
i++) {
 
  273     std::random_device rd;
 
  274     std::mt19937 generator(rd());
 
  276     shuffle(
data.begin(), 
data.end(), generator);
 
  278     for (
int i = 0; 
i < N; 
i++) {
 
  284     for (
int i = 0; 
i < N; 
i++) {
 
  297     for (
int i = 0; 
i < N; 
i++) {
 
  300     for (
int i = 0; 
i < N; 
i++) {
 
  310     for (
int i = 0; 
i < N; 
i++) {
 
  338 TEST(BTreeSet, IteratorEmpty) {
 
  345 TEST(BTreeSet, IteratorBasic) {
 
  351     for (
int i = 0; 
i <= N; 
i++) {
 
  370 TEST(BTreeSet, IteratorStress) {
 
  377     std::vector<int> 
data;
 
  378     for (
int i = 0; 
i < N; 
i++) {
 
  381     std::random_device rd;
 
  382     std::mt19937 generator(rd());
 
  384     shuffle(
data.begin(), 
data.end(), generator);
 
  387     for (
int i = 0; 
i < N; 
i++) {
 
  407     for (
int i = 0; 
i < 10; 
i++) {
 
  413     auto a = t.lower_bound(5);
 
  416     auto b = t.upper_bound(5);
 
  428     a = t.lower_bound(5);
 
  431     b = t.upper_bound(5);
 
  438 TEST(BTreeSet, BoundaryEmpty) {
 
  448     EXPECT_EQ(t.lower_bound(3), t.upper_bound(3));
 
  449     EXPECT_EQ(t.lower_bound(5), t.upper_bound(5));
 
  452     EXPECT_EQ(t.lower_bound(3), t.upper_bound(3));
 
  453     EXPECT_EQ(t.lower_bound(5), t.upper_bound(5));
 
  457     EXPECT_EQ(t.lower_bound(3), t.upper_bound(3));
 
  458     EXPECT_NE(t.lower_bound(5), t.upper_bound(5));
 
  464     for (
int N = 0; N < 100; N++) {
 
  466         std::vector<int> 
data;
 
  468         for (
int i = 0; 
i < N; 
i++) {
 
  472         auto t = test_set::load(
data.begin(), 
data.end());
 
  511     for (
int i = 0; 
i < 100; 
i++) {
 
  516     auto chunks = t.getChunks(20);
 
  520     for (
const auto& cur : chunks) {
 
  522             std::cout << 
i << 
", ";
 
  528     for (
const auto& chunk : chunks) {
 
  529         for (
auto current : chunk) {
 
  536 TEST(BTreeSet, ChunkSplitStress) {
 
  539     for (
int i = 0; 
i < 1000; 
i++) {
 
  541         std::vector<int> 
data;
 
  542         for (
int j = 0; 
j < 
i; 
j++) {
 
  545         std::random_device rd;
 
  546         std::mt19937 generator(rd());
 
  548         shuffle(
data.begin(), 
data.end(), generator);
 
  557         for (
int j = 1; 
j < 100; 
j++) {
 
  558             auto chunks = t.getChunks(
j);
 
  561             if (chunks.empty()) 
continue;
 
  567             for (
const auto& chunk : chunks) {
 
  568                 for (
auto current : chunk) {
 
  579 using Entry = std::tuple<int, int>;
 
  581 std::vector<Entry> 
getData(
unsigned numEntries) {
 
  582     std::vector<Entry> res(numEntries);
 
  584     for (
unsigned i = 0; 
i < numEntries; 
i++) {
 
  587     std::random_device rd;
 
  588     std::mt19937 generator(rd());
 
  590     shuffle(res.begin(), res.end(), generator);
 
  601     return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 
  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;
 
  612     std::cout << 
" done [" << std::setw(5) << 
time << 
"ms]\n";
 
  616 template <
typename C>
 
  623 template <
typename A, 
typename B, 
typename C, 
typename D>
 
  624 struct reserver<
std::unordered_set<A, B, C, D>> {
 
  630 #define checkPerformance(set_type, name, in, out)                                      \ 
  632         std::cout << "Testing: " << name << " ..\n";                                   \ 
  634         time("filling set", [&]() {                                                    \ 
  635             reserver<set_type>()(set, in.size());                                      \ 
  636             for (const auto& cur : in) {                                               \ 
  640         EXPECT_EQ(in.size(), set.size());                                              \ 
  642         time("full scan", [&]() {                                                      \ 
  643             for (auto it = set.begin(); it != set.end(); ++it) {                       \ 
  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;               \ 
  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;               \ 
  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;        \ 
  668         EXPECT_TRUE(allFound);                                                         \ 
  670         time("upper_boundaries", [&]() {                                               \ 
  671             for (const auto& cur : in) {                                               \ 
  672                 allFound = (set.upper_bound(cur) == (++set.find(cur))) && allFound;    \ 
  675         EXPECT_TRUE(allFound);                                                         \ 
  677         time("boundaries on missing elements", [&]() {                                 \ 
  678             for (const auto& cur : out) {                                              \ 
  679                 allFound = (set.lower_bound(cur) == set.upper_bound(cur)) && allFound; \ 
  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";                                                    \ 
  689 TEST(Performance, Basic) {
 
  694     std::cout << 
"Generating Test-Data ...\n";
 
  695     std::vector<Entry> in;
 
  696     std::vector<Entry> out;
 
  697     time(
"generating data", [&]() {
 
  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]);
 
  705     using t1 = std::set<Entry>;
 
  708     using t2 = btree_set<Entry, detail::comparator<Entry>, std::allocator<Entry>, 256, detail::linear_search>;
 
  711     using t3 = btree_set<Entry, detail::comparator<Entry>, std::allocator<Entry>, 256, detail::binary_search>;
 
  715 TEST(Performance, Load) {
 
  719     std::vector<int> 
data;
 
  720     for (
int i = 0; 
i < N; 
i++) {
 
  725     time(
"conventional load", [&]() { btree_set<int> t(
data.begin(), 
data.end()); });
 
  741     std::vector<entry_t> list;
 
  744     for (
int i = 0; 
i < N; 
i++) {
 
  749     for (
int dup = 1; dup < 4; dup++) {
 
  751         std::vector<entry_t> full;
 
  752         for (
int i = 0; 
i < dup; 
i++) {
 
  753             for (
const auto& cur : list) {
 
  759         std::random_device rd;
 
  760         std::mt19937 generator(rd());
 
  762         std::shuffle(full.begin(), full.end(), generator);
 
  766 #pragma omp parallel for  //  schedule(static,1) 
  767         for (
auto it = full.begin(); it < full.end(); ++it) {
 
  776         std::set<entry_t> should(full.begin(), full.end());
 
  777         std::set<entry_t> is(res.
begin(), res.
end());
 
  779         for (
const auto& cur : should) {
 
  783         for (
const auto& cur : res) {
 
  784             EXPECT_TRUE(should.find(cur) != should.end()) << 
"Additional: " << cur << 
"\n" 
  785                                                           << 
"Contained: " << res.contains(cur) << 
"\n";
 
  788         std::vector<entry_t> extra;
 
  789         for (
const auto& cur : is) {
 
  790             if (should.find(cur) == should.end()) extra.push_back(cur);
 
  792         EXPECT_TRUE(extra.empty()) << 
"Extra elments: " << extra << 
"\n";
 
  794         std::vector<entry_t> missing;
 
  795         for (
const auto& cur : should) {
 
  796             if (is.find(cur) == is.end()) missing.push_back(cur);
 
  798         EXPECT_TRUE(missing.empty()) << 
"Missing elments: " << missing << 
"\n";
 
  809 TEST(BTreeSet, ParallelScaling) {
 
  811     using op_context_type = test_set::operation_hints;
 
  819     std::vector<int> 
data;
 
  820     for (
int i = 0; 
i < N; 
i++) {
 
  823     std::vector<int> data2 = 
data;
 
  824     std::random_device rd;
 
  825     std::mt19937 generator(rd());
 
  827     std::shuffle(
data.begin(), 
data.end(), generator);
 
  828     std::shuffle(data2.begin(), data2.end(), generator);
 
  830     for (
int i = 1; 
i <= 8; 
i++) {
 
  833         omp_set_num_threads(
i);
 
  835         double start = omp_get_wtime();
 
  839             op_context_type ctxt;
 
  842             for (
int i = 0; 
i < N; 
i++) {
 
  843                 t.insert(
data[
i], ctxt);
 
  844                 t.insert(data2[
i], ctxt);
 
  848         double end = omp_get_wtime();
 
  850         std::cout << 
"Number of threads: " << 
i << 
"[" << (end - start) << 
"ms]\n";