@@ -114,7 +114,7 @@ func (it *Iterator) SeekGE(key []byte, flags base.SeekGEFlags) *base.InternalKV
114
114
return kv
115
115
}
116
116
}
117
- _ , it .nd , _ = it .seekForBaseSplice (key )
117
+ _ , it .nd = it .seekForBaseSplice (key )
118
118
if it .nd == it .list .tail || it .nd == it .upperNode {
119
119
return nil
120
120
}
@@ -142,7 +142,7 @@ func (it *Iterator) SeekPrefixGE(prefix, key []byte, flags base.SeekGEFlags) *ba
142
142
func (it * Iterator ) SeekLT (key []byte , flags base.SeekLTFlags ) * base.InternalKV {
143
143
// NB: the top-level Iterator has already adjusted key based on
144
144
// the upper-bound.
145
- it .nd , _ , _ = it .seekForBaseSplice (key )
145
+ it .nd , _ = it .seekForBaseSplice (key )
146
146
if it .nd == it .list .head || it .nd == it .lowerNode {
147
147
return nil
148
148
}
@@ -259,53 +259,73 @@ func (it *Iterator) decodeKey() {
259
259
it .kv .K .Trailer = it .nd .keyTrailer
260
260
}
261
261
262
- func (it * Iterator ) seekForBaseSplice (key []byte ) (prev , next * node , found bool ) {
263
- ikey := base .MakeSearchKey (key )
264
-
262
+ func (it * Iterator ) seekForBaseSplice (key []byte ) (prev , next * node ) {
265
263
prev = it .list .head
266
264
for level := int (it .list .Height () - 1 ); level >= 0 ; level -- {
267
265
268
266
// Search this level for the key.
267
+ prevLevelNext := next
269
268
for {
270
269
// Assume prev.key < key.
271
270
next = it .list .getNext (prev , level )
271
+
272
+ // Before performing a key comparison, check if the next pointer
273
+ // equals prevLevelNext. The pointer comparison is significantly
274
+ // cheaper than a key comparison.
275
+ //
276
+ // It's not unlikely for consecutive levels to have the same next
277
+ // pointer. We use [maxHeight]=20 levels, and with each higher
278
+ // height the probability a node extends one more rung of the tower
279
+ // is 1/e.
280
+ //
281
+ // The skiplist may contain nodes with keys between the (prev,next)
282
+ // pair of nodes that make up the previous level's splice. Let's
283
+ // divide these nodes into the L nodes with keys < key and the R
284
+ // nodes with keys > key. Only a subset of these nodes may have
285
+ // towers that reach [level].
286
+ //
287
+ // Of the nodes in R that reach [level], we only care about the one
288
+ // with the smallest key. If there are no nodes in R that reach
289
+ // [level], then this level's splice's next pointer will be the same
290
+ // as the level above's splice's next pointer. We can perform a
291
+ // cheap pointer comparison of [next] and [prevLevelNext] to
292
+ // determine this.
293
+ //
294
+ // (Note that we must still skip over any of the nodes in L that are
295
+ // high enough to reach [level], and each of these nodes will
296
+ // require a key comparison.)
297
+ //
298
+ // (< key) (≥ key)
299
+ // prev prevLevelNext
300
+ // +---------+ +---------+
301
+ // | | | |
302
+ // | level+1 |------------------------> | |
303
+ // | | | |
304
+ // | | next | |
305
+ // | | +--------+ | |
306
+ // | level |--...--| |--...--> | |
307
+ // | | | | | |
308
+ // | | | | | |
309
+ // +---------+ +--------+ +---------+
310
+ if next == prevLevelNext {
311
+ break
312
+ }
272
313
if next == it .list .tail {
273
314
// Tail node, so done.
274
315
break
275
316
}
276
317
277
318
offset , size := next .keyOffset , next .keySize
278
319
nextKey := it .list .arena .buf [offset : offset + size ]
279
- cmp := it .list .cmp (ikey . UserKey , nextKey )
280
- if cmp < 0 {
281
- // We are done for this level, since prev.key < key < next.key.
320
+ cmp := it .list .cmp (key , nextKey )
321
+ if cmp <= 0 {
322
+ // We are done for this level, since prev.key < key <= next.key.
282
323
break
283
324
}
284
- if cmp == 0 {
285
- // User-key equality.
286
- if ikey .Trailer == next .keyTrailer {
287
- // Internal key equality.
288
- found = true
289
- break
290
- }
291
- if ikey .Trailer > next .keyTrailer {
292
- // We are done for this level, since prev.key < key < next.key.
293
- break
294
- }
295
- }
296
325
// Keep moving right on this level.
297
326
prev = next
298
327
}
299
-
300
- if found {
301
- if level != 0 {
302
- // next is pointing at the target node, but we need to find previous on
303
- // the bottom level.
304
- prev = it .list .getPrev (next , 0 )
305
- }
306
- break
307
- }
308
328
}
309
329
310
- return prev , next , found
330
+ return prev , next
311
331
}
0 commit comments