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
d8e493d3
Commit
d8e493d3
authored
Jan 13, 2020
by
Philipp Götze
Browse files
🔨
Moved and added new benchmarks
parent
ceabcc8d
Changes
24
Hide whitespace changes
Inline
Side-by-side
src/
bench/CMakeLists.txt
→
bench/CMakeLists.txt
View file @
d8e493d3
include
(
../
../
cmake/Testing.cmake.in
)
include
(
../cmake/Testing.cmake.in
)
do_bench
(
trees/tree_get
)
do_bench
(
trees/tree_traverse
)
do_bench
(
trees/tree_scan
)
do_bench
(
trees/tree_insert
)
do_bench
(
trees/tree_split
)
do_bench
(
trees/tree_erase
)
do_bench
(
trees/tree_balance
)
do_bench
(
trees/tree_merge
)
# PTABLE
#do_bench(ptable/insert ptable)
do_bench
(
ptable/scan ptable
)
...
...
src/
bench/performance_test.cpp
→
bench/performance_test.cpp
View file @
d8e493d3
File moved
src/
bench/ptable/common.hpp
→
bench/ptable/common.hpp
View file @
d8e493d3
...
...
@@ -18,9 +18,9 @@
#ifndef PTABLE_COMMON_H
#define PTABLE_COMMON_H
#include <
chrono
>
#include <
libpmempool.h
>
#include <unistd.h>
#include <
experimental/filesystem
>
#include <
chrono
>
#include "ptable/PTable.hpp"
using
pmem
::
obj
::
make_persistent
;
...
...
@@ -35,7 +35,7 @@ using PTableType = dbis::ptable::PTable<MyKey, MyTuple>;
using
Vector
=
std
::
vector
<
long
int
>
;
using
VectorVector
=
std
::
vector
<
Vector
>
;
const
int
hibit_pos
(
int
n
)
noexcept
;
int
hibit_pos
(
int
n
)
noexcept
;
template
<
size_t
SIZE
>
static
inline
VectorVector
*
createPointVector
(
VectorVector
*
v
);
...
...
@@ -78,7 +78,7 @@ const VectorVector NON_KEY_RANGES = {
Vector
{
0
,
NUM_TUPLES
-
1
,
0
,
NUM_TUPLES
-
1
}
//100,0%
};
const
int
hibit_pos
(
int
n
)
noexcept
{
int
hibit_pos
(
int
n
)
noexcept
{
int
c
=
0
;
while
(
n
>>
1
!=
0
)
{
c
++
;
...
...
@@ -102,13 +102,15 @@ void insert (pool<root> &pop, const std::string &path, size_t entries) {
std
::
vector
<
typename
std
::
chrono
::
duration
<
int64_t
,
std
::
micro
>::
rep
>
measures
;
pop
=
pool
<
root
>::
create
(
path
,
LAYOUT
,
POOL_SIZE
);
const
auto
alloc_class
=
pop
.
ctl_set
<
struct
pobj_alloc_class_desc
>
(
"heap.alloc_class.128.desc"
,
PTableType
::
IndexType
::
AllocClass
);
transaction
::
run
(
pop
,
[
&
]
{
const
auto
tInfo
=
VTableInfo
<
MyKey
,
MyTuple
>
(
"MyTable"
,
{
"a"
,
"b"
,
"c"
,
"d"
});
const
auto
dims
=
Dimensions
({
{
0
,
10
,
ALIGNMENT
},
{
3
,
10
,
ALIGNMENT
}
});
pop
.
root
()
->
pTable
=
make_persistent
<
PTableType
>
(
tInfo
,
dims
);
pop
.
root
()
->
pTable
=
make_persistent
<
PTableType
>
(
alloc_class
,
tInfo
,
dims
);
});
auto
&
pTable
=
pop
.
root
()
->
pTable
;
...
...
src/
bench/ptable/insert.cpp
→
bench/ptable/insert.cpp
View file @
d8e493d3
...
...
@@ -15,7 +15,6 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <experimental/filesystem>
#include "common.hpp"
using
namespace
dbis
::
ptable
;
...
...
@@ -23,7 +22,7 @@ using namespace dbis::ptable;
int
main
()
{
pool
<
root
>
pop
;
std
::
experimental
::
filesystem
::
remove_all
(
path
);
pmempool_rm
(
path
.
c_str
(),
0
);
if
(
access
(
path
.
c_str
(),
F_OK
)
!=
0
)
{
insert
(
pop
,
path
,
NUM_TUPLES
);
}
else
{
...
...
src/
bench/ptable/point.cpp
→
bench/ptable/point.cpp
View file @
d8e493d3
...
...
@@ -25,33 +25,34 @@
using
namespace
dbis
::
ptable
;
static
void
BM_PointQuery
(
benchmark
::
State
&
state
)
{
pool
<
root
>
pop
;
const
std
::
string
path
=
dbis
::
gPmemPath
+
"benchdb"
+
std
::
to_string
(
state
.
range
(
0
))
+
".db"
;
//std::remove(path.c_str());
//
std::remove(path.c_str());
if
(
access
(
path
.
c_str
(),
F_OK
)
!=
0
)
{
insert
(
pop
,
path
,
state
.
range
(
0
));
}
else
{
//std::cerr << "WARNING: Table already exists" << std::endl;
//
std::cerr << "WARNING: Table already exists" << std::endl;
pop
=
pool
<
root
>::
open
(
path
,
LAYOUT
);
}
auto
&
pTable
=
*
pop
.
root
()
->
pTable
;
auto
&
pTable
=
*
pop
.
root
()
->
pTable
;
for
(
auto
_
:
state
)
{
auto
ptp
=
pTable
.
getByKey
(
state
.
range
(
1
));
if
(
ptp
.
getNode
()
!=
nullptr
)
ptp
;
// ptp.createTuple();
else
std
::
cerr
<<
"key not found"
<<
'\n'
;
if
(
ptp
.
getNode
()
!=
nullptr
)
ptp
;
// ptp.createTuple();
else
std
::
cerr
<<
"key not found"
<<
'\n'
;
}
transaction
::
run
(
pop
,
[
&
]
{
delete_persistent
<
PTableType
>
(
pop
.
root
()
->
pTable
);
});
pop
.
close
();
std
::
experimental
::
filesystem
::
remove_all
(
path
);
pmempool_rm
(
path
.
c_str
(),
0
);
}
static
void
VectorArguments
(
benchmark
::
internal
::
Benchmark
*
b
)
{
for
(
const
auto
&
arg
:
POINT_ACCESS
)
b
->
Args
(
arg
);
for
(
const
auto
&
arg
:
POINT_ACCESS
)
b
->
Args
(
arg
);
}
BENCHMARK
(
BM_PointQuery
)
->
Apply
(
VectorArguments
);
...
...
src/
bench/ptable/scan.cpp
→
bench/ptable/scan.cpp
View file @
d8e493d3
...
...
@@ -21,9 +21,7 @@
using
namespace
dbis
::
ptable
;
static
void
BM_RangeScan
(
benchmark
::
State
&
state
)
{
pool
<
root
>
pop
;
if
(
access
(
path
.
c_str
(),
F_OK
)
!=
0
)
{
...
...
@@ -37,20 +35,20 @@ static void BM_RangeScan(benchmark::State &state) {
/* RangeScan using Block iterator */
for
(
auto
_
:
state
)
{
auto
iter
=
pTable
->
rangeScan
(
ColumnRangeMap
({{
0
,
{(
int
)
state
.
range
(
0
),
(
int
)
state
.
range
(
1
)}}}));
for
(
const
auto
&
tp
:
iter
)
{
auto
iter
=
pTable
->
rangeScan
(
ColumnRangeMap
({{
0
,
{(
int
)
state
.
range
(
0
),
(
int
)
state
.
range
(
1
)}}}));
for
(
const
auto
&
tp
:
iter
)
{
tp
;
}
}
pop
.
close
();
}
static
void
KeyRangeArguments
(
benchmark
::
internal
::
Benchmark
*
b
)
{
static
void
KeyRangeArguments
(
benchmark
::
internal
::
Benchmark
*
b
)
{
for
(
const
auto
&
arg
:
KEY_RANGES
)
b
->
Args
(
arg
);
}
BENCHMARK
(
BM_RangeScan
)
->
Apply
(
KeyRangeArguments
);
static
void
BM_NonKeyRangeScan
(
benchmark
::
State
&
state
)
{
pool
<
root
>
pop
;
if
(
access
(
path
.
c_str
(),
F_OK
)
!=
0
)
{
...
...
@@ -64,21 +62,21 @@ static void BM_NonKeyRangeScan(benchmark::State &state) {
/* RangeScan using Block iterator */
for
(
auto
_
:
state
)
{
auto
iter
=
pTable
->
rangeScan
(
ColumnRangeMap
({{
0
,
{(
int
)
state
.
range
(
0
),
(
int
)
state
.
range
(
1
)}},
{
3
,
{(
double
)
state
.
range
(
2
),
(
double
)
state
.
range
(
3
)}}}));
for
(
const
auto
&
tp
:
iter
)
{
auto
iter
=
pTable
->
rangeScan
(
ColumnRangeMap
({{
0
,
{(
int
)
state
.
range
(
0
),
(
int
)
state
.
range
(
1
)}},
{
3
,
{(
double
)
state
.
range
(
2
),
(
double
)
state
.
range
(
3
)}}}));
for
(
const
auto
&
tp
:
iter
)
{
tp
;
}
}
pop
.
close
();
}
static
void
NonKeyRangeArguments
(
benchmark
::
internal
::
Benchmark
*
b
)
{
static
void
NonKeyRangeArguments
(
benchmark
::
internal
::
Benchmark
*
b
)
{
for
(
const
auto
&
arg
:
NON_KEY_RANGES
)
b
->
Args
(
arg
);
}
BENCHMARK
(
BM_NonKeyRangeScan
)
->
Apply
(
NonKeyRangeArguments
);
static
void
BM_PBPTreeKeyScan
(
benchmark
::
State
&
state
)
{
pool
<
root
>
pop
;
if
(
access
(
path
.
c_str
(),
F_OK
)
!=
0
)
{
...
...
@@ -92,7 +90,8 @@ static void BM_PBPTreeKeyScan(benchmark::State &state) {
for
(
auto
_
:
state
)
{
/* Scan via Index scan */
pTable
->
rangeScan2
(
state
.
range
(
0
),
state
.
range
(
1
),
[](
int
k
,
const
PTuple
<
int
,
MyTuple
>
tp
){
tp
;});
pTable
->
rangeScan2
(
state
.
range
(
0
),
state
.
range
(
1
),
[](
int
k
,
const
PTuple
<
int
,
MyTuple
>
tp
)
{
tp
;
});
}
pop
.
close
();
...
...
@@ -100,7 +99,6 @@ static void BM_PBPTreeKeyScan(benchmark::State &state) {
BENCHMARK
(
BM_PBPTreeKeyScan
)
->
Apply
(
KeyRangeArguments
);
static
void
BM_PBPTreeScan
(
benchmark
::
State
&
state
)
{
pool
<
root
>
pop
;
if
(
access
(
path
.
c_str
(),
F_OK
)
!=
0
)
{
...
...
@@ -115,11 +113,10 @@ static void BM_PBPTreeScan(benchmark::State &state) {
for
(
auto
_
:
state
)
{
/* Scan via PTuple iterator */
auto
eIter
=
pTable
.
end
();
auto
iter
=
pTable
.
select
(
[
&
](
const
PTuple
<
int
,
MyTuple
>
&
tp
)
{
return
(
tp
.
get
<
0
>
()
>=
state
.
range
(
0
))
&&
(
tp
.
get
<
0
>
()
<=
state
.
range
(
1
))
&&
(
tp
.
get
<
3
>
()
>=
state
.
range
(
2
))
&&
(
tp
.
get
<
3
>
()
<=
state
.
range
(
3
));
});
auto
iter
=
pTable
.
select
([
&
](
const
PTuple
<
int
,
MyTuple
>
&
tp
)
{
return
(
tp
.
get
<
0
>
()
>=
state
.
range
(
0
))
&&
(
tp
.
get
<
0
>
()
<=
state
.
range
(
1
))
&&
(
tp
.
get
<
3
>
()
>=
state
.
range
(
2
))
&&
(
tp
.
get
<
3
>
()
<=
state
.
range
(
3
));
});
for
(;
iter
!=
eIter
;
iter
++
)
{
iter
;
//(*iter).get<0>();
...
...
@@ -128,9 +125,8 @@ static void BM_PBPTreeScan(benchmark::State &state) {
transaction
::
run
(
pop
,
[
&
]
{
delete_persistent
<
PTableType
>
(
pop
.
root
()
->
pTable
);
});
pop
.
close
();
std
::
experimental
::
filesystem
::
remove_all
(
path
);
pmempool_rm
(
path
.
c_str
(),
0
);
}
BENCHMARK
(
BM_PBPTreeScan
)
->
Apply
(
NonKeyRangeArguments
);
BENCHMARK_MAIN
();
src/
bench/trees/common.hpp
→
bench/trees/common.hpp
View file @
d8e493d3
...
...
@@ -18,175 +18,211 @@
#ifndef DBIS_TREES_COMMON_HPP
#define DBIS_TREES_COMMON_HPP
#include <unistd.h>
#include <chrono>
#include <iostream>
#include <numeric>
#include <unistd.h>
#include <experimental/filesystem>
#include <libpmemobj++/pool.hpp>
#include <libpmemobj++/persistent_ptr.hpp>
#include <libpmempool.h>
#include <libpmemobj++/container/array.hpp>
#include <libpmemobj++/make_persistent.hpp>
#include <libpmemobj++/persistent_ptr.hpp>
#include <libpmemobj++/pool.hpp>
#include <libpmemobj++/transaction.hpp>
#include <numeric>
#define UNIT_TESTS
#include "benchmark/benchmark.h"
#include "PBPTree.hpp"
#include "benchmark/benchmark.h"
using
namespace
dbis
::
pbptrees
;
using
pmem
::
obj
::
delete_persistent
;
using
pmem
::
obj
::
make_persistent
;
using
pmem
::
obj
::
pool
;
using
pmem
::
obj
::
persistent_ptr
;
using
pmem
::
obj
::
pool
;
using
pmem
::
obj
::
transaction
;
/*=== Types and constants ===*/
/* Customization section */
using
MyTuple
=
std
::
tuple
<
int
,
int
,
double
>
;
using
MyTuple
=
std
::
tuple
<
int
,
int
,
double
>
;
using
MyKey
=
unsigned
long
long
;
constexpr
auto
TARGET_BRANCH_SIZE
=
512
;
constexpr
auto
TARGET_LEAF_SIZE
=
256
;
//< 512B best performance
constexpr
auto
TARGET_LEAF_SIZE
=
512
;
constexpr
auto
TARGET_DEPTH
=
1
;
constexpr
auto
IS_HYBRID
=
0
;
const
std
::
string
path
=
dbis
::
gPmemPath
+
"tree_benchSp.data"
;
constexpr
auto
POOL_SIZE
=
1024
*
1024
*
1024
*
4ull
;
//< 1GB
constexpr
auto
MOVE_TO_RIGHT
=
0
;
///< for balance direction
const
std
::
string
path
=
dbis
::
gPmemPath
+
"tree_bench.data"
;
constexpr
auto
POOL_SIZE
=
1024
*
1024
*
1024
*
4ull
;
//< 4GB
constexpr
auto
LAYOUT
=
"Tree"
;
constexpr
auto
NODE_PTR_SIZE
=
24
;
///< 24 Byte (8-tag + 16-pptr)
/* wBPTree pre-calculations */
template
<
unsigned
int
N
>
template
<
unsigned
int
KEYS
>
constexpr
unsigned
int
getBranchKeyswBPTree
()
{
constexpr
auto
keys
=
getBranchKeyswBPTree
<
N
-
1
>
();
constexpr
auto
CL_h
=
keys
+
((
keys
+
63
)
/
64
)
*
8
;
constexpr
auto
CL
=
((
CL_h
+
63
)
/
64
)
*
64
;
constexpr
auto
SIZE
=
CL
+
keys
*
(
sizeof
(
MyKey
)
+
24
)
+
24
;
//< CacheLine structure & n keys & n+1 children
return
(
SIZE
<=
TARGET_BRANCH_SIZE
)
?
keys
:
((
TARGET_BRANCH_SIZE
-
CL
-
24
)
/
(
sizeof
(
MyKey
)
+
24
));
constexpr
auto
CL_h
=
((
KEYS
+
1
+
7
)
/
8
)
*
8
+
((
KEYS
+
63
)
/
64
)
*
8
;
constexpr
auto
CL
=
((
CL_h
+
63
)
/
64
)
*
64
;
///< rounding up
constexpr
auto
SIZE
=
CL
+
KEYS
*
(
sizeof
(
MyKey
)
+
NODE_PTR_SIZE
)
+
NODE_PTR_SIZE
;
///< CacheLine structure & n keys & n+1 children
if
constexpr
(
SIZE
<=
TARGET_BRANCH_SIZE
)
return
KEYS
;
else
return
getBranchKeyswBPTree
<
KEYS
-
1
>
();
}
template
<
>
constexpr
unsigned
int
getBranchKeyswBPTree
<
1
>
()
{
return
((
TARGET_BRANCH_SIZE
-
64
-
24
)
/
(
sizeof
(
MyKey
)
+
24
));
constexpr
size_t
getBranchKeyswBPTree
()
{
constexpr
auto
KEYS
=
((
TARGET_BRANCH_SIZE
-
64
-
NODE_PTR_SIZE
)
/
(
sizeof
(
MyKey
)
+
NODE_PTR_SIZE
));
return
getBranchKeyswBPTree
<
KEYS
>
();
}
template
<
unsigned
int
N
>
constexpr
unsigned
int
getLeafKeyswBPTree
()
{
constexpr
auto
keys
=
getLeafKeyswBPTree
<
N
-
1
>
();
constexpr
auto
CL_h
=
keys
+
((
keys
+
63
)
/
64
)
*
8
;
template
<
size_t
KEYS
>
constexpr
size_t
getLeafKeyswBPTree
()
{
constexpr
auto
CL_h
=
((
KEYS
+
1
+
7
)
/
8
)
*
8
+
((
KEYS
+
63
)
/
64
)
*
8
+
32
;
constexpr
auto
CL
=
((
CL_h
+
63
)
/
64
)
*
64
;
constexpr
auto
SIZE
=
CL
+
32
+
keys
*
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
));
return
(
SIZE
<=
TARGET_LEAF_SIZE
)
?
keys
:
((
TARGET_LEAF_SIZE
-
CL
-
32
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
constexpr
auto
SIZE
=
CL
+
KEYS
*
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
));
if
constexpr
(
SIZE
<=
TARGET_LEAF_SIZE
)
return
KEYS
;
else
return
getLeafKeyswBPTree
<
KEYS
-
1
>
();
// return SIZE <= TARGET_LEAF_SIZE ? KEYS : getLeafKeyswBPTree<KEYS-1>();
}
template
<
>
constexpr
unsigned
int
getLeafKeyswBPTree
<
1
>
()
{
return
((
TARGET_LEAF_SIZE
-
64
-
32
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
constexpr
size_t
getLeafKeyswBPTree
()
{
constexpr
auto
KEYS
=
((
TARGET_LEAF_SIZE
-
64
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
return
getLeafKeyswBPTree
<
KEYS
>
();
}
/* PBPTree pre-calculations */
template
<
unsigned
int
N
>
constexpr
unsigned
int
getBranchKeysPBPTree
()
{
constexpr
size_t
getBranchKeysPBPTree
()
{
return
((
TARGET_BRANCH_SIZE
-
28
)
/
(
sizeof
(
MyKey
)
+
24
));
}
template
<
unsigned
int
N
>
constexpr
unsigned
in
t
getLeafKeysPBPTree
()
{
return
((
TARGET_LEAF_SIZE
-
3
6
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
constexpr
size_
t
getLeafKeysPBPTree
()
{
return
((
TARGET_LEAF_SIZE
-
6
4
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
}
/* FPTree pre-calculations */
template
<
unsigned
int
N
>
constexpr
unsigned
int
getBranchKeysFPTree
()
{
return
((
TARGET_BRANCH_SIZE
-
28
)
/
(
sizeof
(
MyKey
)
+
24
));
constexpr
size_t
getBranchKeysFPTree
()
{
return
((
TARGET_BRANCH_SIZE
-
28
)
/
(
sizeof
(
MyKey
)
+
NODE_PTR_SIZE
));
}
template
<
unsigned
int
N
>
constexpr
unsigned
int
getLeafKeysFPTree
()
{
constexpr
auto
keys
=
getLeafKeysFPTree
<
N
-
1
>
();
constexpr
auto
CL_h
=
keys
+
((
keys
+
63
)
/
64
)
*
8
;
template
<
size_t
KEYS
>
constexpr
size_t
getLeafKeysFPTree
()
{
constexpr
auto
CL_h
=
((
KEYS
+
7
)
/
8
)
*
8
+
((
KEYS
+
63
)
/
64
)
*
8
+
32
;
constexpr
auto
CL
=
((
CL_h
+
63
)
/
64
)
*
64
;
constexpr
auto
SIZE
=
CL
+
32
+
keys
*
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
));
return
(
SIZE
<=
TARGET_LEAF_SIZE
)
?
keys
:
((
TARGET_LEAF_SIZE
-
CL
-
32
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
constexpr
auto
SIZE
=
CL
+
KEYS
*
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
));
if
constexpr
(
SIZE
<=
TARGET_LEAF_SIZE
)
return
KEYS
;
else
return
getLeafKeysFPTree
<
KEYS
-
1
>
();
}
template
<
>
constexpr
unsigned
int
getLeafKeysFPTree
<
1
>
()
{
return
((
TARGET_LEAF_SIZE
-
64
-
32
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
constexpr
size_t
getLeafKeysFPTree
()
{
constexpr
auto
KEYS
=
((
TARGET_LEAF_SIZE
-
64
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
return
getLeafKeysFPTree
<
KEYS
>
();
}
/* BitPBPTree pre-calculations */
template
<
unsigned
int
N
>
constexpr
unsigned
int
getBranchKeysBitPBPTree
()
{
constexpr
auto
keys
=
getBranchKeysBitPBPTree
<
N
-
1
>
();
constexpr
auto
word
=
sizeof
(
unsigned
long
)
*
8
;
constexpr
auto
BM
=
(
keys
+
word
-
1
)
/
word
*
8
;
constexpr
auto
SIZE
=
BM
+
keys
*
(
sizeof
(
MyKey
)
+
24
)
+
24
;
//< bitmap structure & n keys & n+1 children
return
(
SIZE
<=
TARGET_BRANCH_SIZE
)
?
keys
:
((
TARGET_BRANCH_SIZE
-
BM
-
24
)
/
(
sizeof
(
MyKey
)
+
24
));
template
<
size_t
KEYS
>
constexpr
size_t
getBranchKeysBitPBPTree
()
{
constexpr
auto
wordBits
=
sizeof
(
unsigned
long
)
*
8
;
constexpr
auto
BM
=
(
KEYS
+
wordBits
-
1
)
/
wordBits
*
8
;
///< round to necessary words
constexpr
auto
SIZE
=
BM
+
KEYS
*
(
sizeof
(
MyKey
)
+
NODE_PTR_SIZE
)
+
NODE_PTR_SIZE
;
///< bitmap structure & n keys & n+1 children
if
constexpr
(
SIZE
<=
TARGET_BRANCH_SIZE
)
return
KEYS
;
else
return
getBranchKeyswBPTree
<
KEYS
-
1
>
();
}
template
<
>
constexpr
unsigned
int
getBranchKeysBitPBPTree
<
1
>
()
{
return
((
TARGET_BRANCH_SIZE
-
sizeof
(
unsigned
long
)
-
24
)
/
(
sizeof
(
MyKey
)
+
24
));
constexpr
size_t
getBranchKeysBitPBPTree
()
{
constexpr
auto
KEYS
=
(
TARGET_BRANCH_SIZE
-
sizeof
(
unsigned
long
)
-
NODE_PTR_SIZE
)
/
(
sizeof
(
MyKey
)
+
NODE_PTR_SIZE
);
return
getBranchKeysBitPBPTree
<
KEYS
>
();
}
template
<
unsigned
int
N
>
constexpr
unsigned
int
getLeafKeysBitPBPTree
()
{
constexpr
auto
keys
=
getLeafKeysBitPBPTree
<
N
-
1
>
();
constexpr
auto
word
=
sizeof
(
unsigned
long
)
*
8
;
constexpr
auto
BM
=
(
keys
+
word
-
1
)
/
word
*
8
;
constexpr
auto
SIZE
=
BM
+
32
+
keys
*
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
));
return
(
SIZE
<=
TARGET_LEAF_SIZE
)
?
keys
:
((
TARGET_LEAF_SIZE
-
BM
-
32
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
template
<
size_t
KEYS
>
constexpr
size_t
getLeafKeysBitPBPTree
()
{
constexpr
auto
CL_h
=
((
KEYS
+
63
)
/
64
)
*
8
+
32
;
constexpr
auto
CL
=
((
CL_h
+
63
)
/
64
)
*
64
;
constexpr
auto
SIZE
=
CL
+
KEYS
*
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
));
if
constexpr
(
SIZE
<=
TARGET_LEAF_SIZE
)
return
KEYS
;
else
return
getLeafKeysBitPBPTree
<
KEYS
-
1
>
();
}
template
<
>
constexpr
unsigned
int
getLeafKeysBitPBPTree
<
1
>
()
{
return
((
TARGET_LEAF_SIZE
-
sizeof
(
unsigned
long
)
-
32
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
constexpr
size_t
getLeafKeysBitPBPTree
()
{
constexpr
auto
KEYS
=
((
TARGET_LEAF_SIZE
-
64
)
/
(
sizeof
(
MyKey
)
+
sizeof
(
MyTuple
)));
return
getLeafKeysBitPBPTree
<
KEYS
>
();
}
/* Power of function */
constexpr
uint64_t
ipow
(
uint64_t
base
,
int
exp
,
uint64_t
result
=
1
)
{
return
exp
<
1
?
result
:
ipow
(
base
*
base
,
exp
/
2
,
(
exp
%
2
)
?
result
*
base
:
result
);
return
exp
<
1
?
result
:
ipow
(
base
*
base
,
exp
/
2
,
(
exp
%
2
)
?
result
*
base
:
result
);
}
/* Tree relevant calculated parameters*/
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
LEAFKEYS
=
getLeafKeysPBPTree
();
constexpr
auto
BRANCHKEYS
=
getBranchKeysPBPTree
()
&
~
1
;
///< make this one even
constexpr
auto
ELEMENTS
=
LEAFKEYS
*
ipow
(
BRANCHKEYS
+
1
,
TARGET_DEPTH
);
constexpr
auto
KEYPOS
=
1
;
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
};
};
struct
Int2Type
{
enum
{
value
=
v
};
};
template
<
typename
T
,
size_t
arrSize
,
bool
isHybrid
>
struct
getTypes
;
template
<
typename
T
,
size_t
arrSize
>
struct
getTypes
<
T
,
arrSize
,
true
>
{
using
bNodeType
=
typename
T
::
BranchNode
*
;
using
iArrayType
=
std
::
array
<
bNodeType
,
arrSize
>
;
using
iPtrType
=
std
::
unique_ptr
<
iArrayType
>
;
};
template
<
typename
T
,
size_t
arrSize
>
struct
getTypes
<
T
,
arrSize
,
false
>
{
using
bNodeType
=
pptr
<
typename
T
::
BranchNode
>
;
using
iArrayType
=
pmem
::
obj
::
array
<
bNodeType
,
arrSize
>
;
using
iPtrType
=
pptr
<
iArrayType
>
;
};
template
<
typename
T
,
bool
isHybrid
>
template
<
typename
T
,
bool
isHybrid
>
class
HybridWrapper
{
using
Node
=
typename
T
::
Node
;
using
BNode
=
typename
T
::
BranchNode
;
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
{
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
(
T
&
tree
,
Int2Type
<
true
>
)
const
{
tree
.
recover
()
;
inline
Node
&
setChildAt
(
BNode
&
node
,
const
size_t
pos
,
Int2Type
<
true
>
)
const
{
return
node
.
children
[
pos
]
;
}
inline
void
recover
(
const
T
&
tree
,
Int2Type
<
false
>
)
const
{
return
;
inline
Node
&
setChildAt
(
BNode
&
node
,
const
size_t
pos
,
Int2Type
<
false
>
)
const
{
return
node
.
children
.
get_rw
()[
pos
]
;
}
inline
void
recover
(
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
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
>
());
...
...
@@ -196,28 +232,26 @@ class HybridWrapper {
return
getChildAt
(
node
,
pos
,
Int2Type
<
isHybrid
>
());
}
inline
void
recover
(
T
&
tree
)
const
{
re
cover
(
tree
,
Int2Type
<
isHybrid
>
());
inline
Node
&
setChildAt
(
BNode
&
node
,
const
size_t
pos
)
const
{
re
turn
setChildAt
(
node
,
pos
,
Int2Type
<
isHybrid
>
());
}
inline
void
recover
(
T
&
tree
)
const
{
recover
(
tree
,
Int2Type
<
isHybrid
>
());
}
};
auto
hybridWrapperPtr
=
new
HybridWrapper
<
TreeType
,
IS_HYBRID
>
();
auto
&
hybridWrapper
=
*
hybridWrapperPtr
;
/*=== Insert Function ===*/
void
insert
(
persistent_ptr
<
TreeType
>
&
tree
)
{
void
insert
(
const
persistent_ptr
<
TreeType
>
&
tree
,
unsigned
int
target_depth
=
TARGET_DEPTH
)
{
std
::
chrono
::
high_resolution_clock
::
time_point
t_start
,
t_end
;
std
::
vector
<
typename
std
::
chrono
::
duration
<
int64_t
,
std
::
micro
>::
rep
>
measures
;
auto
insertLoopLeaf
=
[
&
](
int
start
)
{
auto
end
=
start
+
(
LEAFKEYS
+
1
)
/
2
;
auto
insertLoopLeaf
=
[
&
](
int
start
,
bool
ohterHalf
=
false
)
{
auto
end
=
start
+
(
LEAFKEYS
+
1
)
/
2
-
((
LEAFKEYS
%
2
==
1
&&
ohterHalf
)
?
1
:
0
)
;
for
(
auto
j
=
start
;
j
<
end
&&
j
<
ELEMENTS
;
++
j
)
{
auto
tup
=
MyTuple
(
j
+
1
,
(
j
+
1
)
*
100
,
(
j
+
1
)
*
1.0
);
/*if (
i
% (ELEMENTS/100) == 0) {
/*if (
j
% (ELEMENTS/100) == 0) {
std::cout << "Inserting tuple: " << (j+1)*100/ELEMENTS << "%\r";
std::cout.flush();
}*/
...
...
@@ -228,47 +262,54 @@ void insert(persistent_ptr<TreeType> &tree) {
measures
.
push_back
(
diff
);
}
};
std
::
function
<
void
(
int
,
int
,
bool
)
>
insertLoopBranch
=
[
&
](
int
start
,
int
depth
,
bool
otherHalf
)
{
auto
nodeRange
=
LEAFKEYS
*
ipow
(
BRANCHKEYS
+
1
,
depth
);
auto
lowerRange
=
LEAFKEYS
*
ipow
(
BRANCHKEYS
+
1
,
depth
-
1
);
std
::
function
<
void
(
int
,
int
,
bool
)
>
insertLoopBranch
=
[
&
](
int
start
,
int
depth
,
bool
otherHalf
)
{
auto
nodeRange
=
LEAFKEYS
*
ipow
(
BRANCHKEYS
+
1
,
depth
);
auto
lowerRange
=
LEAFKEYS
*
ipow
(
BRANCHKEYS
+
1
,
depth
-
1
);
auto
middle
=
(
nodeRange
+
1
)
/
2
;