Commit f5845457 authored by Philipp Götze's avatar Philipp Götze
Browse files

💄 retapped code

parent 02a47d0f
......@@ -27,7 +27,7 @@
#define UNIT_TESTS
#include "benchmark/benchmark.h"
#include "PBPTree.hpp"
#include "BitPBPTree.hpp"
using namespace dbis::pbptree;
......@@ -38,8 +38,8 @@ using pmem::obj::pool;
using MyTuple = std::tuple <int, int, double>;
using MyKey = unsigned long long;
constexpr auto TARGET_BRANCH_SIZE = 512;
constexpr auto TARGET_LEAF_SIZE = 512; //< 512B best performance
constexpr auto TARGET_DEPTH = 1;
constexpr auto TARGET_LEAF_SIZE = 4096; //< 512B best performance
constexpr auto TARGET_DEPTH = 0;
const std::string path = dbis::gPmemPath + "tree_bench.data";
constexpr auto POOL_SIZE = 1024 * 1024 * 1024 * 4ull; //< 4GB
constexpr auto LAYOUT = "Tree";
......@@ -107,9 +107,9 @@ constexpr uint64_t ipow(uint64_t base, int exp, uint64_t result = 1) {
constexpr auto LEAFKEYS = getLeafKeysPBPTree<5>(); //< 5 iterations should be enough
constexpr auto BRANCHKEYS = getBranchKeysPBPTree<5>();
constexpr auto ELEMENTS = LEAFKEYS*ipow(BRANCHKEYS+1, TARGET_DEPTH);
constexpr auto KEYPOS = ELEMENTS/2;
constexpr auto KEYPOS = ELEMENTS/1;
using TreeType = PBPTree<MyKey, MyTuple, BRANCHKEYS, LEAFKEYS>;
using TreeType = BitPBPTree<MyKey, MyTuple, BRANCHKEYS, LEAFKEYS>;
/*=== Insert Function ===*/
void insert(persistent_ptr<TreeType> &tree) {
......@@ -138,7 +138,7 @@ void insert(persistent_ptr<TreeType> &tree) {
auto firstHalf = start + middle;
auto helper = start + nodeRange - middle - 1;
auto secondHalf = (BRANCHKEYS%2==0)? helper - 0 : helper - lowerRange;
auto end = (otherHalf)? secondHalf : firstHalf;
auto end = (otherHalf)? secondHalf : firstHalf;
for(auto i = start; i <= end; i+= LEAFKEYS*ipow(BRANCHKEYS+1,depth-1)) {
if (depth == 1) insertLoopLeaf(i);
else insertLoopBranch(i, depth-1, false);
......
......@@ -49,15 +49,15 @@ static void BM_TreeInsert(benchmark::State &state) {
});
}
auto tree = pop.root()->tree;
/* Getting the leaf node */
auto leaf = tree->rootNode.leaf;
//tree->printLeafNode(0, leaf);
//tree->printLeafNode(0, leaf);
const auto reqTup = MyTuple(KEYPOS, KEYPOS * 100, KEYPOS * 1.0);
const auto reqTup = MyTuple(KEYPOS, KEYPOS * 100, KEYPOS * 1.0);
TreeType::SplitInfo splitInfo;
bool split;
/* BENCHMARKING */
for (auto _ : state) {
state.PauseTiming();
......@@ -67,9 +67,9 @@ static void BM_TreeInsert(benchmark::State &state) {
prepare(tree);
dbis::PersistEmulation::getBytesWritten();
state.ResumeTiming();
split = tree->insertInLeafNode(leaf, KEYPOS, reqTup, &splitInfo);
state.PauseTiming();
assert(split == false);
tree->deleteLeafNode(leaf);
......
......@@ -49,15 +49,15 @@ static void BM_TreeSplit(benchmark::State &state) {
});
}
auto tree = pop.root()->tree;
/* Getting the leaf node */
auto leaf = tree->rootNode.leaf;
//tree->printLeafNode(0, leaf);
//tree->printLeafNode(0, leaf);
const auto reqTup = MyTuple(ELEMENTS+1, (ELEMENTS+1) * 100, (ELEMENTS+1) * 1.0);
const auto reqTup = MyTuple(ELEMENTS+1, (ELEMENTS+1) * 100, (ELEMENTS+1) * 1.0);
TreeType::SplitInfo splitInfo;
bool split;
/* BENCHMARKING */
for (auto _ : state) {
state.PauseTiming();
......@@ -68,9 +68,9 @@ static void BM_TreeSplit(benchmark::State &state) {
dbis::PersistEmulation::getBytesWritten();
//tree->printLeafNode(0, leaf);
state.ResumeTiming();
tree->splitLeafNode(leaf, &splitInfo);
state.PauseTiming();
//tree->printLeafNode(0, leaf);
tree->deleteLeafNode(leaf->nextLeaf);
......
project (fptree)
include_directories(${PROJECT_SOURCE_DIR}
include_directories(${PROJECT_SOURCE_DIR}
${THIRD_PARTY_DIR})
get_property(I_DIRS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
${I_DIRS}
CACHE INTERNAL "TESTING: Include Directories" FORCE
)
......
......@@ -720,9 +720,10 @@ class FPTree {
unsigned int lookupPositionInLeafNode(const persistent_ptr<LeafNode> node,
const KeyType &key) const {
unsigned int pos = 0u;
const auto &nodeRef = *node;
const auto hash = fpHash(key);
const auto &keys = node->keys.get_ro();
const auto &search = node->search.get_ro();
const auto &keys = nodeRef.keys.get_ro();
const auto &search = nodeRef.search.get_ro();
for (; pos < M ; pos++) {
if(search.fp[pos] == hash &&
search.b.test(pos) &&
......
......@@ -144,7 +144,7 @@ class BitPBPTree {
/* -------------------------------------------------------------------------------------------- */
/**
/**
* A structure for passing information about a node split to the caller.
*/
struct SplitInfo {
......@@ -706,23 +706,23 @@ class BitPBPTree {
* @param pos the position of the child node @child in the @c children array of the branch node
* @param child the node at which the underflow occured
* @return the (possibly new) child node (in case of a merge)
* TODO: I think this is not entirely correct, yet
* TODO: I think this is not entirely correct, yet
*/
pptr<BranchNode> underflowAtBranchLevel(const pptr<BranchNode> &node, const unsigned int pos,
const pptr<BranchNode> &child) {
assert(node != nullptr);
assert(child != nullptr);
auto &nodeRef = *node;
auto &nodeRef = *node;
PROFILE_READ(5)
const auto &nNumKeys = nodeRef.bits.get_ro().count();
const auto prevPos = findMaxKeySmallerThan(node, nodeRef.keys.get_ro()[pos]);
const auto prevNumKeys = nodeRef.children.get_ro()[prevPos].branch->bits.get_ro().count();
auto nextPos = 0u;
auto nextNumKeys = 0u;
const auto &nNumKeys = nodeRef.bits.get_ro().count();
const auto prevPos = findMaxKeySmallerThan(node, nodeRef.keys.get_ro()[pos]);
const auto prevNumKeys = nodeRef.children.get_ro()[prevPos].branch->bits.get_ro().count();
auto nextPos = 0u;
auto nextNumKeys = 0u;
constexpr auto middle = (N + 1) / 2;
pptr<BranchNode> newChild = child;
/// 1. we check whether we can rebalance with one of the siblings
/// 1. we check whether we can rebalance with one of the siblings
if (pos > 0 && prevNumKeys > middle) {
/// we have a sibling at the left for rebalancing the keys
PROFILE_READ(1)
......@@ -730,16 +730,16 @@ class BitPBPTree {
balanceBranchNodes(sibling, child, node, pos);
return newChild;
} else if (pos < nNumKeys) {
PROFILE_READ(3)
nextPos = findMinKeyGreaterThan(node, nodeRef.keys.get_ro()[pos]);
nextNumKeys = nodeRef.children.get_ro()[nextPos].branch->bits.get_ro().count();
PROFILE_READ(3)
nextPos = findMinKeyGreaterThan(node, nodeRef.keys.get_ro()[pos]);
nextNumKeys = nodeRef.children.get_ro()[nextPos].branch->bits.get_ro().count();
/// we have a sibling at the right for rebalancing the keys
if (nextNumKeys > middle) {
PROFILE_READ(1)
auto sibling = (nodeRef.children.get_ro()[nextPos]).branch;
balanceBranchNodes(sibling, child, node, pos);
return newChild;
}
if (nextNumKeys > middle) {
PROFILE_READ(1)
auto sibling = (nodeRef.children.get_ro()[nextPos]).branch;
balanceBranchNodes(sibling, child, node, pos);
return newChild;
}
}
/// 2. if this fails we have to merge two branch nodes
pptr<BranchNode> lSibling = nullptr, rSibling = nullptr;
......@@ -813,7 +813,7 @@ class BitPBPTree {
receiverRef.bits.get_rw().set(u);
/// 1.2. move toMove-1 keys/children from donor to receiver
for (auto i = 1u; i < toMove; i++) {
const auto max = findMaxKeyInNode(donor);
const auto max = findMaxKeyInNode(donor);
const auto u = getFreeZero(receiverRef.bits.get_ro());
receiverRef.keys.get_rw()[u] = donorRef.keys.get_ro()[max];
receiverRef.children.get_rw()[u] = donorRef.children.get_ro()[max];
......@@ -899,13 +899,13 @@ class BitPBPTree {
return false;
}
/**
/**
* Split the given leaf node @c node in the middle and move half of the keys/children to the new
* sibling node.
*
* @param node the leaf node to be split
* @param splitInfo[out] information about the split
*/
*/
void splitLeafNode(const pptr<LeafNode> &node, SplitInfo *splitInfo) {
auto &nodeRef = *node;
......@@ -939,7 +939,7 @@ class BitPBPTree {
/**
* Insert a (key, value) pair at the first free position into the leaf node @c node. The caller
* has to ensure that there is enough space to insert the element.
* has to ensure that there is enough space to insert the element.
*
* @oaram node the leaf node where the element is to be inserted
* @param key the key of the element
......@@ -1106,7 +1106,7 @@ class BitPBPTree {
return pos;
}
/* -------------------------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------------------------- */
/* DEBUGGING */
/* -------------------------------------------------------------------------------------------- */
......@@ -1118,8 +1118,8 @@ class BitPBPTree {
*/
void printBranchNode(const unsigned int d, const pptr<BranchNode> &node) const {
PROFILE_READ(1)
const auto &nodeRef = *node;
const auto nNumKeys = nodeRef.bits.get_ro().count();
const auto &nodeRef = *node;
const auto nNumKeys = nodeRef.bits.get_ro().count();
for (auto i = 0u; i < d; i++) std::cout << " ";
std::cout << d << "BN { [" << node << "] #" << nNumKeys << ": ";
for (auto k = 0u; k < N; k++) {
......@@ -1150,8 +1150,8 @@ class BitPBPTree {
*/
void printLeafNode(const unsigned int d, const pptr<LeafNode> &node) const {
PROFILE_READ(1)
const auto &nodeRef = *node;
const auto nNumKeys = nodeRef.bits.get_ro().count();
const auto &nodeRef = *node;
const auto nNumKeys = nodeRef.bits.get_ro().count();
for (auto i = 0u; i < d; i++) std::cout << " ";
std::cout << "[\033[1m" << std::hex << node << std::dec << "\033[0m #" << nNumKeys << ": ";
for (auto i = 0u; i < M; i++) {
......@@ -1162,7 +1162,7 @@ class BitPBPTree {
std::cout << "]" << std::endl;
}
/* -------------------------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------------------------- */
/* HELPER */
/* -------------------------------------------------------------------------------------------- */
......@@ -1218,27 +1218,27 @@ class BitPBPTree {
template<size_t E>
auto getFreeZero(std::bitset<E> b) {
if constexpr (E > 64) {
auto idx = 0u;
while (idx < E && b.test(idx)) ++idx;
return idx;
} else {
const auto w = b.to_ullong();
if (w != UINT64_MAX) {
/// count consecutive one bits using multiply and lookup
static constexpr uint8_t tab64[64] = {
63, 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5};
/// Applying deBruijn hash function + lookup
return tab64[((uint64_t) ((~w & -~w) * 0x07EDD5E59A4E28C2)) >> 58];
}
/// Valid result is between 0 and 63; 64 means no free position
return static_cast<uint8_t>(64);
}
}
if constexpr (E > 64) {
auto idx = 0u;
while (idx < E && b.test(idx)) ++idx;
return idx;
} else {
const auto w = b.to_ullong();
if (w != UINT64_MAX) {
/// count consecutive one bits using multiply and lookup
static constexpr uint8_t tab64[64] = {
63, 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5};
/// Applying deBruijn hash function + lookup
return tab64[((uint64_t) ((~w & -~w) * 0x07EDD5E59A4E28C2)) >> 58];
}
/// Valid result is between 0 and 63; 64 means no free position
return static_cast<uint8_t>(64);
}
}
/**
* Find the minimum key in unsorted node
......@@ -1284,7 +1284,7 @@ class BitPBPTree {
return pos;
}
/**
/**
* Searches for the next greater key than @key in @c node.
*/
template<typename Node>
......
project (pbptree)
include_directories(${PROJECT_SOURCE_DIR}
include_directories(${PROJECT_SOURCE_DIR}
${THIRD_PARTY_DIR})
get_property(I_DIRS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
${I_DIRS}
CACHE INTERNAL "TESTING: Include Directories" FORCE
)
......
......@@ -792,7 +792,7 @@ class PBPTree {
bool insertInLeafNode(persistent_ptr<LeafNode> node, const KeyType &key,
const ValueType &val, SplitInfo *splitInfo) {
bool split = false;
auto &nodeRef = *node;
auto &nodeRef = *node;
const auto &numKeys = nodeRef.numKeys.get_ro();
auto pos = lookupPositionInLeafNode(node, key);
if (pos < numKeys && nodeRef.keys.get_ro()[pos] == key) {
......@@ -839,7 +839,7 @@ class PBPTree {
sibRef.values.get_rw()[i] = nValues[i + middle];
}
nodeRef.numKeys.get_rw() = middle;
/* setup the list of leaf nodes */
if(nodeRef.nextLeaf != nullptr) {
sibRef.nextLeaf = nodeRef.nextLeaf;
......@@ -848,7 +848,7 @@ class PBPTree {
nodeRef.nextLeaf = sibling;
sibRef.prevLeaf = node;
//PersistEmulation::writeBytes(2*4 + sibRef.numKeys*(sizeof(KeyType) + sizeof(ValueType)) + 2*16); // 2 numKeys + half entries + pointers
auto &splitInfoRef = *splitInfo;
splitInfoRef.leftChild = node;
splitInfoRef.rightChild = sibling;
......
......@@ -183,9 +183,9 @@ class UnsortedPBPTree {
iterator begin() { return iterator(rootNode, depth); }
iterator end() { return iterator(); }
PROFILE_DECL
/**
* Typedef for a function passed to the scan method.
*/
......@@ -953,7 +953,7 @@ class UnsortedPBPTree {
const ValueType &val, SplitInfo *splitInfo) {
bool split = false;
auto pos = lookupPositionInLeafNode(node, key);
auto &nodeRef = *node;
auto &nodeRef = *node;
PROFILE_READ(1)
if (pos < nodeRef.numKeys && nodeRef.keys.get_ro()[pos] == key) {
// handle insert of duplicates
......@@ -963,16 +963,16 @@ class UnsortedPBPTree {
}
if (nodeRef.numKeys == M) {
/* split the node */
splitLeafNode(node, splitInfo);
auto &splitRef = *splitInfo;
auto sibling = splitRef.rightChild.leaf;
splitLeafNode(node, splitInfo);
auto &splitRef = *splitInfo;
auto sibling = splitRef.rightChild.leaf;
/* insert the new entry */
/* insert the new entry */
if (key < splitRef.key)
insertInLeafNodeAtLastPosition(node, key, val);
else
insertInLeafNodeAtLastPosition(sibling, key, val);
/* inform the caller about the split */
splitRef.key = sibling->keys.get_ro()[findMinKeyAtLeafNode(sibling)];
split = true;
......@@ -986,34 +986,34 @@ class UnsortedPBPTree {
void splitLeafNode(persistent_ptr<LeafNode> node, SplitInfo *splitInfo) {
auto &nodeRef = *node;
/* determine the split position by finding the median in unsorted array of keys */
PROFILE_SPLIT
PROFILE_READ(M)
auto data = node->keys.get_ro();
/* determine the split position by finding the median in unsorted array of keys */
PROFILE_SPLIT
PROFILE_READ(M)
auto data = node->keys.get_ro();
const auto [__unused__, splitPos] = findSplitKey(data);
const auto splitKey = data[splitPos];
/* move all entries with greater or equal keys to a new sibling node */
persistent_ptr<LeafNode> sibling = newLeafNode();
auto &sibRef = *sibling;
/* move all entries with greater or equal keys to a new sibling node */
persistent_ptr<LeafNode> sibling = newLeafNode();
auto &sibRef = *sibling;
auto n = 0u, s = 0u; //< node/sibling entry count
for (auto i = 0u; i < M; i++) {
PROFILE_READ(1)
const auto &currkey = nodeRef.keys.get_ro()[i];
if (currkey > splitKey){
PROFILE_READ(1)
PROFILE_WRITE(2)
sibRef.keys.get_rw()[s] = currkey;
sibRef.values.get_rw()[s] = nodeRef.values.get_ro()[i];
s++;
} else {
PROFILE_READ(1)
PROFILE_WRITE(2)
nodeRef.keys.get_rw()[n] = currkey;
nodeRef.values.get_rw()[n] = nodeRef.values.get_ro()[i];
n++;
}
}
for (auto i = 0u; i < M; i++) {
PROFILE_READ(1)
const auto &currkey = nodeRef.keys.get_ro()[i];
if (currkey > splitKey){
PROFILE_READ(1)
PROFILE_WRITE(2)
sibRef.keys.get_rw()[s] = currkey;
sibRef.values.get_rw()[s] = nodeRef.values.get_ro()[i];
s++;
} else {
PROFILE_READ(1)
PROFILE_WRITE(2)
nodeRef.keys.get_rw()[n] = currkey;
nodeRef.values.get_rw()[n] = nodeRef.values.get_ro()[i];
n++;
}
}
nodeRef.numKeys.get_rw() = n;
sibRef.numKeys.get_rw() = s;
......
......@@ -10,7 +10,7 @@ set (PTable_VERSION_MINOR 1)
include_directories(${PROJECT_SOURCE_DIR}
${PBPTREE_INCLUDE_DIRS})
get_property(I_DIRS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
${I_DIRS}
CACHE INTERNAL "TESTING: Include Directories" FORCE
)
......
/**
/**
* https://github.com/motonacciu/meta-serialization
*
* Copyright (c) 2013, Simone Pellegrini All rights reserved.
......@@ -6,12 +6,12 @@
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
......@@ -29,7 +29,7 @@
#ifndef serialize_hpp_
#define serialize_hpp_
#pragma once
#pragma once
#include <vector>
#include <string>
......@@ -45,270 +45,270 @@ inline void serialize(const T&, StreamType&);
namespace detail {
template<std::size_t> struct int_{};
template<std::size_t> struct int_{};
} // end detail namespace
} // end detail namespace
// get_size
// get_size
template <class T>
size_t get_size(const T& obj);
namespace detail {
template <class T>
struct get_size_helper;
template <class T>
struct get_size_helper;
template <class T>
struct get_size_helper<std::vector<T>> {
static size_t value(const std::vector<T>& obj) {
return std::accumulate(obj.begin(), obj.end(), sizeof(size_t),
[](const size_t& acc, const T& cur) { return acc+get_size(cur); });
}
};
template <class T>
struct get_size_helper<std::vector<T>> {
static size_t value(const std::vector<T>& obj) {
return std::accumulate(obj.begin(), obj.end(), sizeof(size_t),
[](const size_t& acc, const T& cur) { return acc+get_size(cur); });
}
};
template <>
struct get_size_helper<std::string> {
static size_t value(const std::string& obj) {
return sizeof(size_t) + obj.length()*sizeof(uint8_t);
}
};
template <>
struct get_size_helper<std::string> {
static size_t value(const std::string& obj) {
return sizeof(size_t) + obj.length()*sizeof(uint8_t);
}
};
template <class tuple_type>
inline size_t get_tuple_size(const tuple_type& obj, int_<0>) {
template <class tuple_type>
inline size_t get_tuple_size(const tuple_type& obj, int_<0>) {
constexpr size_t idx = std::tuple_size<tuple_type>::value-1;
return get_size(std::get<idx>(obj));
}
constexpr size_t idx = std::tuple_size<tuple_type>::value-1;
return get_size(std::get<idx>(obj));
}
template <class tuple_type, size_t pos>
inline size_t get_tuple_size(const tuple_type& obj, int_<pos>) {
constexpr size_t idx = std::tuple_size<tuple_type>::value-pos-1;
size_t acc = get_size(std::get<idx>(obj));
template <class tuple_type, size_t pos>
inline size_t get_tuple_size(const tuple_type& obj, int_<pos>) {
// recur
return acc+get_tuple_size(obj, int_<pos-1>());
}
constexpr size_t idx = std::tuple_size<tuple_type>::value-pos-1;
size_t acc = get_size(std::get<idx>(obj));
template <class ...T>
struct get_size_helper<std::tuple<T...>> {
// recur
return acc+get_tuple_size(obj, int_<pos-1>());
}
static size_t value(const std::tuple<T...>& obj) {
return get_tuple_size(obj, int_<sizeof...(T)-1>());
}
template <class ...T>
struct get_size_helper<std::tuple<T...>> {
};