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