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

🔨 Unified and refactored benchmarks

parent a6358e63
......@@ -19,27 +19,37 @@
#define DBIS_TREES_COMMON_HPP
#include <chrono>
#include <iostream>
#include <numeric>
#include <unistd.h>
#include <experimental/filesystem>
#include <libpmemobj++/pool.hpp>
#include <libpmemobj++/persistent_ptr.hpp>
#include <libpmemobj++/make_persistent.hpp>
#include <libpmemobj++/transaction.hpp>
#define UNIT_TESTS
#include "benchmark/benchmark.h"
#include "BitPBPTree.hpp"
#include "PBPTree.hpp"
using namespace dbis::pbptree;
using pmem::obj::delete_persistent;
using pmem::obj::make_persistent;
using pmem::obj::pool;
using pmem::obj::persistent_ptr;
using pmem::obj::transaction;
/*=== Types and constants ===*/
/* Customization section */
using MyTuple = std::tuple <int, int, double>;
using MyKey = unsigned long long;
constexpr auto TARGET_BRANCH_SIZE = 512;
constexpr auto TARGET_LEAF_SIZE = 4096; //< 512B best performance
constexpr auto TARGET_DEPTH = 0;
constexpr auto TARGET_LEAF_SIZE = 512; //< 512B best performance
constexpr auto TARGET_DEPTH = 1;
constexpr auto IS_HYBRID = false;
const std::string path = dbis::gPmemPath + "tree_bench.data";
constexpr auto POOL_SIZE = 1024 * 1024 * 1024 * 4ull; //< 4GB
constexpr auto POOL_SIZE = 1024 * 1024 * 1024 * 1ull; //< 1GB
constexpr auto LAYOUT = "Tree";
/* wBPTree pre-calculations */
......@@ -102,12 +112,74 @@ constexpr uint64_t ipow(uint64_t base, int exp, uint64_t result = 1) {
}
/* Tree relevant calculated parameters*/
constexpr auto LEAFKEYS = getLeafKeysPBPTree<5>(); //< 5 iterations should be enough
constexpr auto BRANCHKEYS = getBranchKeysPBPTree<5>();
constexpr auto LEAFKEYS = getLeafKeysPBPTree<5>(); ///< 5 iterations should be enough
constexpr auto BRANCHKEYS = getBranchKeysPBPTree<5>() & ~1; ///< make this one even
constexpr auto ELEMENTS = LEAFKEYS*ipow(BRANCHKEYS+1, TARGET_DEPTH);
constexpr auto KEYPOS = ELEMENTS/1;
constexpr auto KEYPOS = ELEMENTS/ELEMENTS;
using TreeType = PBPTree<MyKey, MyTuple, BRANCHKEYS, LEAFKEYS>;
/* Helper for distinction between hybrid and NVM-only structures
http://index-of.co.uk/C++/C++%20Design%20Generic%20Programming%20and%20Design%20Patterns%20Applied.pdf
depending on variable IS_HYBRID different code is generated during compile time
*/
template <int v>
struct Int2Type { enum { value = v }; };
template<typename T, bool isHybrid>
class HybridWrapper {
using Node = typename T::Node;
private:
inline size_t getDepth(const T &tree, Int2Type<true>) const {
return tree.depth;
}
inline size_t getDepth(const T &tree, Int2Type<false>) const {
return tree.depth.get_ro();
}
inline Node getChildAt(const Node &node, const size_t pos, Int2Type<true>) const {
return node.branch->children[pos];
}
inline Node getChildAt(const Node &node, const size_t pos, Int2Type<false>) const {
return node.branch->children.get_ro()[pos];
}
inline void recover(const T &tree, Int2Type<true>) const {
tree.recover();
}
inline void recover(const T &tree, Int2Type<false>) const {
return;
}
public:
inline size_t getDepth(const T &tree) const {
return getDepth(tree, Int2Type<isHybrid>());
}
inline Node getFirstChild(const Node &node) const {
return getChildAt(node, 0, Int2Type<isHybrid>());
}
inline Node getChildAt(const Node &node, const size_t pos) const {
return getChildAt(node, pos, Int2Type<isHybrid>());
}
inline void recover(const T &tree) const {
recover(tree, Int2Type<isHybrid>());
}
};
auto hybridWrapperPtr = new HybridWrapper<TreeType, IS_HYBRID>();
auto &hybridWrapper = *hybridWrapperPtr;
using TreeType = BitPBPTree<MyKey, MyTuple, BRANCHKEYS, LEAFKEYS>;
/*=== Insert Function ===*/
void insert(persistent_ptr<TreeType> &tree) {
......
......@@ -37,23 +37,15 @@ static void BM_TreeGet(benchmark::State &state) {
} else {
LOG("Warning: " << path << " already exists");
pop = pool<root>::open(path, LAYOUT);
//pop.root()->treeRef.recover(); //< hybrids only
hybridWrapper.recover(*pop.root()->tree);
}
const auto tree = pop.root()->tree;
auto &treeRef = *tree;
//treeRef.printBranchNode(0, treeRef.rootNode.branch);
/* Getting a leaf node */
auto d = hybridWrapper.getDepth(treeRef);
auto node = treeRef.rootNode;
/* hybrid versions */
//auto d = treeRef.depth;
//while ( d-- > 0) node = node.branch->children[0];
/* nvm-only trees */
auto d = treeRef.depth.get_ro();
while ( d-- > 0) node = node.branch->children.get_ro()[0];
while ( d-- > 0) node = hybridWrapper.getFirstChild(node);
auto leaf = node.leaf;
/* BENCHMARKING */
......@@ -66,8 +58,11 @@ static void BM_TreeGet(benchmark::State &state) {
//treeRef.printBranchNode(0, treeRef.rootNode.branch);
std::cout << "Elements:" << ELEMENTS << '\n';
transaction::run(pop, [&] { delete_persistent<TreeType>(tree); });
pop.close();
std::experimental::filesystem::remove_all(path);
}
BENCHMARK(BM_TreeGet);//->Apply(KeyRangeArguments);
BENCHMARK(BM_TreeGet);
BENCHMARK_MAIN();
......@@ -15,7 +15,7 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <filesystem>
#include <experimental/filesystem>
#include "common.hpp"
#include "utils/PersistEmulation.hpp"
......@@ -39,8 +39,8 @@ static void BM_TreeInsert(benchmark::State &state) {
});
} else {
LOG("Warning: " << path << " already exists");
auto n = std::filesystem::remove_all(path);
pop = pool<root>::create(path, LAYOUT);
auto n = std::experimental::filesystem::remove_all(path);
pop = pool<root>::create(path, LAYOUT, POOL_SIZE);
transaction::run(pop, [&] {
delete_persistent<TreeType>(pop.root()->tree);
pop.root()->tree = make_persistent<TreeType>();
......@@ -50,8 +50,7 @@ static void BM_TreeInsert(benchmark::State &state) {
auto &treeRef = *tree;
/* Getting the leaf node */
auto leaf = treeRef.rootNode.leaf;
//treeRef.printLeafNode(0, leaf);
auto &leaf = treeRef.rootNode.leaf;
const auto reqTup = MyTuple(KEYPOS, KEYPOS * 100, KEYPOS * 1.0);
TreeType::SplitInfo splitInfo;
......@@ -62,7 +61,7 @@ static void BM_TreeInsert(benchmark::State &state) {
state.PauseTiming();
std::cout.setstate(std::ios_base::failbit);
treeRef.rootNode = treeRef.newLeafNode();
leaf = treeRef.rootNode.leaf;
treeRef.depth = 0;
prepare(tree);
dbis::PersistEmulation::getBytesWritten();
state.ResumeTiming();
......@@ -79,7 +78,10 @@ static void BM_TreeInsert(benchmark::State &state) {
std::cout.clear();
std::cout << "Writes:" << dbis::PersistEmulation::getBytesWritten() << '\n';
std::cout << "Elements:" << ELEMENTS << '\n';
transaction::run(pop, [&] { delete_persistent<TreeType>(tree); });
pop.close();
std::experimental::filesystem::remove_all(path);
}
BENCHMARK(BM_TreeInsert);
......@@ -88,15 +90,15 @@ BENCHMARK_MAIN();
/* preparing inserts */
void prepare(const persistent_ptr<TreeType> tree) {
auto &treeRef = *tree;
auto insertLoop = [&treeRef](int start, int end) {
auto insertLoop = [&treeRef](const auto start, const auto end) {
for (auto j = start; j < end + 1; ++j) {
auto tup = MyTuple(j, j * 100, j * 1.0);
treeRef.insert(j, tup);
}
};
switch (KEYPOS) {
case 1 /*first*/: insertLoop(2, ELEMENTS); break;
case ELEMENTS /*last*/: insertLoop(1, ELEMENTS-1);break;
case ELEMENTS/2 /*middle*/: {insertLoop(1, KEYPOS-1); insertLoop(KEYPOS+1, ELEMENTS);}
case 1 /*first*/: insertLoop(2, LEAFKEYS); break;
case ELEMENTS /*last*/: insertLoop(1, LEAFKEYS-1);break;
case ELEMENTS/2 /*middle*/: {insertLoop(1, KEYPOS-1); insertLoop(KEYPOS+1, LEAFKEYS);}
}
}
......@@ -15,7 +15,7 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <filesystem>
#include <experimental/filesystem>
#include "common.hpp"
#include "utils/PersistEmulation.hpp"
......@@ -39,8 +39,8 @@ static void BM_TreeSplit(benchmark::State &state) {
});
} else {
LOG("Warning: " << path << " already exists");
auto n = std::filesystem::remove_all(path);
pop = pool<root>::create(path, LAYOUT);
auto n = std::experimental::filesystem::remove_all(path);
pop = pool<root>::create(path, LAYOUT, POOL_SIZE);
transaction::run(pop, [&] {
delete_persistent<TreeType>(pop.root()->tree);
pop.root()->tree = make_persistent<TreeType>();
......@@ -48,10 +48,7 @@ static void BM_TreeSplit(benchmark::State &state) {
}
auto tree = pop.root()->tree;
auto &treeRef = *tree;
/* Getting the leaf node */
auto leaf = treeRef.rootNode.leaf;
//treeRef.printLeafNode(0, leaf);
auto &leaf = treeRef.rootNode.leaf;
const auto reqTup = MyTuple(ELEMENTS+1, (ELEMENTS+1) * 100, (ELEMENTS+1) * 1.0);
TreeType::SplitInfo splitInfo;
......@@ -62,10 +59,9 @@ static void BM_TreeSplit(benchmark::State &state) {
state.PauseTiming();
std::cout.setstate(std::ios_base::failbit);
treeRef.rootNode = treeRef.newLeafNode();
leaf = treeRef.rootNode.leaf;
treeRef.depth = 0;
prepare(tree);
dbis::PersistEmulation::getBytesWritten();
//treeRef.printLeafNode(0, leaf);
state.ResumeTiming();
treeRef.splitLeafNode(leaf, &splitInfo);
......@@ -81,7 +77,9 @@ static void BM_TreeSplit(benchmark::State &state) {
std::cout.clear();
std::cout << "Writes:" << dbis::PersistEmulation::getBytesWritten() << '\n';
std::cout << "Elements:" << ELEMENTS << '\n';
transaction::run(pop, [&] { delete_persistent<TreeType>(tree); });
pop.close();
std::experimental::filesystem::remove_all(path);
}
BENCHMARK(BM_TreeSplit);
......@@ -90,7 +88,7 @@ BENCHMARK_MAIN();
/* preparing inserts */
void prepare(const persistent_ptr<TreeType> tree) {
auto &treeRef = *tree;
for (auto j = 1; j < ELEMENTS+1; ++j) {
for (auto j = 1; j < LEAFKEYS+1; ++j) {
auto tup = MyTuple(j, j * 100, j * 1.0);
treeRef.insert(j, tup);
}
......
......@@ -37,7 +37,7 @@ static void BM_TreeTraverse(benchmark::State &state) {
} else {
LOG("Warning: " << path << " already exists");
pop = pool<root>::open(path, LAYOUT);
//pop.root()->treeRef.recover(); //< Hybrids only
hybridWrapper.recover(*pop.root()->tree);
}
auto tree = pop.root()->tree;
auto &treeRef = *tree;
......@@ -46,25 +46,20 @@ static void BM_TreeTraverse(benchmark::State &state) {
/* BENCHMARKING */
for (auto _ : state) {
/* Getting a leaf node */
auto d = hybridWrapper.getDepth(treeRef);
auto node = treeRef.rootNode;
/* hybrid versions *//*
auto d = treeRef.depth;
while ( --d > 0)
node = node.branch->children[treeRef.lookupPositionInBranchNode(node.branch, KEYPOS)];*/
/* NVM-only versions */
auto d = treeRef.depth.get_ro();
while ( --d > 0)
node = node.branch->children.get_ro()[treeRef.lookupPositionInBranchNode(node.branch, KEYPOS)];
while ( --d > 0) node =
hybridWrapper.getChildAt(node, treeRef.lookupPositionInBranchNode(node.branch, KEYPOS));
benchmark::DoNotOptimize(
leaf = node.leaf
);
//auto p = treeRef.lookupPositionInLeafNode(leaf, 1);
}
//treeRef.printBranchNode(0, treeRef.rootNode.branch);
std::cout << "Elements:" << ELEMENTS << "\n";
transaction::run(pop, [&] { delete_persistent<TreeType>(tree); });
pop.close();
std::experimental::filesystem::remove_all(path);
}
BENCHMARK(BM_TreeTraverse);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment