github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/batchskl/skl_test.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package batchskl 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "fmt" 21 "testing" 22 "time" 23 24 "github.com/zuoyebang/bitalosdb/internal/base" 25 26 "github.com/stretchr/testify/require" 27 "golang.org/x/exp/rand" 28 ) 29 30 type iterAdapter struct { 31 Iterator 32 } 33 34 func (i *iterAdapter) verify(key *base.InternalKey) bool { 35 valid := key != nil 36 if valid != i.Valid() { 37 panic(fmt.Sprintf("inconsistent valid: %t != %t", valid, i.Valid())) 38 } 39 if valid { 40 if base.InternalCompare(bytes.Compare, *key, i.Key()) != 0 { 41 panic(fmt.Sprintf("inconsistent key: %s != %s", *key, i.Key())) 42 } 43 } 44 return valid 45 } 46 47 func (i *iterAdapter) SeekGE(key []byte) bool { 48 return i.verify(i.Iterator.SeekGE(key)) 49 } 50 51 func (i *iterAdapter) SeekLT(key []byte) bool { 52 return i.verify(i.Iterator.SeekLT(key)) 53 } 54 55 func (i *iterAdapter) First() bool { 56 return i.verify(i.Iterator.First()) 57 } 58 59 func (i *iterAdapter) Last() bool { 60 return i.verify(i.Iterator.Last()) 61 } 62 63 func (i *iterAdapter) Next() bool { 64 return i.verify(i.Iterator.Next()) 65 } 66 67 func (i *iterAdapter) Prev() bool { 68 return i.verify(i.Iterator.Prev()) 69 } 70 71 func (i *iterAdapter) Key() base.InternalKey { 72 return *i.Iterator.Key() 73 } 74 75 func length(s *Skiplist) int { 76 count := 0 77 78 it := iterAdapter{s.NewIter(nil, nil)} 79 for valid := it.First(); valid; valid = it.Next() { 80 count++ 81 } 82 83 return count 84 } 85 86 func lengthRev(s *Skiplist) int { 87 count := 0 88 89 it := iterAdapter{s.NewIter(nil, nil)} 90 for valid := it.Last(); valid; valid = it.Prev() { 91 count++ 92 } 93 94 return count 95 } 96 97 func makeKey(s string) []byte { 98 return []byte(s) 99 } 100 101 type testStorage struct { 102 data []byte 103 } 104 105 func (d *testStorage) add(key string) uint32 { 106 offset := uint32(len(d.data)) 107 d.data = append(d.data, uint8(base.InternalKeyKindSet)) 108 var buf [binary.MaxVarintLen64]byte 109 n := binary.PutUvarint(buf[:], uint64(len(key))) 110 d.data = append(d.data, buf[:n]...) 111 d.data = append(d.data, key...) 112 return offset 113 } 114 115 func (d *testStorage) addBytes(key []byte) uint32 { 116 offset := uint32(len(d.data)) 117 d.data = append(d.data, uint8(base.InternalKeyKindSet)) 118 var buf [binary.MaxVarintLen64]byte 119 n := binary.PutUvarint(buf[:], uint64(len(key))) 120 d.data = append(d.data, buf[:n]...) 121 d.data = append(d.data, key...) 122 return offset 123 } 124 125 func newTestSkiplist(storage *testStorage) *Skiplist { 126 return NewSkiplist(&storage.data, base.DefaultComparer.Compare, 127 base.DefaultComparer.AbbreviatedKey) 128 } 129 130 func TestEmpty(t *testing.T) { 131 key := makeKey("aaa") 132 l := newTestSkiplist(&testStorage{}) 133 it := iterAdapter{l.NewIter(nil, nil)} 134 135 require.False(t, it.Valid()) 136 137 it.First() 138 require.False(t, it.Valid()) 139 140 it.Last() 141 require.False(t, it.Valid()) 142 143 require.False(t, it.SeekGE(key)) 144 require.False(t, it.Valid()) 145 } 146 147 func TestBasic(t *testing.T) { 148 d := &testStorage{} 149 l := newTestSkiplist(d) 150 it := iterAdapter{l.NewIter(nil, nil)} 151 152 require.Nil(t, l.Add(d.add("key1"))) 153 require.Nil(t, l.Add(d.add("key2"))) 154 require.Nil(t, l.Add(d.add("key3"))) 155 156 require.True(t, it.SeekGE(makeKey("key"))) 157 require.EqualValues(t, "key1", it.Key().UserKey) 158 159 require.True(t, it.SeekGE(makeKey("key1"))) 160 require.EqualValues(t, "key1", it.Key().UserKey) 161 162 require.True(t, it.SeekGE(makeKey("key2"))) 163 require.EqualValues(t, "key2", it.Key().UserKey) 164 165 require.True(t, it.SeekGE(makeKey("key3"))) 166 require.EqualValues(t, "key3", it.Key().UserKey) 167 168 require.True(t, it.SeekGE(makeKey("key2"))) 169 require.True(t, it.SeekGE(makeKey("key3"))) 170 } 171 172 func TestSkiplistAdd(t *testing.T) { 173 d := &testStorage{} 174 l := newTestSkiplist(d) 175 it := iterAdapter{l.NewIter(nil, nil)} 176 177 require.Nil(t, l.Add(d.add(""))) 178 require.EqualValues(t, []byte(nil), it.Key().UserKey) 179 require.True(t, it.First()) 180 require.EqualValues(t, []byte{}, it.Key().UserKey) 181 182 require.Nil(t, l.Add(d.add("00002"))) 183 require.True(t, it.SeekGE(makeKey("00002"))) 184 require.EqualValues(t, "00002", it.Key().UserKey) 185 186 require.Nil(t, l.Add(d.add("00001"))) 187 require.True(t, it.SeekGE(makeKey("00001"))) 188 require.EqualValues(t, "00001", it.Key().UserKey) 189 190 require.Nil(t, l.Add(d.add("00004"))) 191 require.True(t, it.SeekGE(makeKey("00004"))) 192 require.EqualValues(t, "00004", it.Key().UserKey) 193 194 require.Nil(t, l.Add(d.add("00003"))) 195 require.True(t, it.SeekGE(makeKey("00003"))) 196 require.EqualValues(t, "00003", it.Key().UserKey) 197 198 require.Nil(t, l.Add(d.add("00002"))) 199 require.Equal(t, 6, length(l)) 200 require.Equal(t, 6, lengthRev(l)) 201 } 202 203 func TestIteratorNext(t *testing.T) { 204 const n = 100 205 d := &testStorage{} 206 l := newTestSkiplist(d) 207 it := iterAdapter{l.NewIter(nil, nil)} 208 209 require.False(t, it.Valid()) 210 211 it.First() 212 require.False(t, it.Valid()) 213 214 for i := n - 1; i >= 0; i-- { 215 require.Nil(t, l.Add(d.add(fmt.Sprintf("%05d", i)))) 216 } 217 218 it.First() 219 for i := 0; i < n; i++ { 220 require.True(t, it.Valid()) 221 require.EqualValues(t, fmt.Sprintf("%05d", i), it.Key().UserKey) 222 it.Next() 223 } 224 require.False(t, it.Valid()) 225 } 226 227 func TestIteratorPrev(t *testing.T) { 228 const n = 100 229 d := &testStorage{} 230 l := newTestSkiplist(d) 231 it := iterAdapter{l.NewIter(nil, nil)} 232 233 require.False(t, it.Valid()) 234 235 it.Last() 236 require.False(t, it.Valid()) 237 238 for i := 0; i < n; i++ { 239 l.Add(d.add(fmt.Sprintf("%05d", i))) 240 } 241 242 it.Last() 243 for i := n - 1; i >= 0; i-- { 244 require.True(t, it.Valid()) 245 require.EqualValues(t, fmt.Sprintf("%05d", i), string(it.Key().UserKey)) 246 it.Prev() 247 } 248 require.False(t, it.Valid()) 249 } 250 251 func TestIteratorSeekGE(t *testing.T) { 252 const n = 1000 253 d := &testStorage{} 254 l := newTestSkiplist(d) 255 it := iterAdapter{l.NewIter(nil, nil)} 256 257 require.False(t, it.Valid()) 258 it.First() 259 require.False(t, it.Valid()) 260 261 for i := n - 1; i >= 0; i-- { 262 require.Nil(t, l.Add(d.add(fmt.Sprintf("%05d", i*10+1000)))) 263 } 264 265 require.True(t, it.SeekGE(makeKey(""))) 266 require.True(t, it.Valid()) 267 require.EqualValues(t, "01000", it.Key().UserKey) 268 269 require.True(t, it.SeekGE(makeKey("01000"))) 270 require.True(t, it.Valid()) 271 require.EqualValues(t, "01000", it.Key().UserKey) 272 273 require.True(t, it.SeekGE(makeKey("01005"))) 274 require.True(t, it.Valid()) 275 require.EqualValues(t, "01010", it.Key().UserKey) 276 277 require.True(t, it.SeekGE(makeKey("01010"))) 278 require.True(t, it.Valid()) 279 require.EqualValues(t, "01010", it.Key().UserKey) 280 281 require.False(t, it.SeekGE(makeKey("99999"))) 282 require.False(t, it.Valid()) 283 284 require.Nil(t, l.Add(d.add(""))) 285 require.True(t, it.SeekGE([]byte{})) 286 require.True(t, it.Valid()) 287 288 require.True(t, it.SeekGE(makeKey(""))) 289 require.True(t, it.Valid()) 290 } 291 292 func TestIteratorSeekLT(t *testing.T) { 293 const n = 100 294 d := &testStorage{} 295 l := newTestSkiplist(d) 296 it := iterAdapter{l.NewIter(nil, nil)} 297 298 require.False(t, it.Valid()) 299 it.First() 300 require.False(t, it.Valid()) 301 302 for i := n - 1; i >= 0; i-- { 303 require.Nil(t, l.Add(d.add(fmt.Sprintf("%05d", i*10+1000)))) 304 } 305 306 require.False(t, it.SeekLT(makeKey(""))) 307 require.False(t, it.Valid()) 308 309 require.False(t, it.SeekLT(makeKey("01000"))) 310 require.False(t, it.Valid()) 311 312 require.True(t, it.SeekLT(makeKey("01001"))) 313 require.EqualValues(t, "01000", it.Key().UserKey) 314 require.True(t, it.Valid()) 315 316 require.True(t, it.SeekLT(makeKey("01005"))) 317 require.EqualValues(t, "01000", it.Key().UserKey) 318 require.True(t, it.Valid()) 319 320 require.True(t, it.SeekLT(makeKey("01991"))) 321 require.EqualValues(t, "01990", it.Key().UserKey) 322 require.True(t, it.Valid()) 323 324 require.True(t, it.SeekLT(makeKey("99999"))) 325 require.True(t, it.Valid()) 326 require.EqualValues(t, "01990", it.Key().UserKey) 327 328 require.Nil(t, l.Add(d.add(""))) 329 require.False(t, it.SeekLT([]byte{})) 330 require.False(t, it.Valid()) 331 require.True(t, it.SeekLT(makeKey("\x01"))) 332 require.True(t, it.Valid()) 333 require.EqualValues(t, "", it.Key().UserKey) 334 } 335 336 func TestIteratorBounds(t *testing.T) { 337 d := &testStorage{} 338 l := newTestSkiplist(d) 339 for i := 1; i < 10; i++ { 340 require.NoError(t, l.Add(d.add(fmt.Sprintf("%05d", i)))) 341 } 342 343 it := iterAdapter{l.NewIter(makeKey("00003"), makeKey("00007"))} 344 345 for i := 3; i <= 6; i++ { 346 key := makeKey(fmt.Sprintf("%05d", i)) 347 require.True(t, it.SeekGE(key)) 348 require.EqualValues(t, string(key), string(it.Key().UserKey)) 349 } 350 351 for i := 1; i < 3; i++ { 352 key := makeKey(fmt.Sprintf("%05d", i)) 353 require.True(t, it.SeekGE(key)) 354 require.EqualValues(t, string(key), string(it.Key().UserKey)) 355 } 356 357 for i := 7; i < 10; i++ { 358 key := makeKey(fmt.Sprintf("%05d", i)) 359 require.False(t, it.SeekGE(key)) 360 } 361 362 require.True(t, it.SeekGE(makeKey("00006"))) 363 require.EqualValues(t, "00006", it.Key().UserKey) 364 365 require.False(t, it.Next()) 366 367 for i := 4; i <= 7; i++ { 368 key := makeKey(fmt.Sprintf("%05d", i)) 369 require.True(t, it.SeekLT(key)) 370 require.EqualValues(t, fmt.Sprintf("%05d", i-1), string(it.Key().UserKey)) 371 } 372 373 for i := 8; i < 9; i++ { 374 key := makeKey(fmt.Sprintf("%05d", i)) 375 require.True(t, it.SeekLT(key)) 376 require.EqualValues(t, fmt.Sprintf("%05d", i-1), string(it.Key().UserKey)) 377 } 378 379 for i := 1; i < 4; i++ { 380 key := makeKey(fmt.Sprintf("%05d", i)) 381 require.False(t, it.SeekLT(key)) 382 } 383 384 require.True(t, it.SeekLT(makeKey("00004"))) 385 require.EqualValues(t, "00003", it.Key().UserKey) 386 387 require.False(t, it.Prev()) 388 } 389 390 func randomKey(rng *rand.Rand, b []byte) []byte { 391 key := rng.Uint32() 392 key2 := rng.Uint32() 393 binary.LittleEndian.PutUint32(b, key) 394 binary.LittleEndian.PutUint32(b[4:], key2) 395 return b 396 } 397 398 func BenchmarkReadWrite(b *testing.B) { 399 for i := 0; i <= 10; i++ { 400 readFrac := float32(i) / 10.0 401 b.Run(fmt.Sprintf("frac_%d", i*10), func(b *testing.B) { 402 var buf [8]byte 403 d := &testStorage{ 404 data: make([]byte, 0, b.N*10), 405 } 406 l := newTestSkiplist(d) 407 it := l.NewIter(nil, nil) 408 rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) 409 410 b.ResetTimer() 411 for i := 0; i < b.N; i++ { 412 key := randomKey(rng, buf[:]) 413 if rng.Float32() < readFrac { 414 _ = it.SeekGE(key) 415 } else { 416 offset := d.addBytes(buf[:]) 417 _ = l.Add(offset) 418 } 419 } 420 b.StopTimer() 421 }) 422 } 423 } 424 425 func BenchmarkOrderedWrite(b *testing.B) { 426 var buf [8]byte 427 d := &testStorage{ 428 data: make([]byte, 0, b.N*10), 429 } 430 l := newTestSkiplist(d) 431 432 b.ResetTimer() 433 for i := 0; i < b.N; i++ { 434 binary.BigEndian.PutUint64(buf[:], uint64(i)) 435 offset := d.addBytes(buf[:]) 436 _ = l.Add(offset) 437 } 438 } 439 440 func BenchmarkIterNext(b *testing.B) { 441 var buf [8]byte 442 d := &testStorage{ 443 data: make([]byte, 0, 64<<10), 444 } 445 l := newTestSkiplist(d) 446 447 rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) 448 for len(d.data)+20 < cap(d.data) { 449 key := randomKey(rng, buf[:]) 450 offset := d.addBytes(key) 451 _ = l.Add(offset) 452 } 453 454 it := l.NewIter(nil, nil) 455 b.ResetTimer() 456 for i := 0; i < b.N; i++ { 457 if !it.Valid() { 458 it.First() 459 } 460 it.Next() 461 } 462 } 463 464 func BenchmarkIterPrev(b *testing.B) { 465 var buf [8]byte 466 d := &testStorage{ 467 data: make([]byte, 0, 64<<10), 468 } 469 l := newTestSkiplist(d) 470 471 rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) 472 for len(d.data)+20 < cap(d.data) { 473 key := randomKey(rng, buf[:]) 474 offset := d.addBytes(key) 475 _ = l.Add(offset) 476 } 477 478 it := l.NewIter(nil, nil) 479 b.ResetTimer() 480 for i := 0; i < b.N; i++ { 481 if !it.Valid() { 482 it.Last() 483 } 484 it.Prev() 485 } 486 }