github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/interval/generic/example_interval_btree_test.go (about)

     1  // Code generated by go_generics. DO NOT EDIT.
     2  
     3  // Copyright 2020 The Cockroach Authors.
     4  //
     5  // Use of this software is governed by the Business Source License
     6  // included in the file licenses/BSL.txt.
     7  //
     8  // As of the Change Date specified in that file, in accordance with
     9  // the Business Source License, use of this software will be governed
    10  // by the Apache License, Version 2.0, included in the file
    11  // licenses/APL.txt.
    12  
    13  package generic
    14  
    15  import (
    16  	"fmt"
    17  	"math/rand"
    18  	"reflect"
    19  	"sync"
    20  	"testing"
    21  
    22  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    23  	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  func newItem(s roachpb.Span) *example {
    28  	i := nilT.New()
    29  	i.SetKey(s.Key)
    30  	i.SetEndKey(s.EndKey)
    31  	return i
    32  }
    33  
    34  func spanFromItem(i *example) roachpb.Span {
    35  	return roachpb.Span{Key: i.Key(), EndKey: i.EndKey()}
    36  }
    37  
    38  //////////////////////////////////////////
    39  //        Invariant verification        //
    40  //////////////////////////////////////////
    41  
    42  // Verify asserts that the tree's structural invariants all hold.
    43  func (t *btree) Verify(tt *testing.T) {
    44  	if t.length == 0 {
    45  		require.Nil(tt, t.root)
    46  		return
    47  	}
    48  	t.verifyLeafSameDepth(tt)
    49  	t.verifyCountAllowed(tt)
    50  	t.isSorted(tt)
    51  	t.isUpperBoundCorrect(tt)
    52  }
    53  
    54  func (t *btree) verifyLeafSameDepth(tt *testing.T) {
    55  	h := t.Height()
    56  	t.root.verifyDepthEqualToHeight(tt, 1, h)
    57  }
    58  
    59  func (n *node) verifyDepthEqualToHeight(t *testing.T, depth, height int) {
    60  	if n.leaf {
    61  		require.Equal(t, height, depth, "all leaves should have the same depth as the tree height")
    62  	}
    63  	n.recurse(func(child *node, _ int16) {
    64  		child.verifyDepthEqualToHeight(t, depth+1, height)
    65  	})
    66  }
    67  
    68  func (t *btree) verifyCountAllowed(tt *testing.T) {
    69  	t.root.verifyCountAllowed(tt, true)
    70  }
    71  
    72  func (n *node) verifyCountAllowed(t *testing.T, root bool) {
    73  	if !root {
    74  		require.GreaterOrEqual(t, n.count, int16(minItems), "latch count %d must be in range [%d,%d]", n.count, minItems, maxItems)
    75  		require.LessOrEqual(t, n.count, int16(maxItems), "latch count %d must be in range [%d,%d]", n.count, minItems, maxItems)
    76  	}
    77  	for i, item := range n.items {
    78  		if i < int(n.count) {
    79  			require.NotNil(t, item, "latch below count")
    80  		} else {
    81  			require.Nil(t, item, "latch above count")
    82  		}
    83  	}
    84  	if !n.leaf {
    85  		for i, child := range n.children {
    86  			if i <= int(n.count) {
    87  				require.NotNil(t, child, "node below count")
    88  			} else {
    89  				require.Nil(t, child, "node above count")
    90  			}
    91  		}
    92  	}
    93  	n.recurse(func(child *node, _ int16) {
    94  		child.verifyCountAllowed(t, false)
    95  	})
    96  }
    97  
    98  func (t *btree) isSorted(tt *testing.T) {
    99  	t.root.isSorted(tt)
   100  }
   101  
   102  func (n *node) isSorted(t *testing.T) {
   103  	for i := int16(1); i < n.count; i++ {
   104  		require.LessOrEqual(t, cmp(n.items[i-1], n.items[i]), 0)
   105  	}
   106  	if !n.leaf {
   107  		for i := int16(0); i < n.count; i++ {
   108  			prev := n.children[i]
   109  			next := n.children[i+1]
   110  
   111  			require.LessOrEqual(t, cmp(prev.items[prev.count-1], n.items[i]), 0)
   112  			require.LessOrEqual(t, cmp(n.items[i], next.items[0]), 0)
   113  		}
   114  	}
   115  	n.recurse(func(child *node, _ int16) {
   116  		child.isSorted(t)
   117  	})
   118  }
   119  
   120  func (t *btree) isUpperBoundCorrect(tt *testing.T) {
   121  	t.root.isUpperBoundCorrect(tt)
   122  }
   123  
   124  func (n *node) isUpperBoundCorrect(t *testing.T) {
   125  	require.Equal(t, 0, n.findUpperBound().compare(n.max))
   126  	for i := int16(1); i < n.count; i++ {
   127  		require.LessOrEqual(t, upperBound(n.items[i]).compare(n.max), 0)
   128  	}
   129  	if !n.leaf {
   130  		for i := int16(0); i <= n.count; i++ {
   131  			child := n.children[i]
   132  			require.LessOrEqual(t, child.max.compare(n.max), 0)
   133  		}
   134  	}
   135  	n.recurse(func(child *node, _ int16) {
   136  		child.isUpperBoundCorrect(t)
   137  	})
   138  }
   139  
   140  func (n *node) recurse(f func(child *node, pos int16)) {
   141  	if !n.leaf {
   142  		for i := int16(0); i <= n.count; i++ {
   143  			f(n.children[i], i)
   144  		}
   145  	}
   146  }
   147  
   148  //////////////////////////////////////////
   149  //              Unit Tests              //
   150  //////////////////////////////////////////
   151  
   152  func key(i int) roachpb.Key {
   153  	if i < 0 || i > 99999 {
   154  		panic("key out of bounds")
   155  	}
   156  	return []byte(fmt.Sprintf("%05d", i))
   157  }
   158  
   159  func span(i int) roachpb.Span {
   160  	switch i % 10 {
   161  	case 0:
   162  		return roachpb.Span{Key: key(i)}
   163  	case 1:
   164  		return roachpb.Span{Key: key(i), EndKey: key(i).Next()}
   165  	case 2:
   166  		return roachpb.Span{Key: key(i), EndKey: key(i + 64)}
   167  	default:
   168  		return roachpb.Span{Key: key(i), EndKey: key(i + 4)}
   169  	}
   170  }
   171  
   172  func spanWithEnd(start, end int) roachpb.Span {
   173  	if start < end {
   174  		return roachpb.Span{Key: key(start), EndKey: key(end)}
   175  	} else if start == end {
   176  		return roachpb.Span{Key: key(start)}
   177  	} else {
   178  		panic("illegal span")
   179  	}
   180  }
   181  
   182  func spanWithMemo(i int, memo map[int]roachpb.Span) roachpb.Span {
   183  	if s, ok := memo[i]; ok {
   184  		return s
   185  	}
   186  	s := span(i)
   187  	memo[i] = s
   188  	return s
   189  }
   190  
   191  func randomSpan(rng *rand.Rand, n int) roachpb.Span {
   192  	start := rng.Intn(n)
   193  	end := rng.Intn(n + 1)
   194  	if end < start {
   195  		start, end = end, start
   196  	}
   197  	return spanWithEnd(start, end)
   198  }
   199  
   200  func checkIter(t *testing.T, it iterator, start, end int, spanMemo map[int]roachpb.Span) {
   201  	i := start
   202  	for it.First(); it.Valid(); it.Next() {
   203  		item := it.Cur()
   204  		expected := spanWithMemo(i, spanMemo)
   205  		if !expected.Equal(spanFromItem(item)) {
   206  			t.Fatalf("expected %s, but found %s", expected, spanFromItem(item))
   207  		}
   208  		i++
   209  	}
   210  	if i != end {
   211  		t.Fatalf("expected %d, but at %d", end, i)
   212  	}
   213  
   214  	for it.Last(); it.Valid(); it.Prev() {
   215  		i--
   216  		item := it.Cur()
   217  		expected := spanWithMemo(i, spanMemo)
   218  		if !expected.Equal(spanFromItem(item)) {
   219  			t.Fatalf("expected %s, but found %s", expected, spanFromItem(item))
   220  		}
   221  	}
   222  	if i != start {
   223  		t.Fatalf("expected %d, but at %d: %+v", start, i, it)
   224  	}
   225  
   226  	all := newItem(spanWithEnd(start, end))
   227  	for it.FirstOverlap(all); it.Valid(); it.NextOverlap(all) {
   228  		item := it.Cur()
   229  		expected := spanWithMemo(i, spanMemo)
   230  		if !expected.Equal(spanFromItem(item)) {
   231  			t.Fatalf("expected %s, but found %s", expected, spanFromItem(item))
   232  		}
   233  		i++
   234  	}
   235  	if i != end {
   236  		t.Fatalf("expected %d, but at %d", end, i)
   237  	}
   238  }
   239  
   240  // TestBTree tests basic btree operations.
   241  func TestBTree(t *testing.T) {
   242  	var tr btree
   243  	spanMemo := make(map[int]roachpb.Span)
   244  
   245  	// With degree == 16 (max-items/node == 31) we need 513 items in order for
   246  	// there to be 3 levels in the tree. The count here is comfortably above
   247  	// that.
   248  	const count = 768
   249  
   250  	// Add keys in sorted order.
   251  	for i := 0; i < count; i++ {
   252  		tr.Set(newItem(span(i)))
   253  		tr.Verify(t)
   254  		if e := i + 1; e != tr.Len() {
   255  			t.Fatalf("expected length %d, but found %d", e, tr.Len())
   256  		}
   257  		checkIter(t, tr.MakeIter(), 0, i+1, spanMemo)
   258  	}
   259  
   260  	// Delete keys in sorted order.
   261  	for i := 0; i < count; i++ {
   262  		tr.Delete(newItem(span(i)))
   263  		tr.Verify(t)
   264  		if e := count - (i + 1); e != tr.Len() {
   265  			t.Fatalf("expected length %d, but found %d", e, tr.Len())
   266  		}
   267  		checkIter(t, tr.MakeIter(), i+1, count, spanMemo)
   268  	}
   269  
   270  	// Add keys in reverse sorted order.
   271  	for i := 0; i < count; i++ {
   272  		tr.Set(newItem(span(count - i)))
   273  		tr.Verify(t)
   274  		if e := i + 1; e != tr.Len() {
   275  			t.Fatalf("expected length %d, but found %d", e, tr.Len())
   276  		}
   277  		checkIter(t, tr.MakeIter(), count-i, count+1, spanMemo)
   278  	}
   279  
   280  	// Delete keys in reverse sorted order.
   281  	for i := 0; i < count; i++ {
   282  		tr.Delete(newItem(span(count - i)))
   283  		tr.Verify(t)
   284  		if e := count - (i + 1); e != tr.Len() {
   285  			t.Fatalf("expected length %d, but found %d", e, tr.Len())
   286  		}
   287  		checkIter(t, tr.MakeIter(), 1, count-i, spanMemo)
   288  	}
   289  }
   290  
   291  // TestBTreeSeek tests basic btree iterator operations.
   292  func TestBTreeSeek(t *testing.T) {
   293  	const count = 513
   294  
   295  	var tr btree
   296  	for i := 0; i < count; i++ {
   297  		tr.Set(newItem(span(i * 2)))
   298  	}
   299  
   300  	it := tr.MakeIter()
   301  	for i := 0; i < 2*count-1; i++ {
   302  		it.SeekGE(newItem(span(i)))
   303  		if !it.Valid() {
   304  			t.Fatalf("%d: expected valid iterator", i)
   305  		}
   306  		item := it.Cur()
   307  		expected := span(2 * ((i + 1) / 2))
   308  		if !expected.Equal(spanFromItem(item)) {
   309  			t.Fatalf("%d: expected %s, but found %s", i, expected, spanFromItem(item))
   310  		}
   311  	}
   312  	it.SeekGE(newItem(span(2*count - 1)))
   313  	if it.Valid() {
   314  		t.Fatalf("expected invalid iterator")
   315  	}
   316  
   317  	for i := 1; i < 2*count; i++ {
   318  		it.SeekLT(newItem(span(i)))
   319  		if !it.Valid() {
   320  			t.Fatalf("%d: expected valid iterator", i)
   321  		}
   322  		item := it.Cur()
   323  		expected := span(2 * ((i - 1) / 2))
   324  		if !expected.Equal(spanFromItem(item)) {
   325  			t.Fatalf("%d: expected %s, but found %s", i, expected, spanFromItem(item))
   326  		}
   327  	}
   328  	it.SeekLT(newItem(span(0)))
   329  	if it.Valid() {
   330  		t.Fatalf("expected invalid iterator")
   331  	}
   332  }
   333  
   334  // TestBTreeSeekOverlap tests btree iterator overlap operations.
   335  func TestBTreeSeekOverlap(t *testing.T) {
   336  	const count = 513
   337  	const size = 2 * maxItems
   338  
   339  	var tr btree
   340  	for i := 0; i < count; i++ {
   341  		tr.Set(newItem(spanWithEnd(i, i+size+1)))
   342  	}
   343  
   344  	// Iterate over overlaps with a point scan.
   345  	it := tr.MakeIter()
   346  	for i := 0; i < count+size; i++ {
   347  		scanItem := newItem(spanWithEnd(i, i))
   348  		it.FirstOverlap(scanItem)
   349  		for j := 0; j < size+1; j++ {
   350  			expStart := i - size + j
   351  			if expStart < 0 {
   352  				continue
   353  			}
   354  			if expStart >= count {
   355  				continue
   356  			}
   357  
   358  			if !it.Valid() {
   359  				t.Fatalf("%d/%d: expected valid iterator", i, j)
   360  			}
   361  			item := it.Cur()
   362  			expected := spanWithEnd(expStart, expStart+size+1)
   363  			if !expected.Equal(spanFromItem(item)) {
   364  				t.Fatalf("%d: expected %s, but found %s", i, expected, spanFromItem(item))
   365  			}
   366  
   367  			it.NextOverlap(scanItem)
   368  		}
   369  		if it.Valid() {
   370  			t.Fatalf("%d: expected invalid iterator %v", i, it.Cur())
   371  		}
   372  	}
   373  	it.FirstOverlap(newItem(span(count + size + 1)))
   374  	if it.Valid() {
   375  		t.Fatalf("expected invalid iterator")
   376  	}
   377  
   378  	// Iterate over overlaps with a range scan.
   379  	it = tr.MakeIter()
   380  	for i := 0; i < count+size; i++ {
   381  		scanItem := newItem(spanWithEnd(i, i+size+1))
   382  		it.FirstOverlap(scanItem)
   383  		for j := 0; j < 2*size+1; j++ {
   384  			expStart := i - size + j
   385  			if expStart < 0 {
   386  				continue
   387  			}
   388  			if expStart >= count {
   389  				continue
   390  			}
   391  
   392  			if !it.Valid() {
   393  				t.Fatalf("%d/%d: expected valid iterator", i, j)
   394  			}
   395  			item := it.Cur()
   396  			expected := spanWithEnd(expStart, expStart+size+1)
   397  			if !expected.Equal(spanFromItem(item)) {
   398  				t.Fatalf("%d: expected %s, but found %s", i, expected, spanFromItem(item))
   399  			}
   400  
   401  			it.NextOverlap(scanItem)
   402  		}
   403  		if it.Valid() {
   404  			t.Fatalf("%d: expected invalid iterator %v", i, it.Cur())
   405  		}
   406  	}
   407  	it.FirstOverlap(newItem(span(count + size + 1)))
   408  	if it.Valid() {
   409  		t.Fatalf("expected invalid iterator")
   410  	}
   411  }
   412  
   413  // TestBTreeSeekOverlapRandom tests btree iterator overlap operations using
   414  // randomized input.
   415  func TestBTreeSeekOverlapRandom(t *testing.T) {
   416  	rng := rand.New(rand.NewSource(timeutil.Now().UnixNano()))
   417  
   418  	const trials = 10
   419  	for i := 0; i < trials; i++ {
   420  		var tr btree
   421  
   422  		const count = 1000
   423  		items := make([]*example, count)
   424  		itemSpans := make([]int, count)
   425  		for j := 0; j < count; j++ {
   426  			var item *example
   427  			end := rng.Intn(count + 10)
   428  			if end <= j {
   429  				end = j
   430  				item = newItem(spanWithEnd(j, end))
   431  			} else {
   432  				item = newItem(spanWithEnd(j, end+1))
   433  			}
   434  			tr.Set(item)
   435  			items[j] = item
   436  			itemSpans[j] = end
   437  		}
   438  
   439  		const scanTrials = 100
   440  		for j := 0; j < scanTrials; j++ {
   441  			var scanItem *example
   442  			scanStart := rng.Intn(count)
   443  			scanEnd := rng.Intn(count + 10)
   444  			if scanEnd <= scanStart {
   445  				scanEnd = scanStart
   446  				scanItem = newItem(spanWithEnd(scanStart, scanEnd))
   447  			} else {
   448  				scanItem = newItem(spanWithEnd(scanStart, scanEnd+1))
   449  			}
   450  
   451  			var exp, found []*example
   452  			for startKey, endKey := range itemSpans {
   453  				if startKey <= scanEnd && endKey >= scanStart {
   454  					exp = append(exp, items[startKey])
   455  				}
   456  			}
   457  
   458  			it := tr.MakeIter()
   459  			it.FirstOverlap(scanItem)
   460  			for it.Valid() {
   461  				found = append(found, it.Cur())
   462  				it.NextOverlap(scanItem)
   463  			}
   464  
   465  			require.Equal(t, len(exp), len(found), "search for %v", spanFromItem(scanItem))
   466  		}
   467  	}
   468  }
   469  
   470  // TestBTreeCloneConcurrentOperations tests that cloning a btree returns a new
   471  // btree instance which is an exact logical copy of the original but that can be
   472  // modified independently going forward.
   473  func TestBTreeCloneConcurrentOperations(t *testing.T) {
   474  	const cloneTestSize = 1000
   475  	p := perm(cloneTestSize)
   476  
   477  	var trees []*btree
   478  	treeC, treeDone := make(chan *btree), make(chan struct{})
   479  	go func() {
   480  		for b := range treeC {
   481  			trees = append(trees, b)
   482  		}
   483  		close(treeDone)
   484  	}()
   485  
   486  	var wg sync.WaitGroup
   487  	var populate func(tr *btree, start int)
   488  	populate = func(tr *btree, start int) {
   489  		t.Logf("Starting new clone at %v", start)
   490  		treeC <- tr
   491  		for i := start; i < cloneTestSize; i++ {
   492  			tr.Set(p[i])
   493  			if i%(cloneTestSize/5) == 0 {
   494  				wg.Add(1)
   495  				c := tr.Clone()
   496  				go populate(&c, i+1)
   497  			}
   498  		}
   499  		wg.Done()
   500  	}
   501  
   502  	wg.Add(1)
   503  	var tr btree
   504  	go populate(&tr, 0)
   505  	wg.Wait()
   506  	close(treeC)
   507  	<-treeDone
   508  
   509  	t.Logf("Starting equality checks on %d trees", len(trees))
   510  	want := rang(0, cloneTestSize-1)
   511  	for i, tree := range trees {
   512  		if !reflect.DeepEqual(want, all(tree)) {
   513  			t.Errorf("tree %v mismatch", i)
   514  		}
   515  	}
   516  
   517  	t.Log("Removing half of items from first half")
   518  	toRemove := want[cloneTestSize/2:]
   519  	for i := 0; i < len(trees)/2; i++ {
   520  		tree := trees[i]
   521  		wg.Add(1)
   522  		go func() {
   523  			for _, item := range toRemove {
   524  				tree.Delete(item)
   525  			}
   526  			wg.Done()
   527  		}()
   528  	}
   529  	wg.Wait()
   530  
   531  	t.Log("Checking all values again")
   532  	for i, tree := range trees {
   533  		var wantpart []*example
   534  		if i < len(trees)/2 {
   535  			wantpart = want[:cloneTestSize/2]
   536  		} else {
   537  			wantpart = want
   538  		}
   539  		if got := all(tree); !reflect.DeepEqual(wantpart, got) {
   540  			t.Errorf("tree %v mismatch, want %v got %v", i, len(want), len(got))
   541  		}
   542  	}
   543  }
   544  
   545  // TestBTreeCmp tests the btree item comparison.
   546  func TestBTreeCmp(t *testing.T) {
   547  	// NB: go_generics doesn't do well with anonymous types, so name this type.
   548  	// Avoid the slice literal syntax, which GofmtSimplify mandates the use of
   549  	// anonymous constructors with.
   550  	type testCase struct {
   551  		spanA, spanB roachpb.Span
   552  		idA, idB     uint64
   553  		exp          int
   554  	}
   555  	var testCases []testCase
   556  	testCases = append(testCases,
   557  		testCase{
   558  			spanA: roachpb.Span{Key: roachpb.Key("a")},
   559  			spanB: roachpb.Span{Key: roachpb.Key("a")},
   560  			idA:   1,
   561  			idB:   1,
   562  			exp:   0,
   563  		},
   564  		testCase{
   565  			spanA: roachpb.Span{Key: roachpb.Key("a")},
   566  			spanB: roachpb.Span{Key: roachpb.Key("a"), EndKey: roachpb.Key("b")},
   567  			idA:   1,
   568  			idB:   1,
   569  			exp:   -1,
   570  		},
   571  		testCase{
   572  			spanA: roachpb.Span{Key: roachpb.Key("a"), EndKey: roachpb.Key("c")},
   573  			spanB: roachpb.Span{Key: roachpb.Key("a"), EndKey: roachpb.Key("b")},
   574  			idA:   1,
   575  			idB:   1,
   576  			exp:   1,
   577  		},
   578  		testCase{
   579  			spanA: roachpb.Span{Key: roachpb.Key("a"), EndKey: roachpb.Key("c")},
   580  			spanB: roachpb.Span{Key: roachpb.Key("a"), EndKey: roachpb.Key("c")},
   581  			idA:   1,
   582  			idB:   1,
   583  			exp:   0,
   584  		},
   585  		testCase{
   586  			spanA: roachpb.Span{Key: roachpb.Key("a")},
   587  			spanB: roachpb.Span{Key: roachpb.Key("a")},
   588  			idA:   1,
   589  			idB:   2,
   590  			exp:   -1,
   591  		},
   592  		testCase{
   593  			spanA: roachpb.Span{Key: roachpb.Key("a")},
   594  			spanB: roachpb.Span{Key: roachpb.Key("a")},
   595  			idA:   2,
   596  			idB:   1,
   597  			exp:   1,
   598  		},
   599  		testCase{
   600  			spanA: roachpb.Span{Key: roachpb.Key("b")},
   601  			spanB: roachpb.Span{Key: roachpb.Key("a"), EndKey: roachpb.Key("c")},
   602  			idA:   1,
   603  			idB:   1,
   604  			exp:   1,
   605  		},
   606  		testCase{
   607  			spanA: roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("e")},
   608  			spanB: roachpb.Span{Key: roachpb.Key("c"), EndKey: roachpb.Key("d")},
   609  			idA:   1,
   610  			idB:   1,
   611  			exp:   -1,
   612  		},
   613  	)
   614  	for _, tc := range testCases {
   615  		name := fmt.Sprintf("cmp(%s:%d,%s:%d)", tc.spanA, tc.idA, tc.spanB, tc.idB)
   616  		t.Run(name, func(t *testing.T) {
   617  			laA := newItem(tc.spanA)
   618  			laA.SetID(tc.idA)
   619  			laB := newItem(tc.spanB)
   620  			laB.SetID(tc.idB)
   621  			require.Equal(t, tc.exp, cmp(laA, laB))
   622  		})
   623  	}
   624  }
   625  
   626  // TestIterStack tests the interface of the iterStack type.
   627  func TestIterStack(t *testing.T) {
   628  	f := func(i int) iterFrame { return iterFrame{pos: int16(i)} }
   629  	var is iterStack
   630  	for i := 1; i <= 2*len(iterStackArr{}); i++ {
   631  		var j int
   632  		for j = 0; j < i; j++ {
   633  			is.push(f(j))
   634  		}
   635  		require.Equal(t, j, is.len())
   636  		for j--; j >= 0; j-- {
   637  			require.Equal(t, f(j), is.pop())
   638  		}
   639  		is.reset()
   640  	}
   641  }
   642  
   643  //////////////////////////////////////////
   644  //              Benchmarks              //
   645  //////////////////////////////////////////
   646  
   647  // perm returns a random permutation of items with spans in the range [0, n).
   648  func perm(n int) (out []*example) {
   649  	for _, i := range rand.Perm(n) {
   650  		out = append(out, newItem(spanWithEnd(i, i+1)))
   651  	}
   652  	return out
   653  }
   654  
   655  // rang returns an ordered list of items with spans in the range [m, n].
   656  func rang(m, n int) (out []*example) {
   657  	for i := m; i <= n; i++ {
   658  		out = append(out, newItem(spanWithEnd(i, i+1)))
   659  	}
   660  	return out
   661  }
   662  
   663  // all extracts all items from a tree in order as a slice.
   664  func all(tr *btree) (out []*example) {
   665  	it := tr.MakeIter()
   666  	it.First()
   667  	for it.Valid() {
   668  		out = append(out, it.Cur())
   669  		it.Next()
   670  	}
   671  	return out
   672  }
   673  
   674  func forBenchmarkSizes(b *testing.B, f func(b *testing.B, count int)) {
   675  	for _, count := range []int{16, 128, 1024, 8192, 65536} {
   676  		b.Run(fmt.Sprintf("count=%d", count), func(b *testing.B) {
   677  			f(b, count)
   678  		})
   679  	}
   680  }
   681  
   682  // BenchmarkBTreeInsert measures btree insertion performance.
   683  func BenchmarkBTreeInsert(b *testing.B) {
   684  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   685  		insertP := perm(count)
   686  		b.ResetTimer()
   687  		for i := 0; i < b.N; {
   688  			var tr btree
   689  			for _, item := range insertP {
   690  				tr.Set(item)
   691  				i++
   692  				if i >= b.N {
   693  					return
   694  				}
   695  			}
   696  		}
   697  	})
   698  }
   699  
   700  // BenchmarkBTreeDelete measures btree deletion performance.
   701  func BenchmarkBTreeDelete(b *testing.B) {
   702  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   703  		insertP, removeP := perm(count), perm(count)
   704  		b.ResetTimer()
   705  		for i := 0; i < b.N; {
   706  			b.StopTimer()
   707  			var tr btree
   708  			for _, item := range insertP {
   709  				tr.Set(item)
   710  			}
   711  			b.StartTimer()
   712  			for _, item := range removeP {
   713  				tr.Delete(item)
   714  				i++
   715  				if i >= b.N {
   716  					return
   717  				}
   718  			}
   719  			if tr.Len() > 0 {
   720  				b.Fatalf("tree not empty: %s", &tr)
   721  			}
   722  		}
   723  	})
   724  }
   725  
   726  // BenchmarkBTreeDeleteInsert measures btree deletion and insertion performance.
   727  func BenchmarkBTreeDeleteInsert(b *testing.B) {
   728  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   729  		insertP := perm(count)
   730  		var tr btree
   731  		for _, item := range insertP {
   732  			tr.Set(item)
   733  		}
   734  		b.ResetTimer()
   735  		for i := 0; i < b.N; i++ {
   736  			item := insertP[i%count]
   737  			tr.Delete(item)
   738  			tr.Set(item)
   739  		}
   740  	})
   741  }
   742  
   743  // BenchmarkBTreeDeleteInsertCloneOnce measures btree deletion and insertion
   744  // performance after the tree has been copy-on-write cloned once.
   745  func BenchmarkBTreeDeleteInsertCloneOnce(b *testing.B) {
   746  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   747  		insertP := perm(count)
   748  		var tr btree
   749  		for _, item := range insertP {
   750  			tr.Set(item)
   751  		}
   752  		tr = tr.Clone()
   753  		b.ResetTimer()
   754  		for i := 0; i < b.N; i++ {
   755  			item := insertP[i%count]
   756  			tr.Delete(item)
   757  			tr.Set(item)
   758  		}
   759  	})
   760  }
   761  
   762  // BenchmarkBTreeDeleteInsertCloneEachTime measures btree deletion and insertion
   763  // performance while the tree is repeatedly copy-on-write cloned.
   764  func BenchmarkBTreeDeleteInsertCloneEachTime(b *testing.B) {
   765  	for _, reset := range []bool{false, true} {
   766  		b.Run(fmt.Sprintf("reset=%t", reset), func(b *testing.B) {
   767  			forBenchmarkSizes(b, func(b *testing.B, count int) {
   768  				insertP := perm(count)
   769  				var tr, trReset btree
   770  				for _, item := range insertP {
   771  					tr.Set(item)
   772  				}
   773  				b.ResetTimer()
   774  				for i := 0; i < b.N; i++ {
   775  					item := insertP[i%count]
   776  					if reset {
   777  						trReset.Reset()
   778  						trReset = tr
   779  					}
   780  					tr = tr.Clone()
   781  					tr.Delete(item)
   782  					tr.Set(item)
   783  				}
   784  			})
   785  		})
   786  	}
   787  }
   788  
   789  // BenchmarkBTreeMakeIter measures the cost of creating a btree iterator.
   790  func BenchmarkBTreeMakeIter(b *testing.B) {
   791  	var tr btree
   792  	for i := 0; i < b.N; i++ {
   793  		it := tr.MakeIter()
   794  		it.First()
   795  	}
   796  }
   797  
   798  // BenchmarkBTreeIterSeekGE measures the cost of seeking a btree iterator
   799  // forward.
   800  func BenchmarkBTreeIterSeekGE(b *testing.B) {
   801  	rng := rand.New(rand.NewSource(timeutil.Now().UnixNano()))
   802  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   803  		var spans []roachpb.Span
   804  		var tr btree
   805  
   806  		for i := 0; i < count; i++ {
   807  			s := span(i)
   808  			spans = append(spans, s)
   809  			tr.Set(newItem(s))
   810  		}
   811  
   812  		b.ResetTimer()
   813  		for i := 0; i < b.N; i++ {
   814  			s := spans[rng.Intn(len(spans))]
   815  			it := tr.MakeIter()
   816  			it.SeekGE(newItem(s))
   817  			if testing.Verbose() {
   818  				if !it.Valid() {
   819  					b.Fatal("expected to find key")
   820  				}
   821  				if !s.Equal(spanFromItem(it.Cur())) {
   822  					b.Fatalf("expected %s, but found %s", s, spanFromItem(it.Cur()))
   823  				}
   824  			}
   825  		}
   826  	})
   827  }
   828  
   829  // BenchmarkBTreeIterSeekLT measures the cost of seeking a btree iterator
   830  // backward.
   831  func BenchmarkBTreeIterSeekLT(b *testing.B) {
   832  	rng := rand.New(rand.NewSource(timeutil.Now().UnixNano()))
   833  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   834  		var spans []roachpb.Span
   835  		var tr btree
   836  
   837  		for i := 0; i < count; i++ {
   838  			s := span(i)
   839  			spans = append(spans, s)
   840  			tr.Set(newItem(s))
   841  		}
   842  
   843  		b.ResetTimer()
   844  		for i := 0; i < b.N; i++ {
   845  			j := rng.Intn(len(spans))
   846  			s := spans[j]
   847  			it := tr.MakeIter()
   848  			it.SeekLT(newItem(s))
   849  			if testing.Verbose() {
   850  				if j == 0 {
   851  					if it.Valid() {
   852  						b.Fatal("unexpected key")
   853  					}
   854  				} else {
   855  					if !it.Valid() {
   856  						b.Fatal("expected to find key")
   857  					}
   858  					s := spans[j-1]
   859  					if !s.Equal(spanFromItem(it.Cur())) {
   860  						b.Fatalf("expected %s, but found %s", s, spanFromItem(it.Cur()))
   861  					}
   862  				}
   863  			}
   864  		}
   865  	})
   866  }
   867  
   868  // BenchmarkBTreeIterFirstOverlap measures the cost of finding a single
   869  // overlapping item using a btree iterator.
   870  func BenchmarkBTreeIterFirstOverlap(b *testing.B) {
   871  	rng := rand.New(rand.NewSource(timeutil.Now().UnixNano()))
   872  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   873  		var spans []roachpb.Span
   874  		var tr btree
   875  
   876  		for i := 0; i < count; i++ {
   877  			s := spanWithEnd(i, i+1)
   878  			spans = append(spans, s)
   879  			tr.Set(newItem(s))
   880  		}
   881  
   882  		b.ResetTimer()
   883  		for i := 0; i < b.N; i++ {
   884  			j := rng.Intn(len(spans))
   885  			s := spans[j]
   886  			it := tr.MakeIter()
   887  			it.FirstOverlap(newItem(s))
   888  			if testing.Verbose() {
   889  				if !it.Valid() {
   890  					b.Fatal("expected to find key")
   891  				}
   892  				if !s.Equal(spanFromItem(it.Cur())) {
   893  					b.Fatalf("expected %s, but found %s", s, spanFromItem(it.Cur()))
   894  				}
   895  			}
   896  		}
   897  	})
   898  }
   899  
   900  // BenchmarkBTreeIterNext measures the cost of seeking a btree iterator to the
   901  // next item in the tree.
   902  func BenchmarkBTreeIterNext(b *testing.B) {
   903  	var tr btree
   904  
   905  	const count = 8 << 10
   906  	const size = 2 * maxItems
   907  	for i := 0; i < count; i++ {
   908  		item := newItem(spanWithEnd(i, i+size+1))
   909  		tr.Set(item)
   910  	}
   911  
   912  	it := tr.MakeIter()
   913  	b.ResetTimer()
   914  	for i := 0; i < b.N; i++ {
   915  		if !it.Valid() {
   916  			it.First()
   917  		}
   918  		it.Next()
   919  	}
   920  }
   921  
   922  // BenchmarkBTreeIterPrev measures the cost of seeking a btree iterator to the
   923  // previous item in the tree.
   924  func BenchmarkBTreeIterPrev(b *testing.B) {
   925  	var tr btree
   926  
   927  	const count = 8 << 10
   928  	const size = 2 * maxItems
   929  	for i := 0; i < count; i++ {
   930  		item := newItem(spanWithEnd(i, i+size+1))
   931  		tr.Set(item)
   932  	}
   933  
   934  	it := tr.MakeIter()
   935  	b.ResetTimer()
   936  	for i := 0; i < b.N; i++ {
   937  		if !it.Valid() {
   938  			it.First()
   939  		}
   940  		it.Prev()
   941  	}
   942  }
   943  
   944  // BenchmarkBTreeIterNextOverlap measures the cost of seeking a btree iterator
   945  // to the next overlapping item in the tree.
   946  func BenchmarkBTreeIterNextOverlap(b *testing.B) {
   947  	var tr btree
   948  
   949  	const count = 8 << 10
   950  	const size = 2 * maxItems
   951  	for i := 0; i < count; i++ {
   952  		item := newItem(spanWithEnd(i, i+size+1))
   953  		tr.Set(item)
   954  	}
   955  
   956  	allCmd := newItem(spanWithEnd(0, count+1))
   957  	it := tr.MakeIter()
   958  	b.ResetTimer()
   959  	for i := 0; i < b.N; i++ {
   960  		if !it.Valid() {
   961  			it.FirstOverlap(allCmd)
   962  		}
   963  		it.NextOverlap(allCmd)
   964  	}
   965  }
   966  
   967  // BenchmarkBTreeIterOverlapScan measures the cost of scanning over all
   968  // overlapping items using a btree iterator.
   969  func BenchmarkBTreeIterOverlapScan(b *testing.B) {
   970  	var tr btree
   971  	rng := rand.New(rand.NewSource(timeutil.Now().UnixNano()))
   972  
   973  	const count = 8 << 10
   974  	const size = 2 * maxItems
   975  	for i := 0; i < count; i++ {
   976  		tr.Set(newItem(spanWithEnd(i, i+size+1)))
   977  	}
   978  
   979  	b.ResetTimer()
   980  	for i := 0; i < b.N; i++ {
   981  		item := newItem(randomSpan(rng, count))
   982  		it := tr.MakeIter()
   983  		it.FirstOverlap(item)
   984  		for it.Valid() {
   985  			it.NextOverlap(item)
   986  		}
   987  	}
   988  }