Commit 7878b2b4 authored by Philipp Götze's avatar Philipp Götze

Integrated PCM and small adjustments to benchmarks

parent 237b37fd
Pipeline #673 failed with stages
in 1 minute and 54 seconds
......@@ -17,7 +17,13 @@
#include "common.hpp"
#include "utils/PersistEmulation.hpp"
#ifdef ENABLE_PCM
#include <cpucounters.h>
#endif
uint64_t pmmwrites = 0;
uint64_t pmmreads = 0;
uint64_t modBytes = 0; ///< modified Bytes
constexpr auto ArraySize = L3 / TARGET_LEAF_SIZE;
using ArrayType = pmem::obj::array<pptr<TreeType::LeafNode>, ArraySize>;
......@@ -39,6 +45,18 @@ void prepare(const pptr<TreeType> &tree, const pptr<TreeType::LeafNode> &leaf2);
/* Get benchmarks on Tree */
static void BM_TreeBalance(benchmark::State &state) {
#ifdef ENABLE_PCM
PCM *pcm_ = PCM::getInstance();
auto s = pcm_->program();
if (s != PCM::Success) {
std::cerr << "Error creating PCM instance: " << s << std::endl;
if (s == PCM::PMUBusy)
pcm_->resetPMU();
else
exit(0);
}
#endif
std::cout << "BRANCHKEYS: " << BRANCHKEYS << "\nLEAFKEYS: " << LEAFKEYS << "\n";
pool<root> pop;
......@@ -72,25 +90,23 @@ static void BM_TreeBalance(benchmark::State &state) {
leaf2 = root->receiver;
pop.drain();
/* BENCHMARKING */
for (auto _ : state) {
state.PauseTiming();
std::cout.setstate(std::ios_base::failbit);
const auto leafNodePos = std::rand() % ArraySize;
auto donorNode = (*donorArray)[leafNodePos];
auto receiverNode = (*receiverArray)[leafNodePos];
#ifdef ENABLE_PCM
SocketCounterState before_sstate;
SocketCounterState after_sstate;
#endif
/// Lambda function for measured part (needed twice)
auto benchmark = [&pop, &treeRef](
pptr<TreeType::LeafNode> &donorNode,
pptr<TreeType::LeafNode> &receiverNode) {
auto &donorRef = *donorNode;
auto &receiverRef = *receiverNode;
dbis::PersistEmulation::getBytesWritten();
state.ResumeTiming();
benchmark::DoNotOptimize(*donorNode);
benchmark::DoNotOptimize(*receiverNode);
// transaction::run(pop, [&] {
treeRef.balanceLeafNodes(donorNode, receiverNode);
// });
benchmark::DoNotOptimize(*donorNode);
benchmark::DoNotOptimize(*receiverNode);
constexpr auto Balanced = ((LEAFKEYS - 1) / 2 + LEAFKEYS) / 2;
constexpr auto SortedMoves = (LEAFKEYS - 1) / 2 + LEAFKEYS - Balanced;
......@@ -99,45 +115,93 @@ static void BM_TreeBalance(benchmark::State &state) {
// pop.flush(donorRef.bits);
// pop.flush(&donorRef.slot.get_ro(),
// sizeof(donorRef.slot.get_ro()) + sizeof(donorRef.bits.get_ro()));
// pop.flush(&donorRef.keys.get_ro(), sizeof(MyKey) * UnsortedMoves);
// pop.flush(&donorRef.values.get_ro(), sizeof(MyTuple) * UnsortedMoves);
// pop.flush(&donorRef.keys.get_ro(), sizeof(MyKey) * SortedMoves);
// pop.flush(&donorRef.values.get_ro(), sizeof(MyTuple) * SortedMoves);
// pop.flush(&donorRef.keys.get_ro()[(LEAFKEYS - 1) / 2], sizeof(MyKey) * UnsortedMoves);
// pop.flush(&donorRef.values.get_ro()[(LEAFKEYS - 1) / 2], sizeof(MyTuple) * UnsortedMoves);
// donorNode.flush(pop);
pop.flush(receiverRef.numKeys);
// pop.flush(receiverRef.bits);
// pop.flush(&receiverRef.bits.get_ro(),
// sizeof(receiverRef.bits.get_ro()) + sizeof(receiverRef.fp.get_ro()));
// sizeof(receiverRef.bits.get_ro()) + sizeof(receiverRef.fp.get_ro()));
// pop.flush(&receiverRef.slot.get_ro(),
// sizeof(receiverRef.slot.get_ro()) + sizeof(receiverRef.bits.get_ro()));
pop.flush(&receiverRef.keys.get_ro()[(LEAFKEYS - 1) / 2], sizeof(MyKey) * SortedMoves);
pop.flush(&receiverRef.values.get_ro()[(LEAFKEYS - 1) / 2], sizeof(MyTuple) * SortedMoves);
pop.flush(&receiverRef.keys.get_ro(), sizeof(MyKey) * SortedMoves);
pop.flush(&receiverRef.values.get_ro(), sizeof(MyTuple) * SortedMoves);
// pop.flush(&receiverRef.keys.get_ro()[(LEAFKEYS - 1) / 2], sizeof(MyKey) * UnsortedMoves);
// pop.flush(&receiverRef.values.get_ro()[(LEAFKEYS - 1) / 2], sizeof(MyTuple) * UnsortedMoves);
// receiverNode.flush(pop);
pop.drain();
state.PauseTiming();
benchmark::DoNotOptimize(*donorNode);
benchmark::DoNotOptimize(*receiverNode);
benchmark::ClobberMemory();
};
/// BENCHMARK Writes
if (pmmwrites == 0) {
auto donorNode = (*donorArray)[0];
auto receiverNode = (*receiverArray)[0];
dbis::PersistEmulation::getBytesWritten();
#ifdef ENABLE_PCM
before_sstate = getSocketCounterState(1);
#endif
benchmark(donorNode, receiverNode);
#ifdef ENABLE_PCM
after_sstate = getSocketCounterState(1);
pmmreads = getBytesReadFromPMM(before_sstate, after_sstate);
pmmwrites = getBytesWrittenToPMM(before_sstate, after_sstate);
#endif
modBytes = dbis::PersistEmulation::getBytesWritten();
*donorNode = *leaf; ///< reset the modified node
*receiverNode = *leaf2; ///< reset the modified node
state.ResumeTiming();
donorNode.flush(pop);
receiverNode.flush(pop);
pop.drain();
}
/// BENCHMARKING
std::cout.setstate(std::ios_base::failbit);
std::srand(std::time(nullptr));
for (auto _ : state) {
const auto leafNodePos = std::rand() % ArraySize;
auto donorNode = (*donorArray)[leafNodePos];
auto receiverNode = (*receiverArray)[leafNodePos];
auto &donorRef = *donorNode;
auto &receiverRef = *receiverNode;
auto start = std::chrono::high_resolution_clock::now();
benchmark(donorNode, receiverNode);
auto end = std::chrono::high_resolution_clock::now();
// treeRef.printLeafNode(0, donorNode);
// treeRef.printLeafNode(0, receiverNode);
donorRef = *leaf; ///< reset the modified node
receiverRef = *leaf2; ///< reset the modified node
donorNode.flush(pop);
receiverNode.flush(pop);
pop.drain();
auto elapsed_seconds =
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
state.SetIterationTime(elapsed_seconds.count());
}
// treeRef.printLeafNode(0, leaf);
std::cout.clear();
std::cout << "Writes:" << dbis::PersistEmulation::getBytesWritten() << '\n';
// treeRef.printLeafNode(0, leaf);
// treeRef.printLeafNode(0, leaf2);
std::cout << "Iterations:" << state.iterations() << '\n';
std::cout << "PMM Reads:" << pmmreads << '\n';
std::cout << "Writes:" << modBytes << '\n';
std::cout << "PMM Writes:" << pmmwrites << '\n';
std::cout << "Elements:" << ELEMENTS << '\n';
transaction::run(pop, [&] {
delete_persistent<TreeType>(tree);
delete_persistent<ArrayType>(donorArray);
delete_persistent<ArrayType>(receiverArray);
});
pop.close();
pmempool_rm(path.c_str(), 0);
}
BENCHMARK(BM_TreeBalance);
BENCHMARK(BM_TreeBalance)->UseManualTime();
BENCHMARK_MAIN();
void prepare(pmem::obj::pool<root> &pop, pobj_alloc_class_desc alloc_class) {
......
......@@ -102,20 +102,21 @@ static void BM_TreeErase(benchmark::State &state) {
treeRef.eraseFromLeafNodeAtPosition(leafNode, pos, KEYPOS);
//});
pop.flush(leafRef.numKeys);
// pop.flush(leafRef.bits);
// pop.flush(leafRef.numKeys);
pop.flush(leafRef.bits);
// pop.flush(&leafRef.slot.get_ro(),
// sizeof(leafRef.slot.get_ro()) + sizeof(leafRef.bits.get_ro()));
// pop.flush(&leafRef.bits.get_ro(),
// sizeof(leafRef.bits.get_ro()) + sizeof(leafRef.fp.get_ro()));
// pop.flush(&leafRef.keys.get_ro()[pos], sizeof(MyKey));
// pop.flush(&leafRef.values.get_ro()[pos], sizeof(MyTuple));
pop.flush(&leafRef.keys.get_ro()[pos], (LEAFKEYS - 1 - pos) * sizeof(MyKey));
pop.flush(&leafRef.values.get_ro()[pos], (LEAFKEYS - 1 - pos) * sizeof(MyTuple));
// pop.flush(&leafRef.keys.get_ro()[pos], (LEAFKEYS - 1 - pos) * sizeof(MyKey));
// pop.flush(&leafRef.values.get_ro()[pos], (LEAFKEYS - 1 - pos) * sizeof(MyTuple));
pop.drain();
// leafNode.persist(pop);
benchmark::DoNotOptimize(*leafNode);
benchmark::ClobberMemory();
};
/// BENCHMARK Writes
......
......@@ -75,7 +75,7 @@ static void BM_TreeGet(benchmark::State &state) {
static constexpr auto SlotSize = ((LEAFKEYS+1 + 7) / 8) * 8;
static constexpr auto HashSize = ((LEAFKEYS + 7) / 8) * 8;
static constexpr auto BitsetSize = ((LEAFKEYS + 63) / 64) * 8;
static constexpr auto SearchSize = BitsetSize +16;
static constexpr auto SearchSize = BitsetSize + HashSize + 16;
static constexpr auto PaddingSize = (64 - SearchSize % 64) % 64;
struct alignas(64) DRAMLeafNode {
......@@ -83,18 +83,18 @@ static void BM_TreeGet(benchmark::State &state) {
//slot[0] = 0;
}
DRAMLeafNode(const TreeType::LeafNode &other)
: //slot(other.slot.get_ro()),
: slot(other.slot.get_ro()),
bits(other.bits.get_ro()),
//fp(other.fp.get_ro()),
// fp(other.fp.get_ro()),
nextLeaf(nullptr),
prevLeaf(nullptr),
keys(other.keys.get_ro())
// values(other.values.get_ro()),
{}
//std::array<uint8_t, LEAFKEYS+1> slot;
std::array<uint8_t, LEAFKEYS+1> slot;
std::bitset<LEAFKEYS> bits;
//std::array<uint8_t, LEAFKEYS> fp;
// std::array<uint8_t, LEAFKEYS> fp;
DRAMLeafNode *nextLeaf;
DRAMLeafNode *prevLeaf;
char padding[PaddingSize];
......@@ -103,14 +103,17 @@ static void BM_TreeGet(benchmark::State &state) {
};
*/
/// Both PMem and DRAM
auto &tree = pop.root()->tree;
insert(tree, 0);
auto &treeRef = *tree;
tree.flush(pop);
auto &leafArray = pop.root()->leafArray;
auto &leafArray = pop.root()->leafArray; ///< PMem
auto &leaf = treeRef.rootNode.leaf;
leaf.flush(pop);
/// PMem considerations
///*
transaction::run(pop, [&] {
leafArray = make_persistent<LeafArray>();
for (int i = 0; i < ArraySize; ++i) {
......@@ -120,6 +123,7 @@ static void BM_TreeGet(benchmark::State &state) {
}
});
pop.drain();
//*/
/// DRAM considerations
/*
......@@ -143,21 +147,25 @@ for (auto _ : state) {
auto start = std::chrono::high_resolution_clock::now();
benchmark::DoNotOptimize(*leafNode);
treeRef.lookupPositionInLeafNode(leafNode, KEYPOS);
treeRef.lookupPositionInLeafNode(leafNode, KEYPOS); ///< PMem variant
/// DRAM considerations
/*
// auto pos = 0u;
// const auto &nodeRef = *leafNode;
// const auto hash = (uint8_t)(key & 0xFF);
// const auto &keys = nodeRef.keys;
const auto &nodeRef = *leafNode;
const auto &keys = nodeRef.keys;
// const auto num = nodeRef.numKeys;
// const auto &slots = nodeRef.slot;
const auto &slots = nodeRef.slot;
// const auto &bits = nodeRef.bits;
// const auto hash = (uint8_t)(key & 0xFF);
// const auto &hashs = nodeRef.fp;
// for (; pos < LEAFKEYS; ++pos)
// if (bits.test(pos) && keys[pos] == key) break;
// if (//hashs[pos] == hash &&
// bits.test(pos) && keys[pos] == key) break;
// for (; pos < num && keys[pos] != key; ++pos);
// auto pos = dbis::binarySearch<false>(keys, 0, num-1, key);
// benchmark::DoNotOptimize(pos);
auto pos = dbis::binarySearch<false>(keys, slots, 1, slots[0], key);
benchmark::DoNotOptimize(pos);
*/
benchmark::DoNotOptimize(*leafNode);
auto end = std::chrono::high_resolution_clock::now();
auto elapsed_seconds =
......
......@@ -104,12 +104,9 @@ static void BM_TreeInsert(benchmark::State &state) {
auto benchmark = [&pop, &treeRef, &reqTup, &pos](
const pptr<TreeType::LeafNode> &leafNode) {
auto &leafRef = *leafNode;
//const auto pos = treeRef.lookupPositionInLeafNode(leafNode, KEYPOS);
// const auto pos = dbis::BitOperations::getFreeZero(leafNode->bits.get_ro());
benchmark::DoNotOptimize(*leafNode);
// transaction::run(pop, [&] {
treeRef.insertInLeafNodeAtPosition(leafNode, pos, KEYPOS, reqTup);
// treeRef.insertInLeafNodeAtLastPosition(leafNode, KEYPOS, reqTup);
//});
pop.flush(leafRef.numKeys);
// pop.flush(leafRef.bits);
......@@ -131,7 +128,6 @@ static void BM_TreeInsert(benchmark::State &state) {
/// BENCHMARK Writes
if (pmmwrites == 0) {
auto &leafNode = (*leafArray)[0];
// auto &leafRef = *leafNode;
dbis::PersistEmulation::getBytesWritten();
#ifdef ENABLE_PCM
......
......@@ -17,7 +17,13 @@
#include "common.hpp"
#include "utils/PersistEmulation.hpp"
#ifdef ENABLE_PCM
#include <cpucounters.h>
#endif
uint64_t pmmwrites = 0;
uint64_t pmmreads = 0;
uint64_t modBytes = 0; ///< modified Bytes
constexpr auto ArraySize = L3 / TARGET_LEAF_SIZE;
using ArrayType = pmem::obj::array<pptr<TreeType::LeafNode>, ArraySize>;
......@@ -39,6 +45,18 @@ void prepare(const pptr<TreeType> &tree, const pptr<TreeType::LeafNode> &leaf);
/* Get benchmarks on Tree */
static void BM_TreeMerge(benchmark::State &state) {
#ifdef ENABLE_PCM
PCM *pcm_ = PCM::getInstance();
auto s = pcm_->program();
if (s != PCM::Success) {
std::cerr << "Error creating PCM instance: " << s << std::endl;
if (s == PCM::PMUBusy)
pcm_->resetPMU();
else
exit(0);
}
#endif
std::cout << "BRANCHKEYS: " << BRANCHKEYS << " - " << sizeof(TreeType::BranchNode)
<< "\nLEAFKEYS: " << LEAFKEYS << " - " << sizeof(TreeType::LeafNode) << "\n";
......@@ -72,59 +90,97 @@ static void BM_TreeMerge(benchmark::State &state) {
}
}
pop.drain();
auto &treeRef = *tree;
/* BENCHMARKING */
for (auto _ : state) {
state.PauseTiming();
std::cout.setstate(std::ios_base::failbit);
const auto leafNodePos = std::rand() % ArraySize;
auto sourceNode = (*sourceArray)[leafNodePos];
auto targetNode = (*targetArray)[leafNodePos];
#ifdef ENABLE_PCM
SocketCounterState before_sstate;
SocketCounterState after_sstate;
#endif
/// Lambda function for measured part (needed twice)
auto benchmark = [&pop, &treeRef](
pptr<TreeType::LeafNode> &sourceNode,
pptr<TreeType::LeafNode> &targetNode) {
auto &sourceRef = *sourceNode;
auto &targetRef = *targetNode;
dbis::PersistEmulation::getBytesWritten();
state.ResumeTiming();
//benchmark::DoNotOptimize(*sourceNode);
//benchmark::DoNotOptimize(*targetNode);
benchmark::DoNotOptimize(*sourceNode);
benchmark::DoNotOptimize(*targetNode);
// transaction::run(pop, [&] {
treeRef.mergeLeafNodes(targetNode, sourceNode);
// delete_persistent<TreeType::LeafNode>(sourceNode);
// });
//benchmark::DoNotOptimize(*sourceNode);
//benchmark::DoNotOptimize(*targetNode);
pop.flush(targetRef.numKeys);
//pop.flush(targetRef.bits);
// pop.flush(targetRef.bits);
// pop.flush(&targetRef.bits.get_ro(),
// sizeof(targetRef.bits.get_ro()) + sizeof(targetRef.fp.get_ro()));
// pop.flush(&targetRef.slot.get_ro(),
// sizeof(targetRef.slot.get_ro()) + sizeof(targetRef.bits.get_ro()));
//pop.flush(&targetRef.keys.get_ro()[(LEAFKEYS + 1) / 2], sizeof(MyKey) * (LEAFKEYS - 1) / 2);
//pop.flush(&targetRef.values.get_ro()[(LEAFKEYS + 1) / 2], sizeof(MyTuple) * (LEAFKEYS - 1) / 2);
targetNode.flush(pop);
pop.flush(&targetRef.keys.get_ro()[(LEAFKEYS + 1) / 2], sizeof(MyKey) * (LEAFKEYS - 1) / 2);
pop.flush(&targetRef.values.get_ro()[(LEAFKEYS + 1) / 2], sizeof(MyTuple) * (LEAFKEYS - 1) / 2);
// targetNode.flush(pop);
pop.drain();
state.PauseTiming();
//targetNode = treeRef.newLeafNode(leaf2);
benchmark::DoNotOptimize(*sourceNode);
benchmark::DoNotOptimize(*targetNode);
benchmark::ClobberMemory();
};
/// BENCHMARK Writes
if (pmmwrites == 0) {
auto sourceNode = (*sourceArray)[0];
auto targetNode = (*targetArray)[0];
dbis::PersistEmulation::getBytesWritten();
#ifdef ENABLE_PCM
before_sstate = getSocketCounterState(1);
#endif
benchmark(sourceNode, targetNode);
#ifdef ENABLE_PCM
after_sstate = getSocketCounterState(1);
pmmreads = getBytesReadFromPMM(before_sstate, after_sstate);
pmmwrites = getBytesWrittenToPMM(before_sstate, after_sstate);
#endif
modBytes = dbis::PersistEmulation::getBytesWritten();
*targetNode = *leaf2; ///< reset the modified node
// (*sourceArray)[0] = treeRef.newLeafNode(leaf);
targetNode.persist(pop);
}
/// BENCHMARKING
std::cout.setstate(std::ios_base::failbit);
std::srand(std::time(nullptr));
for (auto _ : state) {
const auto leafNodePos = std::rand() % ArraySize;
auto sourceNode = (*sourceArray)[leafNodePos];
auto targetNode = (*targetArray)[leafNodePos];
auto &sourceRef = *sourceNode;
auto &targetRef = *targetNode;
auto start = std::chrono::high_resolution_clock::now();
benchmark(sourceNode, targetNode);
auto end = std::chrono::high_resolution_clock::now();
*targetNode = *leaf2; ///< reset the modified node
state.ResumeTiming();
targetNode.persist(pop);
// (*sourceArray)[leafNodePos] = treeRef.newLeafNode(leaf);
auto elapsed_seconds =
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
state.SetIterationTime(elapsed_seconds.count());
}
// treeRef.printLeafNode(0, leaf);
std::cout.clear();
std::cout << "Writes:" << dbis::PersistEmulation::getBytesWritten() << '\n';
std::cout << "Iterations:" << state.iterations() << '\n';
std::cout << "PMM Reads:" << pmmreads << '\n';
std::cout << "Writes:" << modBytes << '\n';
std::cout << "PMM Writes:" << pmmwrites << '\n';
std::cout << "Elements:" << ELEMENTS << '\n';
transaction::run(pop, [&] {
delete_persistent<TreeType>(tree);
delete_persistent<ArrayType>(sourceArray);
delete_persistent<ArrayType>(targetArray);
});
pop.close();
pmempool_rm(path.c_str(), 0);
}
BENCHMARK(BM_TreeMerge);
BENCHMARK(BM_TreeMerge)->UseManualTime();
BENCHMARK_MAIN();
......
......@@ -18,7 +18,13 @@
#include <libpmemobj++/container/array.hpp>
#include "common.hpp"
#include "utils/PersistEmulation.hpp"
#ifdef ENABLE_PCM
#include <cpucounters.h>
#endif
uint64_t pmmwrites = 0;
uint64_t pmmreads = 0;
uint64_t modBytes = 0; ///< modified Bytes
constexpr auto ArraySize = L3 / 512; // TARGET_LEAF_SIZE;
struct root {
......@@ -35,6 +41,18 @@ void prepare(const persistent_ptr<TreeType> tree);
/* Get benchmarks on Tree */
static void BM_TreeSplit(benchmark::State &state) {
#ifdef ENABLE_PCM
PCM *pcm_ = PCM::getInstance();
auto s = pcm_->program();
if (s != PCM::Success) {
std::cerr << "Error creating PCM instance: " << s << std::endl;
if (s == PCM::PMUBusy)
pcm_->resetPMU();
else
exit(0);
}
#endif
std::cout << "BRANCHKEYS: " << BRANCHKEYS << " - " << sizeof(TreeType::BranchNode)
<< "\nLEAFKEYS: " << LEAFKEYS << " - " << sizeof(TreeType::LeafNode) << "\n";
......@@ -71,60 +89,107 @@ static void BM_TreeSplit(benchmark::State &state) {
bool split;
auto &treeRef = *tree;
/* BENCHMARKING */
for (auto _ : state) {
state.PauseTiming();
std::cout.setstate(std::ios_base::failbit);
const auto leafNodePos = std::rand() % ArraySize;
auto leafNode = (*leafArray)[leafNodePos];
auto &leafRef = *leafNode;
dbis::PersistEmulation::getBytesWritten();
state.ResumeTiming();
#ifdef ENABLE_PCM
SocketCounterState before_sstate;
SocketCounterState after_sstate;
#endif
/// Lambda function for measured part (needed twice)
auto benchmark = [&pop, &treeRef, &splitInfo](
const pptr<TreeType::LeafNode> &leafNode) {
auto &leafRef = *leafNode;
benchmark::DoNotOptimize(*leafNode);
// transaction::run(pop, [&] {
treeRef.splitLeafNode(leafNode, &splitInfo);
// leafRef.nextLeaf = treeRef.newLeafNode(leafNode);
// });
benchmark::DoNotOptimize(*leafNode);
benchmark::DoNotOptimize(*leafRef.nextLeaf);
pop.flush(leafRef.numKeys);
// pop.flush(leafRef.bits);
// pop.flush(&leafRef.slot.get_ro(),
// sizeof(leafRef.slot.get_ro()) + sizeof(leafRef.bits.get_ro()));
// sizeof(leafRef.slot.get_ro()) + sizeof(leafRef.bits.get_ro()));
// pop.flush(&leafRef.keys.get_ro(), sizeof(MyKey) * (LEAFKEYS)/2);
// pop.flush(&leafRef.values.get_ro(), sizeof(MyTuple) * (LEAFKEYS)/2);
pop.flush(leafRef.nextLeaf->numKeys);
// pop.flush(leafRef.nextLeaf->numKeys);
// pop.flush(leafRef.nextLeaf->bits);
// pop.flush(&leafRef.nextLeaf->bits.get_ro(), + sizeof(leafRef.bits.get_ro())+
// sizeof(leafRef.fp.get_ro()));
// pop.flush(&leafRef.nextLeaf->slot.get_ro(), sizeof(leafRef.slot.get_ro()) +
// sizeof(leafRef.bits.get_ro()));
// sizeof(leafRef.bits.get_ro()));
pop.flush(&leafRef.nextLeaf->keys.get_ro(), sizeof(MyKey) * (LEAFKEYS + 1) / 2);
pop.flush(&leafRef.nextLeaf->values.get_ro(), sizeof(MyTuple) * (LEAFKEYS + 1) / 2);
// leafRef.nextLeaf.flush(pop);
pop.drain();
state.PauseTiming();
benchmark::DoNotOptimize(*leafNode);
benchmark::DoNotOptimize(*leafRef.nextLeaf);
benchmark::ClobberMemory();
};
/// BENCHMARK Writes
if (pmmwrites == 0) {
auto &leafNode = (*leafArray)[0];
dbis::PersistEmulation::getBytesWritten();
#ifdef ENABLE_PCM
before_sstate = getSocketCounterState(1);
#endif
benchmark(leafNode);
#ifdef ENABLE_PCM
after_sstate = getSocketCounterState(1);
pmmreads = getBytesReadFromPMM(before_sstate, after_sstate);
pmmwrites = getBytesWrittenToPMM(before_sstate, after_sstate);
#endif
modBytes = dbis::PersistEmulation::getBytesWritten();
treeRef.depth = 0;
treeRef.rootNode = leaf;
tree.flush(pop);
treeRef.rootNode.leaf.flush(pop);
*leafNode = *leaf; ///< reset the modified node
leafNode.flush(pop);
treeRef.deleteLeafNode(leafNode->nextLeaf);
pop.drain();
}
/// BENCHMARK Timing
std::cout.setstate(std::ios_base::failbit);
std::srand(std::time(nullptr));
for (auto _ : state) {
const auto leafNodePos = std::rand() % ArraySize;
auto leafNode = (*leafArray)[leafNodePos];
auto &leafRef = *leafNode;
auto start = std::chrono::high_resolution_clock::now();
benchmark(leafNode);
auto end = std::chrono::high_resolution_clock::now();
treeRef.depth = 0;
treeRef.rootNode = leaf;
tree.flush(pop);
treeRef.rootNode.leaf.flush(pop);
*leafNode = *leaf; ///< reset the modified node
leafNode.flush(pop);
treeRef.deleteLeafNode(leafRef.nextLeaf);
state.ResumeTiming();
pop.drain();
auto elapsed_seconds =
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
state.SetIterationTime(elapsed_seconds.count());
}
/// Evaluation & cleanup
// treeRef.printLeafNode(0, leaf);
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::cout << "Iterations:" << state.iterations() << '\n';
std::cout << "PMM Reads:" << pmmreads << '\n';
std::cout << "Writes:" << modBytes << '\n';
std::cout << "PMM Writes:" << pmmwrites << '\n';
std::cout << "Elements:" << ELEMENTS << '\n';
pop.close();
pmempool_rm(path.c_str(), 0);
}
BENCHMARK(BM_TreeSplit);
BENCHMARK(BM_TreeSplit)->UseManualTime();
BENCHMARK_MAIN();