From f0ed1371d6d35df51761ea7965287b16eea15450 Mon Sep 17 00:00:00 2001 From: Russell Sears Date: Mon, 30 Mar 2020 16:13:37 -0700 Subject: [PATCH] reduce the number of calls to operator< made by lower_bound and upper_bound #2877 --- fdbclient/VersionedMap.h | 35 ++++++++++++++++++++++++++++------- flow/IndexedSet.h | 14 ++++++++++---- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/fdbclient/VersionedMap.h b/fdbclient/VersionedMap.h index 8f49f4e25ec..ae1b4531474 100644 --- a/fdbclient/VersionedMap.h +++ b/fdbclient/VersionedMap.h @@ -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 - void lower_bound(const Reference>& p, Version at, const X& x, std::vector*>& f){ + void lower_bound(const Reference>& p, Version at, const X& x, std::vector*>& f, std::vector& 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->datadata - lower_bound(p->child(!less, at), at, x, f); + lower_bound(p->child(!less, at), at, x, f, lessThan); } template - void upper_bound(const Reference>& p, Version at, const X& x, std::vector*>& f){ + void lower_bound(const Reference>& p, Version at, const X& x, std::vector*>& f) { + std::vector lessThan; + lower_bound(p, at, x, f, lessThan); + } + + template + void upper_bound(const Reference>& p, Version at, const X& x, std::vector*>& f, std::vector& 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 + void upper_bound(const Reference>& p, Version at, const X& x, std::vector*>& f){ + std::vector lessThan; + upper_bound(p, at, x, f, lessThan); + } + template void move(Version at, std::vector*>& f){ ASSERT(f.size()); diff --git a/flow/IndexedSet.h b/flow/IndexedSet.h index 4ed75056e54..99188c13aea 100644 --- a/flow/IndexedSet.h +++ b/flow/IndexedSet.h @@ -700,6 +700,7 @@ int IndexedSet::insert(const std::vector>& 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; @@ -995,6 +996,7 @@ template typename IndexedSet::iterator IndexedSet::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); @@ -1009,13 +1011,15 @@ template typename IndexedSet::iterator IndexedSet::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); @@ -1027,13 +1031,15 @@ template typename IndexedSet::iterator IndexedSet::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);