github.com/Jeffail/benthos/v3@v3.65.0/internal/transaction/benchmarks_test.go (about) 1 package transaction 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 func BenchmarkTransactionsChannelN10(b *testing.B) { 13 benchmarkTransactionsChannelBased(b, 10) 14 } 15 16 func BenchmarkTransactionsChannelN100(b *testing.B) { 17 benchmarkTransactionsChannelBased(b, 100) 18 } 19 20 func BenchmarkTransactionsChannelN1000(b *testing.B) { 21 benchmarkTransactionsChannelBased(b, 1000) 22 } 23 24 func BenchmarkTransactionsChannelN10000(b *testing.B) { 25 benchmarkTransactionsChannelBased(b, 10000) 26 } 27 28 func BenchmarkTransactionsFuncN10(b *testing.B) { 29 benchmarkTransactionsFuncBased(b, 10) 30 } 31 32 func BenchmarkTransactionsFuncN100(b *testing.B) { 33 benchmarkTransactionsFuncBased(b, 100) 34 } 35 36 func BenchmarkTransactionsFuncN1000(b *testing.B) { 37 benchmarkTransactionsFuncBased(b, 1000) 38 } 39 40 func BenchmarkTransactionsFuncN10000(b *testing.B) { 41 benchmarkTransactionsFuncBased(b, 10000) 42 } 43 44 type messageDumb struct { 45 raw []byte 46 } 47 48 type transactionChanRes struct { 49 m messageDumb 50 resChan chan<- error 51 } 52 53 type transactionFnRes struct { 54 m messageDumb 55 resFn func(context.Context, error) error 56 } 57 58 func benchmarkTransactionsChannelBased(b *testing.B, buffered int) { 59 tChan := make(chan transactionChanRes) 60 61 b.ReportAllocs() 62 63 var wg sync.WaitGroup 64 go func() { 65 for i := 0; i < b.N; i++ { 66 wg.Add(1) 67 68 rChan := make(chan error) 69 tChan <- transactionChanRes{ 70 m: messageDumb{raw: []byte(fmt.Sprintf("hello world %v", i))}, 71 resChan: rChan, 72 } 73 74 go func() { 75 defer wg.Done() 76 <-rChan 77 }() 78 } 79 close(tChan) 80 }() 81 82 rChans := make([]chan<- error, buffered) 83 ackAll := func() { 84 for j := 0; j < buffered; j++ { 85 if rChans[j] == nil { 86 return 87 } 88 rChans[j] <- nil 89 } 90 } 91 for { 92 for j := 0; j < buffered; j++ { 93 rChans[j] = nil 94 } 95 for j := 0; j < buffered; j++ { 96 tran, open := <-tChan 97 if !open { 98 ackAll() 99 wg.Wait() 100 return 101 } 102 rChans[j] = tran.resChan 103 } 104 ackAll() 105 } 106 } 107 108 func benchmarkTransactionsFuncBased(b *testing.B, buffered int) { 109 tChan := make(chan transactionFnRes) 110 111 b.ReportAllocs() 112 113 var wg sync.WaitGroup 114 go func() { 115 for i := 0; i < b.N; i++ { 116 wg.Add(1) 117 tChan <- transactionFnRes{ 118 m: messageDumb{raw: []byte(fmt.Sprintf("hello world %v", i))}, 119 resFn: func(c context.Context, e error) error { 120 wg.Done() 121 return nil 122 }, 123 } 124 } 125 close(tChan) 126 }() 127 128 rFns := make([]func(context.Context, error) error, buffered) 129 ackAll := func() { 130 for j := 0; j < buffered; j++ { 131 if rFns[j] == nil { 132 return 133 } 134 require.NoError(b, rFns[j](context.Background(), nil)) 135 } 136 } 137 for { 138 for j := 0; j < buffered; j++ { 139 rFns[j] = nil 140 } 141 for j := 0; j < buffered; j++ { 142 tran, open := <-tChan 143 if !open { 144 ackAll() 145 wg.Wait() 146 return 147 } 148 rFns[j] = tran.resFn 149 } 150 ackAll() 151 } 152 }