diff --git a/memtable/inlineskiplist.h b/memtable/inlineskiplist.h index 505b73d28a7c6a70ba37409103bd1b8027c4ea67..6262fc6913fbfb1a0a1b945656c65d83760499cc 100644 --- a/memtable/inlineskiplist.h +++ b/memtable/inlineskiplist.h @@ -239,6 +239,7 @@ class InlineSkipList { // point to a node that is before the key, and after should point to // a node that is after the key. after should be nullptr if a good after // node isn't conveniently available. + template void FindSpliceForLevel(const char* key, Node* before, Node* after, int level, Node** out_prev, Node** out_next); @@ -446,6 +447,9 @@ InlineSkipList::FindGreaterOrEqual(const char* key) const { Node* last_bigger = nullptr; while (true) { Node* next = x->Next(level); + if (next != nullptr) { + PREFETCH(next->Next(level), 0, 1); + } // Make sure the lists are sorted assert(x == head_ || next == nullptr || KeyIsAfterNode(next->Key(), x)); // Make sure we haven't overshot during our search @@ -485,6 +489,9 @@ InlineSkipList::FindLessThan(const char* key, Node** prev, while (true) { assert(x != nullptr); Node* next = x->Next(level); + if (next != nullptr) { + PREFETCH(next->Next(level), 0, 1); + } assert(x == head_ || next == nullptr || KeyIsAfterNode(next->Key(), x)); assert(x == head_ || KeyIsAfterNode(key, x)); if (next != last_not_after && KeyIsAfterNode(key, next)) { @@ -535,6 +542,9 @@ uint64_t InlineSkipList::EstimateCount(const char* key) const { while (true) { assert(x == head_ || compare_(x->Key(), key) < 0); Node* next = x->Next(level); + if (next != nullptr) { + PREFETCH(next->Next(level), 0, 1); + } if (next == nullptr || compare_(next->Key(), key) >= 0) { if (level == 0) { return count; @@ -642,12 +652,21 @@ void InlineSkipList::InsertWithHint(const char* key, void** hint) { } template +template void InlineSkipList::FindSpliceForLevel(const char* key, Node* before, Node* after, int level, Node** out_prev, Node** out_next) { while (true) { Node* next = before->Next(level); + if (next != nullptr) { + PREFETCH(next->Next(level), 0, 1); + } + if (prefetch_before == true) { + if (next != nullptr && level>0) { + PREFETCH(next->Next(level-1), 0, 1); + } + } assert(before == head_ || next == nullptr || KeyIsAfterNode(next->Key(), before)); assert(before == head_ || KeyIsAfterNode(key, before)); @@ -668,7 +687,7 @@ void InlineSkipList::RecomputeSpliceLevels(const char* key, assert(recompute_level > 0); assert(recompute_level <= splice->height_); for (int i = recompute_level - 1; i >= 0; --i) { - FindSpliceForLevel(key, splice->prev_[i + 1], splice->next_[i + 1], i, + FindSpliceForLevel(key, splice->prev_[i + 1], splice->next_[i + 1], i, &splice->prev_[i], &splice->next_[i]); } } @@ -796,7 +815,7 @@ void InlineSkipList::Insert(const char* key, Splice* splice, // search, because it should be unlikely that lots of nodes have // been inserted between prev[i] and next[i]. No point in using // next[i] as the after hint, because we know it is stale. - FindSpliceForLevel(key, splice->prev_[i], nullptr, i, &splice->prev_[i], + FindSpliceForLevel(key, splice->prev_[i], nullptr, i, &splice->prev_[i], &splice->next_[i]); // Since we've narrowed the bracket for level i, we might have @@ -811,7 +830,7 @@ void InlineSkipList::Insert(const char* key, Splice* splice, for (int i = 0; i < height; ++i) { if (i >= recompute_height && splice->prev_[i]->Next(i) != splice->next_[i]) { - FindSpliceForLevel(key, splice->prev_[i], nullptr, i, &splice->prev_[i], + FindSpliceForLevel(key, splice->prev_[i], nullptr, i, &splice->prev_[i], &splice->next_[i]); } assert(splice->next_[i] == nullptr ||