github.com/matrixorigin/matrixone@v1.2.0/pkg/common/arenaskl/skl_test.go (about) 1 /* 2 * Copyright 2017 Dgraph Labs, Inc. and Contributors 3 * Modifications copyright (C) 2017 Andy Kimball and Contributors 4 * and copyright (C) 2024 MatrixOrigin Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package arenaskl 20 21 import ( 22 "bytes" 23 "encoding/binary" 24 "fmt" 25 "strconv" 26 "sync" 27 "sync/atomic" 28 "testing" 29 "time" 30 31 "github.com/stretchr/testify/require" 32 "golang.org/x/exp/rand" 33 ) 34 35 const arenaSize = 1 << 20 36 37 // iterAdapter adapts the new Iterator API which returns the key and value from 38 // positioning methods (Seek*, First, Last, Next, Prev) to the old API which 39 // returned a boolean corresponding to Valid. Only used by test code. 40 type iterAdapter struct { 41 *Iterator 42 key []byte 43 val []byte 44 } 45 46 func newIterAdapter(iter *Iterator) *iterAdapter { 47 return &iterAdapter{ 48 Iterator: iter, 49 } 50 } 51 52 func (i *iterAdapter) update(ok bool, key, val []byte) bool { 53 i.key = key 54 i.val = val 55 return ok 56 } 57 58 func (i *iterAdapter) String() string { 59 return "iter-adapter" 60 } 61 62 func (i *iterAdapter) SeekGE(key []byte) bool { 63 return i.update(i.Iterator.SeekGE(key)) 64 } 65 66 func (i *iterAdapter) SeekPrefixGE(prefix, key []byte) bool { 67 return i.update(i.Iterator.SeekPrefixGE(prefix, key)) 68 } 69 70 func (i *iterAdapter) SeekLT(key []byte) bool { 71 return i.update(i.Iterator.SeekLT(key)) 72 } 73 74 func (i *iterAdapter) First() bool { 75 return i.update(i.Iterator.First()) 76 } 77 78 func (i *iterAdapter) Last() bool { 79 return i.update(i.Iterator.Last()) 80 } 81 82 func (i *iterAdapter) Next() bool { 83 return i.update(i.Iterator.Next()) 84 } 85 86 func (i *iterAdapter) Prev() bool { 87 return i.update(i.Iterator.Prev()) 88 } 89 90 func (i *iterAdapter) Key() []byte { 91 return i.key 92 } 93 94 func (i *iterAdapter) Value() []byte { 95 return i.val 96 } 97 98 func (i *iterAdapter) Valid() bool { 99 return i.key != nil 100 } 101 102 func makeIntKey(i int) []byte { 103 return []byte(fmt.Sprintf("%05d", i)) 104 } 105 106 func makeKey(s string) []byte { 107 return []byte(s) 108 } 109 110 func makeIkey(s string) []byte { 111 return []byte(s) 112 } 113 114 func makeValue(i int) []byte { 115 return []byte(fmt.Sprintf("v%05d", i)) 116 } 117 118 func makeInserterAdd(s *Skiplist) func(key []byte, value []byte) error { 119 ins := &Inserter{} 120 return func(key []byte, value []byte) error { 121 return ins.Add(s, key, value) 122 } 123 } 124 125 // length iterates over skiplist to give exact size. 126 func length(s *Skiplist) int { 127 count := 0 128 129 it := newIterAdapter(s.NewIter(nil, nil)) 130 for valid := it.First(); valid; valid = it.Next() { 131 count++ 132 } 133 134 return count 135 } 136 137 // length iterates over skiplist in reverse order to give exact size. 138 func lengthRev(s *Skiplist) int { 139 count := 0 140 141 it := newIterAdapter(s.NewIter(nil, nil)) 142 for valid := it.Last(); valid; valid = it.Prev() { 143 count++ 144 } 145 146 return count 147 } 148 149 func TestEmpty(t *testing.T) { 150 key := makeKey("aaa") 151 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 152 it := newIterAdapter(l.NewIter(nil, nil)) 153 154 require.False(t, it.Valid()) 155 156 it.First() 157 require.False(t, it.Valid()) 158 159 it.Last() 160 require.False(t, it.Valid()) 161 162 require.False(t, it.SeekGE(key)) 163 require.False(t, it.Valid()) 164 } 165 166 func TestFull(t *testing.T) { 167 l := NewSkiplist(newArena(1000), bytes.Compare) 168 169 foundArenaFull := false 170 for i := 0; i < 100; i++ { 171 err := l.Add(makeIntKey(i), makeValue(i)) 172 if err == ErrArenaFull { 173 foundArenaFull = true 174 break 175 } 176 } 177 178 require.True(t, foundArenaFull) 179 180 err := l.Add(makeIkey("someval"), nil) 181 require.Equal(t, ErrArenaFull, err) 182 } 183 184 // TestBasic tests single-threaded seeks and adds. 185 func TestBasic(t *testing.T) { 186 for _, inserter := range []bool{false, true} { 187 t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) { 188 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 189 it := newIterAdapter(l.NewIter(nil, nil)) 190 191 add := l.Add 192 if inserter { 193 add = makeInserterAdd(l) 194 } 195 196 // Try adding values. 197 add(makeIkey("key1"), makeValue(1)) 198 add(makeIkey("key3"), makeValue(3)) 199 add(makeIkey("key2"), makeValue(2)) 200 201 require.True(t, it.SeekGE(makeKey("key"))) 202 require.True(t, it.Valid()) 203 require.NotEqual(t, "key", it.Key()) 204 205 require.True(t, it.SeekGE(makeKey("key1"))) 206 require.EqualValues(t, "key1", it.Key()) 207 require.EqualValues(t, makeValue(1), it.Value()) 208 209 require.True(t, it.SeekGE(makeKey("key2"))) 210 require.EqualValues(t, "key2", it.Key()) 211 require.EqualValues(t, makeValue(2), it.Value()) 212 213 require.True(t, it.SeekGE(makeKey("key3"))) 214 require.EqualValues(t, "key3", it.Key()) 215 require.EqualValues(t, makeValue(3), it.Value()) 216 }) 217 } 218 } 219 220 // TestConcurrentBasic tests concurrent writes followed by concurrent reads. 221 func TestConcurrentBasic(t *testing.T) { 222 const n = 1000 223 224 for _, inserter := range []bool{false, true} { 225 t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) { 226 // Set testing flag to make it easier to trigger unusual race conditions. 227 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 228 l.testing = true 229 230 var wg sync.WaitGroup 231 for i := 0; i < n; i++ { 232 wg.Add(1) 233 go func(i int) { 234 defer wg.Done() 235 236 if inserter { 237 var ins Inserter 238 ins.Add(l, makeIntKey(i), makeValue(i)) 239 } else { 240 l.Add(makeIntKey(i), makeValue(i)) 241 } 242 }(i) 243 } 244 wg.Wait() 245 246 // Check values. Concurrent reads. 247 for i := 0; i < n; i++ { 248 wg.Add(1) 249 go func(i int) { 250 defer wg.Done() 251 252 it := newIterAdapter(l.NewIter(nil, nil)) 253 require.True(t, it.SeekGE(makeKey(fmt.Sprintf("%05d", i)))) 254 require.EqualValues(t, fmt.Sprintf("%05d", i), it.Key()) 255 }(i) 256 } 257 wg.Wait() 258 require.Equal(t, n, length(l)) 259 require.Equal(t, n, lengthRev(l)) 260 }) 261 } 262 } 263 264 // TestConcurrentOneKey will read while writing to one single key. 265 func TestConcurrentOneKey(t *testing.T) { 266 const n = 100 267 key := makeKey("thekey") 268 ikey := makeIkey("thekey") 269 270 for _, inserter := range []bool{false, true} { 271 t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) { 272 // Set testing flag to make it easier to trigger unusual race conditions. 273 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 274 l.testing = true 275 276 var wg sync.WaitGroup 277 writeDone := make(chan struct{}, 1) 278 for i := 0; i < n; i++ { 279 wg.Add(1) 280 go func(i int) { 281 defer func() { 282 wg.Done() 283 select { 284 case writeDone <- struct{}{}: 285 default: 286 } 287 }() 288 289 if inserter { 290 var ins Inserter 291 ins.Add(l, ikey, makeValue(i)) 292 } else { 293 l.Add(ikey, makeValue(i)) 294 } 295 }(i) 296 } 297 // Wait until at least some write made it such that reads return a value. 298 <-writeDone 299 var sawValue atomic.Int32 300 for i := 0; i < n; i++ { 301 wg.Add(1) 302 go func() { 303 defer wg.Done() 304 305 it := newIterAdapter(l.NewIter(nil, nil)) 306 it.SeekGE(key) 307 require.True(t, it.Valid()) 308 require.True(t, bytes.Equal(key, it.Key())) 309 310 sawValue.Add(1) 311 v, err := strconv.Atoi(string(it.Value()[1:])) 312 require.NoError(t, err) 313 require.True(t, 0 <= v && v < n) 314 }() 315 } 316 wg.Wait() 317 require.Equal(t, int32(n), sawValue.Load()) 318 require.Equal(t, 1, length(l)) 319 require.Equal(t, 1, lengthRev(l)) 320 }) 321 } 322 } 323 324 func TestSkiplistAdd(t *testing.T) { 325 for _, inserter := range []bool{false, true} { 326 t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) { 327 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 328 it := newIterAdapter(l.NewIter(nil, nil)) 329 330 add := l.Add 331 if inserter { 332 add = makeInserterAdd(l) 333 } 334 335 // Add nil key and value (treated same as empty). 336 err := add([]byte{}, nil) 337 require.Nil(t, err) 338 require.True(t, it.SeekGE([]byte{})) 339 require.EqualValues(t, []byte{}, it.Key()) 340 require.EqualValues(t, []byte{}, it.Value()) 341 342 l = NewSkiplist(newArena(arenaSize), bytes.Compare) 343 it = newIterAdapter(l.NewIter(nil, nil)) 344 345 add = l.Add 346 if inserter { 347 add = makeInserterAdd(l) 348 } 349 350 // Add empty key and value (treated same as nil). 351 err = add(makeIkey(""), []byte{}) 352 require.Nil(t, err) 353 require.True(t, it.SeekGE([]byte{})) 354 require.EqualValues(t, []byte{}, it.Key()) 355 require.EqualValues(t, []byte{}, it.Value()) 356 357 // Add to empty list. 358 err = add(makeIntKey(2), makeValue(2)) 359 require.Nil(t, err) 360 require.True(t, it.SeekGE(makeKey("00002"))) 361 require.EqualValues(t, "00002", it.Key()) 362 require.EqualValues(t, makeValue(2), it.Value()) 363 364 // Add first element in non-empty list. 365 err = add(makeIntKey(1), makeValue(1)) 366 require.Nil(t, err) 367 require.True(t, it.SeekGE(makeKey("00001"))) 368 require.EqualValues(t, "00001", it.Key()) 369 require.EqualValues(t, makeValue(1), it.Value()) 370 371 // Add last element in non-empty list. 372 err = add(makeIntKey(4), makeValue(4)) 373 require.Nil(t, err) 374 require.True(t, it.SeekGE(makeKey("00004"))) 375 require.EqualValues(t, "00004", it.Key()) 376 require.EqualValues(t, makeValue(4), it.Value()) 377 378 // Add element in middle of list. 379 err = add(makeIntKey(3), makeValue(3)) 380 require.Nil(t, err) 381 require.True(t, it.SeekGE(makeKey("00003"))) 382 require.EqualValues(t, "00003", it.Key()) 383 require.EqualValues(t, makeValue(3), it.Value()) 384 385 // Try to add element that already exists. 386 err = add(makeIntKey(2), nil) 387 require.Equal(t, ErrRecordExists, err) 388 require.EqualValues(t, "00003", it.Key()) 389 require.EqualValues(t, makeValue(3), it.Value()) 390 391 require.Equal(t, 5, length(l)) 392 require.Equal(t, 5, lengthRev(l)) 393 }) 394 } 395 } 396 397 // TestConcurrentAdd races between adding same nodes. 398 func TestConcurrentAdd(t *testing.T) { 399 for _, inserter := range []bool{false, true} { 400 t.Run(fmt.Sprintf("inserter=%t", inserter), func(t *testing.T) { 401 const n = 100 402 403 // Set testing flag to make it easier to trigger unusual race conditions. 404 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 405 l.testing = true 406 407 start := make([]sync.WaitGroup, n) 408 end := make([]sync.WaitGroup, n) 409 410 for i := 0; i < n; i++ { 411 start[i].Add(1) 412 end[i].Add(2) 413 } 414 415 for f := 0; f < 2; f++ { 416 go func(f int) { 417 it := newIterAdapter(l.NewIter(nil, nil)) 418 add := l.Add 419 if inserter { 420 add = makeInserterAdd(l) 421 } 422 423 for i := 0; i < n; i++ { 424 start[i].Wait() 425 426 key := makeIntKey(i) 427 if add(key, nil) == nil { 428 require.True(t, it.SeekGE(key)) 429 require.EqualValues(t, key, it.Key()) 430 } 431 432 end[i].Done() 433 } 434 }(f) 435 } 436 437 for i := 0; i < n; i++ { 438 start[i].Done() 439 end[i].Wait() 440 } 441 442 require.Equal(t, n, length(l)) 443 require.Equal(t, n, lengthRev(l)) 444 }) 445 } 446 } 447 448 // TestIteratorNext tests a basic iteration over all nodes from the beginning. 449 func TestIteratorNext(t *testing.T) { 450 const n = 100 451 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 452 it := newIterAdapter(l.NewIter(nil, nil)) 453 454 require.False(t, it.Valid()) 455 456 it.First() 457 require.False(t, it.Valid()) 458 459 for i := n - 1; i >= 0; i-- { 460 l.Add(makeIntKey(i), makeValue(i)) 461 } 462 463 it.First() 464 for i := 0; i < n; i++ { 465 require.True(t, it.Valid()) 466 require.EqualValues(t, makeIntKey(i), it.Key()) 467 require.EqualValues(t, makeValue(i), it.Value()) 468 it.Next() 469 } 470 require.False(t, it.Valid()) 471 } 472 473 // TestIteratorPrev tests a basic iteration over all nodes from the end. 474 func TestIteratorPrev(t *testing.T) { 475 const n = 100 476 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 477 it := newIterAdapter(l.NewIter(nil, nil)) 478 479 require.False(t, it.Valid()) 480 481 it.Last() 482 require.False(t, it.Valid()) 483 484 var ins Inserter 485 for i := 0; i < n; i++ { 486 ins.Add(l, makeIntKey(i), makeValue(i)) 487 } 488 489 it.Last() 490 for i := n - 1; i >= 0; i-- { 491 require.True(t, it.Valid()) 492 require.EqualValues(t, makeIntKey(i), it.Key()) 493 require.EqualValues(t, makeValue(i), it.Value()) 494 it.Prev() 495 } 496 require.False(t, it.Valid()) 497 } 498 499 func TestIteratorSeekGEAndSeekPrefixGE(t *testing.T) { 500 const n = 100 501 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 502 it := newIterAdapter(l.NewIter(nil, nil)) 503 504 require.False(t, it.Valid()) 505 it.First() 506 require.False(t, it.Valid()) 507 // 1000, 1010, 1020, ..., 1990. 508 509 var ins Inserter 510 for i := n - 1; i >= 0; i-- { 511 v := i*10 + 1000 512 ins.Add(l, makeIntKey(v), makeValue(v)) 513 } 514 515 require.True(t, it.SeekGE(makeKey(""))) 516 require.True(t, it.Valid()) 517 require.EqualValues(t, "01000", it.Key()) 518 require.EqualValues(t, "v01000", it.Value()) 519 520 require.True(t, it.SeekGE(makeKey("01000"))) 521 require.True(t, it.Valid()) 522 require.EqualValues(t, "01000", it.Key()) 523 require.EqualValues(t, "v01000", it.Value()) 524 525 require.True(t, it.SeekGE(makeKey("01005"))) 526 require.True(t, it.Valid()) 527 require.EqualValues(t, "01010", it.Key()) 528 require.EqualValues(t, "v01010", it.Value()) 529 530 require.True(t, it.SeekGE(makeKey("01010"))) 531 require.True(t, it.Valid()) 532 require.EqualValues(t, "01010", it.Key()) 533 require.EqualValues(t, "v01010", it.Value()) 534 535 require.False(t, it.SeekGE(makeKey("99999"))) 536 require.False(t, it.Valid()) 537 538 // Test seek for empty key. 539 ins.Add(l, []byte{}, nil) 540 require.True(t, it.SeekGE([]byte{})) 541 require.True(t, it.Valid()) 542 require.EqualValues(t, "", it.Key()) 543 544 require.True(t, it.SeekGE(makeKey(""))) 545 require.True(t, it.Valid()) 546 require.EqualValues(t, "", it.Key()) 547 } 548 549 func TestIteratorSeekLT(t *testing.T) { 550 const n = 100 551 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 552 it := newIterAdapter(l.NewIter(nil, nil)) 553 554 require.False(t, it.Valid()) 555 it.First() 556 require.False(t, it.Valid()) 557 // 1000, 1010, 1020, ..., 1990. 558 var ins Inserter 559 for i := n - 1; i >= 0; i-- { 560 v := i*10 + 1000 561 ins.Add(l, makeIntKey(v), makeValue(v)) 562 } 563 564 require.False(t, it.SeekLT(makeKey(""))) 565 require.False(t, it.Valid()) 566 567 require.False(t, it.SeekLT(makeKey("01000"))) 568 require.False(t, it.Valid()) 569 570 require.True(t, it.SeekLT(makeKey("01001"))) 571 require.True(t, it.Valid()) 572 require.EqualValues(t, "01000", it.Key()) 573 require.EqualValues(t, "v01000", it.Value()) 574 575 require.True(t, it.SeekLT(makeKey("01005"))) 576 require.True(t, it.Valid()) 577 require.EqualValues(t, "01000", it.Key()) 578 require.EqualValues(t, "v01000", it.Value()) 579 580 require.True(t, it.SeekLT(makeKey("01991"))) 581 require.True(t, it.Valid()) 582 require.EqualValues(t, "01990", it.Key()) 583 require.EqualValues(t, "v01990", it.Value()) 584 585 require.True(t, it.SeekLT(makeKey("99999"))) 586 require.True(t, it.Valid()) 587 require.EqualValues(t, "01990", it.Key()) 588 require.EqualValues(t, "v01990", it.Value()) 589 590 // Test seek for empty key. 591 ins.Add(l, []byte{}, nil) 592 require.False(t, it.SeekLT([]byte{})) 593 require.False(t, it.Valid()) 594 595 require.True(t, it.SeekLT(makeKey("\x01"))) 596 require.True(t, it.Valid()) 597 require.EqualValues(t, "", it.Key()) 598 } 599 600 // TODO(peter): test First and Last. 601 func TestIteratorBounds(t *testing.T) { 602 l := NewSkiplist(newArena(arenaSize), bytes.Compare) 603 for i := 1; i < 10; i++ { 604 require.NoError(t, l.Add(makeIntKey(i), makeValue(i))) 605 } 606 607 key := func(i int) []byte { 608 return makeIntKey(i) 609 } 610 611 it := newIterAdapter(l.NewIter(key(3), key(7))) 612 613 // SeekGE within the lower and upper bound succeeds. 614 for i := 3; i <= 6; i++ { 615 k := key(i) 616 require.True(t, it.SeekGE(k)) 617 require.EqualValues(t, string(k), string(it.Key())) 618 } 619 620 // SeekGE before the lower bound still succeeds (only the upper bound is 621 // checked). 622 for i := 1; i < 3; i++ { 623 k := key(i) 624 require.True(t, it.SeekGE(k)) 625 require.EqualValues(t, string(k), string(it.Key())) 626 } 627 628 // SeekGE beyond the upper bound fails. 629 for i := 7; i < 10; i++ { 630 require.False(t, it.SeekGE(key(i))) 631 } 632 633 require.True(t, it.SeekGE(key(6))) 634 require.EqualValues(t, "00006", it.Key()) 635 require.EqualValues(t, "v00006", it.Value()) 636 637 // Next into the upper bound fails. 638 require.False(t, it.Next()) 639 640 // SeekLT within the lower and upper bound succeeds. 641 for i := 4; i <= 7; i++ { 642 require.True(t, it.SeekLT(key(i))) 643 require.EqualValues(t, string(key(i-1)), string(it.Key())) 644 } 645 646 // SeekLT beyond the upper bound still succeeds (only the lower bound is 647 // checked). 648 for i := 8; i < 9; i++ { 649 require.True(t, it.SeekLT(key(8))) 650 require.EqualValues(t, string(key(i-1)), string(it.Key())) 651 } 652 653 // SeekLT before the lower bound fails. 654 for i := 1; i < 4; i++ { 655 require.False(t, it.SeekLT(key(i))) 656 } 657 658 require.True(t, it.SeekLT(key(4))) 659 require.EqualValues(t, "00003", it.Key()) 660 require.EqualValues(t, "v00003", it.Value()) 661 662 // Prev into the lower bound fails. 663 require.False(t, it.Prev()) 664 } 665 666 func randomKey(rng *rand.Rand, b []byte) []byte { 667 key := rng.Uint32() 668 key2 := rng.Uint32() 669 binary.LittleEndian.PutUint32(b, key) 670 binary.LittleEndian.PutUint32(b[4:], key2) 671 return b 672 } 673 674 // Standard test. Some fraction is read. Some fraction is write. Writes have 675 // to go through mutex lock. 676 func BenchmarkReadWrite(b *testing.B) { 677 for i := 0; i <= 10; i++ { 678 readFrac := float32(i) / 10.0 679 b.Run(fmt.Sprintf("frac_%d", i*10), func(b *testing.B) { 680 l := NewSkiplist(newArena(uint32((b.N+2)*maxNodeSize)), bytes.Compare) 681 b.ResetTimer() 682 var count int 683 b.RunParallel(func(pb *testing.PB) { 684 it := l.NewIter(nil, nil) 685 rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) 686 buf := make([]byte, 8) 687 688 for pb.Next() { 689 if rng.Float32() < readFrac { 690 ok, key, _ := it.SeekGE(randomKey(rng, buf)) 691 if ok { 692 _ = key 693 count++ 694 } 695 } else { 696 _ = l.Add(randomKey(rng, buf), nil) 697 } 698 } 699 }) 700 }) 701 } 702 } 703 704 func BenchmarkOrderedWrite(b *testing.B) { 705 l := NewSkiplist(newArena(8<<20), bytes.Compare) 706 var ins Inserter 707 buf := make([]byte, 8) 708 709 b.ResetTimer() 710 for i := 0; i < b.N; i++ { 711 binary.BigEndian.PutUint64(buf, uint64(i)) 712 if err := ins.Add(l, buf, nil); err == ErrArenaFull { 713 b.StopTimer() 714 l = NewSkiplist(newArena(uint32((b.N+2)*maxNodeSize)), bytes.Compare) 715 ins = Inserter{} 716 b.StartTimer() 717 } 718 } 719 } 720 721 func BenchmarkIterNext(b *testing.B) { 722 l := NewSkiplist(newArena(64<<10), bytes.Compare) 723 rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) 724 buf := make([]byte, 8) 725 for { 726 if err := l.Add(randomKey(rng, buf), nil); err == ErrArenaFull { 727 break 728 } 729 } 730 731 it := l.NewIter(nil, nil) 732 b.ResetTimer() 733 for i := 0; i < b.N; i++ { 734 ok, key, _ := it.Next() 735 if !ok { 736 _, key, _ = it.First() 737 } 738 _ = key 739 } 740 } 741 742 func BenchmarkIterPrev(b *testing.B) { 743 l := NewSkiplist(newArena(64<<10), bytes.Compare) 744 rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) 745 buf := make([]byte, 8) 746 for { 747 if err := l.Add(randomKey(rng, buf), nil); err == ErrArenaFull { 748 break 749 } 750 } 751 752 it := l.NewIter(nil, nil) 753 _, _, _ = it.Last() 754 b.ResetTimer() 755 for i := 0; i < b.N; i++ { 756 ok, key, _ := it.Prev() 757 if !ok { 758 _, key, _ = it.Last() 759 } 760 _ = key 761 } 762 } 763 764 // BenchmarkSeekPrefixGE looks at the performance of repeated calls to 765 // SeekPrefixGE, with different skip distances and different settings of 766 // trySeekUsingNext. 767 func BenchmarkSeekPrefixGE(b *testing.B) { 768 l := NewSkiplist(newArena(64<<10), bytes.Compare) 769 var count int 770 // count was measured to be 1279. 771 for count = 0; ; count++ { 772 if err := l.Add(makeIntKey(count), makeValue(count)); err == ErrArenaFull { 773 break 774 } 775 } 776 for _, skip := range []int{1, 2, 4, 8, 16} { 777 for _, useNext := range []bool{false} { 778 b.Run(fmt.Sprintf("skip=%d/use-next=%t", skip, useNext), func(b *testing.B) { 779 it := l.NewIter(nil, nil) 780 j := 0 781 var k []byte 782 makeKey := func() { 783 k = []byte(fmt.Sprintf("%05d", j)) 784 } 785 makeKey() 786 it.SeekPrefixGE(k, k) 787 b.ResetTimer() 788 for i := 0; i < b.N; i++ { 789 j += skip 790 if j >= count { 791 j = 0 792 } 793 makeKey() 794 it.SeekPrefixGE(k, k) 795 } 796 }) 797 } 798 } 799 }