[RocksDB] Fix skiplist sequential insertion optimization

Summary: The original optimization missed updating links other than the lowest level.

Test Plan: make check; perf_context_test

Reviewers: dhruba

Reviewed By: dhruba

CC: leveldb, adsharma

Differential Revision: https://reviews.facebook.net/D13119
This commit is contained in:
Haobo Xu 2013-09-26 02:12:10 -07:00
parent e0aa19a94e
commit 08740b15a4

View File

@ -107,6 +107,7 @@ class SkipList {
// Used for optimizing sequential insert patterns // Used for optimizing sequential insert patterns
Node* prev_[kMaxHeight]; Node* prev_[kMaxHeight];
int prev_height_;
inline int GetMaxHeight() const { inline int GetMaxHeight() const {
return static_cast<int>( return static_cast<int>(
@ -267,6 +268,10 @@ typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOr
Node* x = prev[0]; Node* x = prev[0];
Node* next = x->Next(0); Node* next = x->Next(0);
if ((x == head_) || KeyIsAfterNode(key, x)) { if ((x == head_) || KeyIsAfterNode(key, x)) {
// Adjust all relevant insertion points to the previous entry
for (int i = 1; i < prev_height_; i++) {
prev[i] = x;
}
return next; return next;
} }
} }
@ -275,6 +280,9 @@ typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOr
int level = GetMaxHeight() - 1; int level = GetMaxHeight() - 1;
while (true) { while (true) {
Node* next = x->Next(level); Node* next = x->Next(level);
// Make sure the lists are sorted.
// If x points to head_ or next points nullptr, it is trivially satisfied.
assert((x == head_) || (next == nullptr) || KeyIsAfterNode(next->key, x));
if (KeyIsAfterNode(key, next)) { if (KeyIsAfterNode(key, next)) {
// Keep searching in this list // Keep searching in this list
x = next; x = next;
@ -337,6 +345,7 @@ SkipList<Key,Comparator>::SkipList(Comparator cmp, Arena* arena)
arena_(arena), arena_(arena),
head_(NewNode(0 /* any key will do */, kMaxHeight)), head_(NewNode(0 /* any key will do */, kMaxHeight)),
max_height_(reinterpret_cast<void*>(1)), max_height_(reinterpret_cast<void*>(1)),
prev_height_(1),
rnd_(0xdeadbeef) { rnd_(0xdeadbeef) {
for (int i = 0; i < kMaxHeight; i++) { for (int i = 0; i < kMaxHeight; i++) {
head_->SetNext(i, nullptr); head_->SetNext(i, nullptr);
@ -378,6 +387,7 @@ void SkipList<Key,Comparator>::Insert(const Key& key) {
prev_[i]->SetNext(i, x); prev_[i]->SetNext(i, x);
} }
prev_[0] = x; prev_[0] = x;
prev_height_ = height;
} }
template<typename Key, class Comparator> template<typename Key, class Comparator>