github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/execinfra/base_test.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package execinfra 12 13 import ( 14 "context" 15 "fmt" 16 "sync" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/sql/execinfrapb" 20 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 21 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 22 "github.com/cockroachdb/cockroach/pkg/sql/types" 23 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 24 ) 25 26 // Test the behavior of Run in the presence of errors that switch to the drain 27 // and forward metadata mode. 28 func TestRunDrain(t *testing.T) { 29 defer leaktest.AfterTest(t)() 30 31 ctx := context.Background() 32 33 // A source with no rows and 2 ProducerMetadata messages. 34 src := &RowChannel{} 35 src.InitWithBufSizeAndNumSenders(nil, 10, 1) 36 src.Push(nil /* row */, &execinfrapb.ProducerMetadata{Err: fmt.Errorf("test")}) 37 src.Push(nil /* row */, nil /* meta */) 38 src.Start(ctx) 39 40 // A receiver that is marked as done consuming rows so that Run will 41 // immediately move from forwarding rows and metadata to draining metadata. 42 buf := &RowChannel{} 43 buf.InitWithBufSizeAndNumSenders(nil, 10, 1) 44 buf.ConsumerDone() 45 46 Run(ctx, src, buf) 47 48 if src.ConsumerStatus != DrainRequested { 49 t.Fatalf("expected DrainRequested, but found %d", src.ConsumerStatus) 50 } 51 } 52 53 // Benchmark a pipeline of RowChannels. 54 func BenchmarkRowChannelPipeline(b *testing.B) { 55 for _, length := range []int{1, 2, 3, 4} { 56 b.Run(fmt.Sprintf("length=%d", length), func(b *testing.B) { 57 rc := make([]RowChannel, length) 58 var wg sync.WaitGroup 59 wg.Add(len(rc)) 60 61 for i := range rc { 62 rc[i].InitWithNumSenders(sqlbase.OneIntCol, 1) 63 64 go func(i int) { 65 defer wg.Done() 66 cur := &rc[i] 67 var next *RowChannel 68 if i+1 != len(rc) { 69 next = &rc[i+1] 70 } 71 for { 72 row, meta := cur.Next() 73 if row == nil { 74 if next != nil { 75 next.ProducerDone() 76 } 77 break 78 } 79 if next != nil { 80 _ = next.Push(row, meta) 81 } 82 } 83 }(i) 84 } 85 86 row := sqlbase.EncDatumRow{ 87 sqlbase.DatumToEncDatum(types.Int, tree.NewDInt(tree.DInt(1))), 88 } 89 b.SetBytes(int64(8 * 1 * 1)) 90 for i := 0; i < b.N; i++ { 91 _ = rc[0].Push(row, nil /* meta */) 92 } 93 rc[0].ProducerDone() 94 wg.Wait() 95 }) 96 } 97 } 98 99 func BenchmarkMultiplexedRowChannel(b *testing.B) { 100 numRows := 1 << 16 101 row := sqlbase.EncDatumRow{sqlbase.IntEncDatum(0)} 102 for _, senders := range []int{2, 4, 8} { 103 b.Run(fmt.Sprintf("senders=%d", senders), func(b *testing.B) { 104 b.SetBytes(int64(senders * numRows * 8)) 105 for i := 0; i < b.N; i++ { 106 var wg sync.WaitGroup 107 wg.Add(senders + 1) 108 mrc := &RowChannel{} 109 mrc.InitWithNumSenders(sqlbase.OneIntCol, senders) 110 go func() { 111 for { 112 if r, _ := mrc.Next(); r == nil { 113 break 114 } 115 } 116 wg.Done() 117 }() 118 for j := 0; j < senders; j++ { 119 go func() { 120 for k := 0; k < numRows; k++ { 121 mrc.Push(row, nil /* meta */) 122 } 123 mrc.ProducerDone() 124 wg.Done() 125 }() 126 } 127 wg.Wait() 128 } 129 }) 130 } 131 }