Skip to content

Commit

Permalink
Create twigs when creating new layers.
Browse files Browse the repository at this point in the history
Consider inserting these two keys in sequence:

   www.fart/barf/hello/one/two/three
   www.fart/barf/hello/one/two/four

We previously moved through the following states:

   www.fart #0: /barf/hello/one/two/three

   www.fart #0: [unused suffix] LAYER
     /barf/he #0: llo/one/two/three

   www.fart #0: [unused suffix] LAYER
     /barf/he #0: [unused suffix] LAYER
       llo/one/ #0: two/three

   www.fart #0: [unused suffix] LAYER
     /barf/he #0: [unused suffix] LAYER
       llo/one/ #0: [unused suffix] LAYER
         two/thre #0: e

   www.fart #0: [unused suffix] LAYER
     /barf/he #0: [unused suffix] LAYER
       llo/one/ #0: [unused suffix] LAYER
         two/thre #0: e
         two/four stephentu#1

That created, initialized, and then rendered unused two suffix
structures for the intermediate layers. But there's no need to
create such structures. We can tell while creating a layer whether
we'll need to split it. Now we do this:

   www.fart #0: /barf/hello/one/two/three

   www.fart #0: [unused suffix] LAYER
     /barf/he #0: LAYER
       llo/one/ #0: LAYER
         two/thre #0: e
         two/four stephentu#1

The intermediate layers are created without suffixes. This allocates
about 1/2 as much memory for key suffixes on the URL test.
  • Loading branch information
kohler committed May 4, 2014
1 parent 3b9e9f3 commit 1a731de
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 20 deletions.
56 changes: 36 additions & 20 deletions masstree_insert.hh
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,38 @@ node_base<P>* tcursor<P>::check_leaf_new_layer(nodeversion_type v,
key_type oka(n_->ksuf(kp_));
ka_.shift();
int kc = key_compare(oka, ka_);

// Create a twig of nodes until the suffixes diverge
leaf_type* twig_head = n_;
leaf_type* twig_tail = n_;
while (kc == 0) {
leaf_type* nl = leaf_type::make_root(0, twig_tail, ti);
nl->assign_initialize_for_layer(0, oka);
if (twig_head != n_)
twig_tail->lv_[0] = nl;
else
twig_head = nl;
nl->permutation_ = permuter_type::make_sorted(1);
twig_tail = nl;
oka.shift();
ka_.shift();
kc = key_compare(oka, ka_);
}

// Estimate how much space will be required for keysuffixes
size_t ksufsize;
if (kc && (ka_.has_suffix() || oka.has_suffix()))
if (ka_.has_suffix() || oka.has_suffix())
ksufsize = (std::max(0, ka_.suffix_length())
+ std::max(0, oka.suffix_length())) * (n_->width / 2)
+ n_->iksuf_[0].overhead(n_->width);
else
ksufsize = 0;
leaf_type *nl = leaf_type::make_root(ksufsize, n_, ti);
nl->assign_initialize(0, kc <= 0 ? oka : ka_, ti);
if (kc != 0)
nl->assign_initialize(1, kc <= 0 ? ka_ : oka, ti);
leaf_type *nl = leaf_type::make_root(ksufsize, twig_tail, ti);
nl->assign_initialize(0, kc < 0 ? oka : ka_, ti);
nl->assign_initialize(1, kc < 0 ? ka_ : oka, ti);
nl->lv_[kc > 0] = n_->lv_[kp_];
if (kc != 0) {
nl->lock(*nl, ti.lock_fence(tc_leaf_lock));
nl->lv_[kc < 0] = leafvalue_type::make_empty();
}
if (kc <= 0)
nl->lock(*nl, ti.lock_fence(tc_leaf_lock));
if (kc < 0)
nl->permutation_ = permuter_type::make_sorted(1);
else {
permuter_type permnl = permuter_type::make_sorted(2);
Expand All @@ -110,19 +124,21 @@ node_base<P>* tcursor<P>::check_leaf_new_layer(nodeversion_type v,
// retry. The first keylenx_ write informs a reader that the value is
// in flux, the second informs it of the true value. On x86 we only
// need compiler barriers.
n_->keylenx_[kp_] = sizeof(n_->ikey0_[0]) + 65;
n_->keylenx_[kp_] = n_->unstable_layer_keylenx;
if (twig_tail != n_)
twig_tail->lv_[0] = nl;
fence();
n_->lv_[kp_] = nl;
if (twig_head != n_)
n_->lv_[kp_] = twig_head;
else
n_->lv_[kp_] = nl;
fence();
n_->keylenx_[kp_] = sizeof(n_->ikey0_[0]) + 129;
n_->nksuf_ -= !!oka.length();
n_->keylenx_[kp_] = n_->stable_layer_keylenx;
--n_->nksuf_;
n_->unlock(v);
if (kc != 0) {
n_ = nl;
ki_ = kp_ = kc < 0;
return insert_marker();
} else
return nl;
n_ = nl;
ki_ = kp_ = kc < 0;
return insert_marker();
}

template <typename P>
Expand Down
7 changes: 7 additions & 0 deletions masstree_struct.hh
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ class leaf : public node_base<P> {
typedef typename P::threadinfo_type threadinfo;
typedef stringbag<uint8_t> internal_ksuf_type;
typedef stringbag<uint16_t> external_ksuf_type;
static constexpr int unstable_layer_keylenx = sizeof(ikey_type) + 65;
static constexpr int stable_layer_keylenx = sizeof(ikey_type) + 129;

int8_t extrasize64_;
int8_t nremoved_;
Expand Down Expand Up @@ -494,6 +496,11 @@ class leaf : public node_base<P> {
ikey0_[p] = x->ikey0_[xp];
keylenx_[p] = x->keylenx_[xp];
}
inline void assign_initialize_for_layer(int p, const key_type& ka) {
assert(ka.has_suffix());
ikey0_[p] = ka.ikey();
keylenx_[p] = stable_layer_keylenx;
}
inline void assign_ksuf(int p, Str s, bool initializing, threadinfo& ti) {
if (extrasize64_ <= 0 || !iksuf_[0].assign(p, s))
hard_assign_ksuf(p, s, initializing, ti);
Expand Down

0 comments on commit 1a731de

Please sign in to comment.