Skip to content

Commit

Permalink
reduce the number of calls to operator< made by lower_bound and upper…
Browse files Browse the repository at this point in the history
…_bound #2877
  • Loading branch information
sears committed Mar 30, 2020
1 parent f92ef73 commit f0ed137
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 11 deletions.
35 changes: 28 additions & 7 deletions fdbclient/VersionedMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,30 +114,51 @@ namespace PTreeImpl {
return contains(p->child(!less, at), at, x);
}

// TODO: Remove the number of invocations of operator<, and replace with something closer to memcmp.
// and same for upper_bound.
template<class T, class X>
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f){
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f, std::vector<bool>& lessThan){
if (!p) {
while (f.size() && !(x < f.back()->data))
while (f.size() && !(lessThan.back())) {
f.pop_back();
lessThan.pop_back();
}
return;
}
f.push_back(p.getPtr());
bool less = x < p->data;
lessThan.push_back(less);
if (!less && !(p->data<x)) return; // x == p->data
lower_bound(p->child(!less, at), at, x, f);
lower_bound(p->child(!less, at), at, x, f, lessThan);
}

template<class T, class X>
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f){
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f) {
std::vector<bool> lessThan;
lower_bound(p, at, x, f, lessThan);
}

template<class T, class X>
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f, std::vector<bool>& lessThan){
if (!p) {
while (f.size() && !(x < f.back()->data))
while (f.size() && !(x < f.back()->data)) {
f.pop_back();
lessThan.pop_back();
}
return;
}
f.push_back(p.getPtr());
upper_bound(p->child(!(x < p->data), at), at, x, f);
bool less = x < p->data;
lessThan.push_back(less);
upper_bound(p->child(!less, at), at, x, f, lessThan);
}


template<class T, class X>
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f){
std::vector<bool> lessThan;
upper_bound(p, at, x, f, lessThan);
}

template<class T, bool forward>
void move(Version at, std::vector<const PTree<T>*>& f){
ASSERT(f.size());
Expand Down
14 changes: 10 additions & 4 deletions flow/IndexedSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,7 @@ int IndexedSet<T,Metric>::insert(const std::vector<std::pair<T,Metric>>& dataVec
// traverse to find insert point
bool foundNode = false;
while (true){
// TODO: remove implicit double invocation of memcmp
d = t->data < data;
if (!d)
blockEnd = t;
Expand Down Expand Up @@ -995,6 +996,7 @@ template <class Key>
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::find(const Key &key) const {
Node* t = root;
while (t){
// TODO: avoid indirect double invocation of memcmp
int d = t->data < key;
if (!d && !(key < t->data)) // t->data == key
return iterator(t);
Expand All @@ -1009,13 +1011,15 @@ template <class Key>
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::lower_bound(const Key &key) const {
Node* t = root;
if (!t) return iterator();
bool less;
while (true) {
Node *n = t->child[ t->data < key ];
less = t->data < key;
Node *n = t->child[less];
if (!n) break;
t = n;
}

if (t->data < key)
if (less)
moveIterator<1>(t);

return iterator(t);
Expand All @@ -1027,13 +1031,15 @@ template <class Key>
typename IndexedSet<T,Metric>::iterator IndexedSet<T,Metric>::upper_bound(const Key &key) const {
Node* t = root;
if (!t) return iterator();
bool not_less;
while (true) {
Node *n = t->child[ !(key < t->data) ];
not_less = !(key < t->data);
Node *n = t->child[not_less];
if (!n) break;
t = n;
}

if (!(key < t->data))
if (not_less)
moveIterator<1>(t);

return iterator(t);
Expand Down

0 comments on commit f0ed137

Please sign in to comment.