Permalink
Browse files

Replacing binary search in find_lower() with linear search for small …

…nodes.
  • Loading branch information...
1 parent cba986f commit 9a7c9d9f007893bdd46d9dcd6e050a107eda6164 @bingmann committed Mar 16, 2013
View
@@ -92,6 +92,12 @@ struct btree_default_set_traits
/// Number of slots in each inner node of the tree. Estimated so that each node
/// has a size of about 256 bytes.
static const int innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
+
+ /// As of stx-btree-0.9, the code does linear search in find_lower() and
+ /// find_upper() instead of binary_search, unless the node size is larger
+ /// than this threshold. See notes at
+ /// http://panthema.net/2013/0317-STX-B+Tree-Binary-vs-Linear-Search
+ static const size_t binsearch_threshold = 256;
};
/** Generates default traits for a B+ tree used as a map. It estimates leaf and
@@ -116,6 +122,12 @@ struct btree_default_map_traits
/// Number of slots in each inner node of the tree. Estimated so that each node
/// has a size of about 256 bytes.
static const int innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
+
+ /// As of stx-btree-0.9, the code does linear search in find_lower() and
+ /// find_upper() instead of binary_search, unless the node size is larger
+ /// than this threshold. See notes at
+ /// http://panthema.net/2013/0317-STX-B+Tree-Binary-vs-Linear-Search
+ static const size_t binsearch_threshold = 256;
};
/** @brief Basic class implementing a base B+ tree data structure in memory.
@@ -1605,44 +1617,51 @@ class btree
private:
// *** B+ Tree Node Binary Search Functions
- /// Searches for the first key in the node n less or equal to key. Uses
+ /// Searches for the first key in the node n greater or equal to key. Uses
/// binary search with an optional linear self-verification. This is a
/// template function, because the slotkey array is located at different
/// places in leaf_node and inner_node.
template <typename node_type>
inline int find_lower(const node_type *n, const key_type& key) const
{
- if (n->slotuse == 0) return 0;
+ if ( sizeof(n->slotkey) > traits::binsearch_threshold )
+ {
+ if (n->slotuse == 0) return 0;
- int lo = 0, hi = n->slotuse;
+ int lo = 0, hi = n->slotuse;
- while (lo < hi)
- {
- int mid = (lo + hi) >> 1;
+ while (lo < hi)
+ {
+ int mid = (lo + hi) >> 1;
- if (key_lessequal(key, n->slotkey[mid])) {
- hi = mid; // key <= mid
- }
- else {
- lo = mid + 1; // key > mid
+ if (key_lessequal(key, n->slotkey[mid])) {
+ hi = mid; // key <= mid
+ }
+ else {
+ lo = mid + 1; // key > mid
+ }
}
- }
- BTREE_PRINT("btree::find_lower: on " << n << " key " << key << " -> (" << lo << ") " << hi);
+ BTREE_PRINT("btree::find_lower: on " << n << " key " << key << " -> " << lo << " / " << hi);
- // verify result using simple linear search
- if (selfverify)
- {
- int i = n->slotuse - 1;
- while(i >= 0 && key_lessequal(key, n->slotkey[i]))
- i--;
- i++;
+ // verify result using simple linear search
+ if (selfverify)
+ {
+ int i = 0;
+ while (i < n->slotuse && key_less(n->slotkey[i],key)) ++i;
- BTREE_PRINT("btree::find_lower: testfind: " << i);
- BTREE_ASSERT(i == hi);
- }
+ BTREE_PRINT("btree::find_lower: testfind: " << i);
+ BTREE_ASSERT(i == lo);
+ }
- return hi;
+ return lo;
+ }
+ else // for nodes <= binsearch_threshold do linear search.
+ {
+ int lo = 0;
+ while (lo < n->slotuse && key_less(n->slotkey[lo],key)) ++lo;
+ return lo;
+ }
}
/// Searches for the first key in the node n greater than key. Uses binary
@@ -1652,37 +1671,44 @@ class btree
template <typename node_type>
inline int find_upper(const node_type *n, const key_type& key) const
{
- if (n->slotuse == 0) return 0;
+ if ( sizeof(n->slotkey) > traits::binsearch_threshold )
+ {
+ if (n->slotuse == 0) return 0;
- int lo = 0, hi = n->slotuse;
+ int lo = 0, hi = n->slotuse;
- while (lo < hi)
- {
- int mid = (lo + hi) >> 1;
+ while (lo < hi)
+ {
+ int mid = (lo + hi) >> 1;
- if (key_less(key, n->slotkey[mid])) {
- hi = mid; // key < mid
- }
- else {
- lo = mid + 1; // key >= mid
+ if (key_less(key, n->slotkey[mid])) {
+ hi = mid; // key < mid
+ }
+ else {
+ lo = mid + 1; // key >= mid
+ }
}
- }
- BTREE_PRINT("btree::find_upper: on " << n << " key " << key << " -> (" << lo << ") " << hi);
+ BTREE_PRINT("btree::find_upper: on " << n << " key " << key << " -> " << lo << " / " << hi);
- // verify result using simple linear search
- if (selfverify)
- {
- int i = n->slotuse - 1;
- while(i >= 0 && key_less(key, n->slotkey[i]))
- i--;
- i++;
+ // verify result using simple linear search
+ if (selfverify)
+ {
+ int i = 0;
+ while (i < n->slotuse && key_lessequal(n->slotkey[i],key)) ++i;
- BTREE_PRINT("btree::find_upper testfind: " << i);
- BTREE_ASSERT(i == hi);
- }
+ BTREE_PRINT("btree::find_upper testfind: " << i);
+ BTREE_ASSERT(i == hi);
+ }
- return hi;
+ return lo;
+ }
+ else // for nodes <= binsearch_threshold do linear search.
+ {
+ int lo = 0;
+ while (lo < n->slotuse && key_lessequal(n->slotkey[lo],key)) ++lo;
+ return lo;
+ }
}
public:
@@ -32,7 +32,8 @@ struct BoundTest : public tpunit::TestFixture
)
{}
- struct traits_nodebug
+ template <typename KeyType>
+ struct traits_nodebug : stx::btree_default_set_traits<KeyType>
{
static const bool selfverify = true;
static const bool debug = false;
@@ -43,7 +44,8 @@ struct BoundTest : public tpunit::TestFixture
void test_multi(const unsigned int insnum, const int modulo)
{
- typedef stx::btree_multimap<unsigned int, unsigned int, std::less<unsigned int>, struct traits_nodebug> btree_type;
+ typedef stx::btree_multimap<unsigned int, unsigned int,
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
btree_type bt;
typedef std::multiset<unsigned int> multiset_type;
@@ -34,7 +34,8 @@ struct BulkLoadTest : public tpunit::TestFixture
)
{}
- struct traits_nodebug
+ template <typename KeyType>
+ struct traits_nodebug : stx::btree_default_set_traits<KeyType>
{
static const bool selfverify = true;
static const bool debug = false;
@@ -46,7 +47,7 @@ struct BulkLoadTest : public tpunit::TestFixture
void test_set_instance(size_t numkeys, unsigned int mod)
{
typedef stx::btree_multiset<unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
std::vector<unsigned int> keys (numkeys);
@@ -82,7 +83,7 @@ struct BulkLoadTest : public tpunit::TestFixture
void test_map_instance(size_t numkeys, unsigned int mod)
{
typedef stx::btree_multimap<int, std::string,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
std::vector< std::pair<int,std::string> > pairs (numkeys);
@@ -33,7 +33,8 @@ struct DumpRestoreTest : public tpunit::TestFixture
)
{}
- struct traits_nodebug
+ template <typename KeyType>
+ struct traits_nodebug : stx::btree_default_set_traits<KeyType>
{
static const bool selfverify = true;
static const bool debug = false;
@@ -45,7 +46,7 @@ struct DumpRestoreTest : public tpunit::TestFixture
void test_dump_restore_3200()
{
typedef stx::btree_multiset<unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
std::string dumpstr;
@@ -91,7 +92,7 @@ struct DumpRestoreTest : public tpunit::TestFixture
{ // try restore the btree image using a different instantiation
typedef stx::btree_multiset<long long,
- std::less<long long>, struct traits_nodebug> otherbtree_type;
+ std::less<long long>, traits_nodebug<long long> > otherbtree_type;
otherbtree_type bt3;
@@ -40,7 +40,8 @@ struct IteratorTest : public tpunit::TestFixture
)
{}
- struct traits_nodebug
+ template <typename KeyType>
+ struct traits_nodebug : stx::btree_default_set_traits<KeyType>
{
static const bool selfverify = true;
static const bool debug = false;
@@ -52,7 +53,7 @@ struct IteratorTest : public tpunit::TestFixture
void test_iterator1()
{
typedef stx::btree_multiset<unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
std::vector<unsigned int> vector;
@@ -114,7 +115,7 @@ struct IteratorTest : public tpunit::TestFixture
void test_iterator2()
{
typedef stx::btree_multimap<unsigned int, unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
std::vector< btree_type::value_type > vector;
@@ -175,7 +176,7 @@ struct IteratorTest : public tpunit::TestFixture
void test_iterator3()
{
typedef stx::btree_map<unsigned int, unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
btree_type map;
@@ -472,7 +473,7 @@ struct IteratorTest : public tpunit::TestFixture
void test_iterator4()
{
typedef stx::btree_set<unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
btree_type set;
@@ -699,7 +700,7 @@ struct IteratorTest : public tpunit::TestFixture
void test_iterator5()
{
typedef stx::btree_set<unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
btree_type set;
@@ -794,7 +795,7 @@ struct IteratorTest : public tpunit::TestFixture
void test_erase_iterator1()
{
typedef stx::btree_multimap<int, int,
- std::less<int>, struct traits_nodebug> btree_type;
+ std::less<int>, traits_nodebug<unsigned int> > btree_type;
btree_type map;
@@ -39,7 +39,8 @@ struct LargeTest : public tpunit::TestFixture
)
{}
- struct traits_nodebug
+ template <typename KeyType>
+ struct traits_nodebug : stx::btree_default_set_traits<KeyType>
{
static const bool selfverify = true;
static const bool debug = false;
@@ -51,7 +52,7 @@ struct LargeTest : public tpunit::TestFixture
void test_multi(const unsigned int insnum, const unsigned int modulo)
{
typedef stx::btree_multiset<unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
btree_type bt;
@@ -163,7 +164,7 @@ struct LargeTest : public tpunit::TestFixture
void test_sequence()
{
typedef stx::btree_multiset<unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
btree_type bt;
@@ -30,7 +30,8 @@ struct RelationTest : public tpunit::TestFixture
)
{}
- struct traits_nodebug
+ template <typename KeyType>
+ struct traits_nodebug : stx::btree_default_set_traits<KeyType>
{
static const bool selfverify = true;
static const bool debug = false;
@@ -42,7 +43,7 @@ struct RelationTest : public tpunit::TestFixture
void test_relations()
{
typedef stx::btree_multiset<unsigned int,
- std::less<unsigned int>, struct traits_nodebug> btree_type;
+ std::less<unsigned int>, traits_nodebug<unsigned int> > btree_type;
btree_type bt1, bt2;
Oops, something went wrong.

0 comments on commit 9a7c9d9

Please sign in to comment.