int MemTable::KeyComparator::operator()(const char* prefix_len_key1,
const char* prefix_len_key2) const {
// Internal keys are encoded as length-prefixed strings.
+ PERF_COUNTER_ADD(user_key_comparison_count, 1);
+ PERF_TIMER_GUARD(user_key_comparison_time);
+ PERF_TIMER_START(user_key_comparison_time);
Slice k1 = GetLengthPrefixedSlice(prefix_len_key1);
Slice k2 = GetLengthPrefixedSlice(prefix_len_key2);
- return comparator.Compare(k1, k2);
+ int r = comparator.Compare(k1, k2);
+
+/* char l1 = *prefix_len_key1 - 8;
+ char l2 = *prefix_len_key2 - 8;
+ size_t min_len = (l1 < l2) ? l1 : l2;
+ int r = memcmp(prefix_len_key1+1, prefix_len_key2+1, min_len);
+
+ if (r == 0) {
+ if (l1 < l2) r = -1;
+ else if (l1 > l2) r = +1;
+ else {
+ uint64_t anum = *(uint64_t*)prefix_len_key1 + l1 + 1;
+ uint64_t bnum = *(uint64_t*)prefix_len_key2 + l1 + 1;
+ if (anum > bnum) {
+ r = -1;
+ } else if (anum < bnum) {
+ r = +1;
+ }
+*/
+/* const char* end = prefix_len_key1 + l1;
+ const char* pos2 = prefix_len_key2 + l2 + 8;
+ for(const char* pos = end + 8; pos != end; --pos, --pos2 ){
+ if (*pos < *pos2) {
+ r = -1;
+ break;
+ } else if (*pos > *pos2) {
+ r = +1;
+ break;
+ }
+ }*/
+/* }
+ }*/
+ PERF_TIMER_STOP(user_key_comparison_time);
+ return r;
}
int MemTable::KeyComparator::operator()(const char* prefix_len_key,
const Slice& key)
const {
+ PERF_COUNTER_ADD(user_key_comparison_count, 1);
+ PERF_TIMER_GUARD(user_key_comparison_time);
+ PERF_TIMER_START(user_key_comparison_time);
// Internal keys are encoded as length-prefixed strings.
Slice a = GetLengthPrefixedSlice(prefix_len_key);
- return comparator.Compare(a, key);
+ int r = comparator.Compare(a, key);
+/* char l1 = *prefix_len_key - 8;
+ char l2 = key.size() - 8;
+ size_t min_len = (l1 < l2) ? l1 : l2;
+ int r = memcmp(prefix_len_key+1, key.data(), min_len);
+
+ if (r == 0) {
+ if (l1 < l2) r = -1;
+ else if (l1 > l2) r = +1;
+ else {
+ const char* end = prefix_len_key + l1;
+ const char* pos2 = key.data() + key.size() + 8;
+ for(const char* pos = end + 8; pos != end; --pos, --pos2 ){
+ if (*pos < *pos2) {
+ r = -1;
+ break;
+ } else if (*pos > *pos2) {
+ r = +1;
+ break;
+ }
+ }
+ }
+ }*/
+
+ PERF_TIMER_STOP(user_key_comparison_time);
+ return r;
+}
+
+int MemTable::KeyComparator::operator()(const char* prefix_len_key,
+ const ParsedInternalKey& key)
+ const {
+ PERF_TIMER_GUARD(user_key_comparison_time);
+ PERF_TIMER_START(user_key_comparison_time);
+ // Internal keys are encoded as length-prefixed strings.
+ Slice k1 = GetLengthPrefixedSlice(prefix_len_key);
+ int r = comparator.Compare(k1, key);
+ PERF_TIMER_STOP(user_key_comparison_time);
+ return r;
}
Slice MemTableRep::UserKey(const char* key) const {
#include <stdlib.h>
#include <algorithm>
#include <atomic>
+#include "rocksdb/slice.h"
+#include "util/coding.h"
#include "port/port.h"
#include "util/allocator.h"
#include "util/random.h"
+#include "db/dbformat.h"
+//#include "port/port.h"
namespace rocksdb {
// Return true if key is greater than the data stored in "n". Null n
// is considered infinite. n should not be head_.
bool KeyIsAfterNode(const char* key, Node* n) const;
+ bool KeyIsAfterNode(const ParsedInternalKey& key, Node* n) const;
// Returns the earliest node with a key >= key.
// Return nullptr if there is no such node.
// node isn't conveniently available.
void FindSpliceForLevel(const char* key, Node* before, Node* after, int level,
Node** out_prev, Node** out_next);
+ void FindSpliceForLevel(const ParsedInternalKey& key, Node* before, Node* after, int level,
+ Node** out_prev, Node** out_next);
// Recomputes Splice levels from highest_level (inclusive) down to
// lowest_level (inclusive).
void RecomputeSpliceLevels(const char* key, Splice* splice,
int recompute_level);
+ void RecomputeSpliceLevels(const ParsedInternalKey& key, Splice* splice,
+ int recompute_level);
// No copying allowed
InlineSkipList(const InlineSkipList&);
return (n != nullptr) && (compare_(n->Key(), key) < 0);
}
+template <class Comparator>
+bool InlineSkipList<Comparator>::KeyIsAfterNode(const ParsedInternalKey& key,
+ Node* n) const {
+ // nullptr n is considered infinite
+ assert(n != head_);
+ return (n != nullptr) && (compare_(n->Key(), key) < 0);
+}
+
template <class Comparator>
typename InlineSkipList<Comparator>::Node*
InlineSkipList<Comparator>::FindGreaterOrEqual(const char* key) const {
}
}
+template <class Comparator>
+void InlineSkipList<Comparator>::FindSpliceForLevel(const ParsedInternalKey& key,
+ Node* before, Node* after,
+ int level, Node** out_prev,
+ Node** out_next) {
+ while (true) {
+ Node* next = before->Next(level);
+ assert(before == head_ || next == nullptr ||
+ KeyIsAfterNode(next->Key(), before));
+ assert(before == head_ || KeyIsAfterNode(key, before));
+ if (next == after || !KeyIsAfterNode(key, next)) {
+ // found it
+ *out_prev = before;
+ *out_next = next;
+ return;
+ }
+ before = next;
+ }
+}
+
template <class Comparator>
void InlineSkipList<Comparator>::RecomputeSpliceLevels(const char* key,
Splice* splice,
}
}
+template <class Comparator>
+void InlineSkipList<Comparator>::RecomputeSpliceLevels(const ParsedInternalKey& key,
+ Splice* splice,
+ int recompute_level) {
+ 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,
+ &splice->prev_[i], &splice->next_[i]);
+ }
+}
+
template <class Comparator>
template <bool UseCAS>
void InlineSkipList<Comparator>::Insert(const char* key, Splice* splice,
}
assert(max_height <= kMaxPossibleHeight);
+/* ParsedInternalKey key_int;
+ ParseInternalKey(GetLengthPrefixedSlice(key), &key_int);*/
+ const char* key_int = key;
+
int recompute_height = 0;
if (splice->height_ < max_height) {
// Either splice has never been used or max_height has grown since
// our chances of success.
++recompute_height;
} else if (splice->prev_[recompute_height] != head_ &&
- !KeyIsAfterNode(key, splice->prev_[recompute_height])) {
+ !KeyIsAfterNode(key_int, splice->prev_[recompute_height])) {
// key is from before splice
if (allow_partial_splice_fix) {
// skip all levels with the same node without more comparisons
// we're pessimistic, recompute everything
recompute_height = max_height;
}
- } else if (KeyIsAfterNode(key, splice->next_[recompute_height])) {
+ } else if (KeyIsAfterNode(key_int, splice->next_[recompute_height])) {
// key is from after splice
if (allow_partial_splice_fix) {
Node* bad = splice->next_[recompute_height];
}
assert(recompute_height <= max_height);
if (recompute_height > 0) {
- RecomputeSpliceLevels(key, splice, recompute_height);
+ RecomputeSpliceLevels(key_int, splice, recompute_height);
}
bool splice_is_valid = true;
// 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_int, splice->prev_[i], nullptr, i, &splice->prev_[i],
&splice->next_[i]);
// Since we've narrowed the bracket for level i, we might have
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_int, splice->prev_[i], nullptr, i, &splice->prev_[i],
&splice->next_[i]);
}
assert(splice->next_[i] == nullptr ||