Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
code
PMem-based Data Structures
Commits
7878b2b4
Commit
7878b2b4
authored
Jun 15, 2020
by
Philipp Götze
Browse files
Integrated PCM and small adjustments to benchmarks
parent
237b37fd
Pipeline
#673
failed with stages
in 1 minute and 54 seconds
Changes
15
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
bench/trees/tree_balance.cpp
View file @
7878b2b4
...
...
@@ -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
<<
"
\n
LEAFKEYS: "
<<
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) *
Uns
ortedMoves);
// pop.flush(&donorRef.values.get_ro(), sizeof(MyTuple) *
Uns
ortedMoves);
// pop.flush(&donorRef.keys.get_ro(), sizeof(MyKey) *
S
ortedMoves);
// pop.flush(&donorRef.values.get_ro(), sizeof(MyTuple) *
S
ortedMoves);
// 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
)
{
...
...
bench/trees/tree_erase.cpp
View file @
7878b2b4
...
...
@@ -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
...
...
bench/trees/tree_get.cpp
View file @
7878b2b4
...
...
@@ -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
=
...
...
bench/trees/tree_insert.cpp
View file @
7878b2b4
...
...
@@ -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
...
...
bench/trees/tree_merge.cpp
View file @
7878b2b4
...
...
@@ -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
)
<<
"
\n
LEAFKEYS: "
<<
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
();
...
...
bench/trees/tree_split.cpp
View file @
7878b2b4
...
...
@@ -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
)
<<
"
\n
LEAFKEYS: "
<<
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
();