1package diodes_test 2 3import ( 4 "crypto/rand" 5 "io/ioutil" 6 "log" 7 "os" 8 "sync" 9 "testing" 10 "time" 11 12 "code.cloudfoundry.org/go-diodes" 13) 14 15var randData = randDataGen() 16 17func TestMain(m *testing.M) { 18 log.SetOutput(ioutil.Discard) 19 20 os.Exit(m.Run()) 21} 22 23func BenchmarkOneToOnePoller(b *testing.B) { 24 d := diodes.NewPoller(diodes.NewOneToOne(b.N, diodes.AlertFunc(func(missed int) { 25 panic("Oops...") 26 }))) 27 28 var wg sync.WaitGroup 29 wg.Add(1) 30 defer wg.Wait() 31 32 go func() { 33 defer wg.Done() 34 for i := 0; i < b.N; i++ { 35 data := randData(i) 36 d.Set(diodes.GenericDataType(data)) 37 } 38 }() 39 40 b.ResetTimer() 41 42 for i := 0; i < b.N; i++ { 43 d.Next() 44 } 45} 46 47func BenchmarkOneToOneWaiter(b *testing.B) { 48 d := diodes.NewWaiter(diodes.NewOneToOne(b.N, diodes.AlertFunc(func(missed int) { 49 panic("Oops...") 50 }))) 51 52 var wg sync.WaitGroup 53 wg.Add(1) 54 defer wg.Wait() 55 56 go func() { 57 defer wg.Done() 58 for i := 0; i < b.N; i++ { 59 data := randData(i) 60 d.Set(diodes.GenericDataType(data)) 61 } 62 }() 63 64 b.ResetTimer() 65 66 for i := 0; i < b.N; i++ { 67 d.Next() 68 } 69} 70 71func BenchmarkManyToOnePoller(b *testing.B) { 72 d := diodes.NewPoller(diodes.NewManyToOne(b.N, diodes.AlertFunc(func(missed int) { 73 panic("Oops...") 74 }))) 75 76 var wg sync.WaitGroup 77 wg.Add(1) 78 defer wg.Wait() 79 80 go func() { 81 defer wg.Done() 82 for i := 0; i < b.N; i++ { 83 data := randData(i) 84 d.Set(diodes.GenericDataType(data)) 85 } 86 }() 87 88 b.ResetTimer() 89 90 for i := 0; i < b.N; i++ { 91 d.Next() 92 } 93} 94 95func BenchmarkManyToOneWaiter(b *testing.B) { 96 d := diodes.NewWaiter(diodes.NewManyToOne(b.N, diodes.AlertFunc(func(missed int) { 97 panic("Oops...") 98 }))) 99 100 var wg sync.WaitGroup 101 wg.Add(1) 102 defer wg.Wait() 103 104 go func() { 105 defer wg.Done() 106 for i := 0; i < b.N; i++ { 107 data := randData(i) 108 d.Set(diodes.GenericDataType(data)) 109 } 110 }() 111 112 b.ResetTimer() 113 114 for i := 0; i < b.N; i++ { 115 d.Next() 116 } 117} 118 119func BenchmarkChannel(b *testing.B) { 120 c := make(chan []byte, b.N) 121 122 var wg sync.WaitGroup 123 wg.Add(1) 124 defer wg.Wait() 125 126 go func() { 127 defer wg.Done() 128 for i := 0; i < b.N; i++ { 129 data := randData(i) 130 c <- *data 131 } 132 }() 133 134 b.ResetTimer() 135 136 for i := 0; i < b.N; i++ { 137 <-c 138 } 139} 140 141func BenchmarkOneToOnePollerDrain(b *testing.B) { 142 d := diodes.NewPoller(diodes.NewOneToOne(100, diodes.AlertFunc(func(missed int) { 143 // NOP 144 }))) 145 146 var wg sync.WaitGroup 147 wg.Add(1) 148 149 go func() { 150 wg.Done() 151 for { 152 d.Next() 153 } 154 }() 155 156 wg.Wait() 157 b.ResetTimer() 158 159 for i := 0; i < b.N; i++ { 160 data := randData(i) 161 d.Set(diodes.GenericDataType(data)) 162 } 163} 164 165func BenchmarkOneToOneWaiterDrain(b *testing.B) { 166 d := diodes.NewWaiter(diodes.NewOneToOne(100, diodes.AlertFunc(func(missed int) { 167 // NOP 168 }))) 169 170 var wg sync.WaitGroup 171 wg.Add(1) 172 go func() { 173 wg.Done() 174 for { 175 d.Next() 176 } 177 }() 178 179 wg.Wait() 180 b.ResetTimer() 181 182 for i := 0; i < b.N; i++ { 183 data := randData(i) 184 d.Set(diodes.GenericDataType(data)) 185 } 186} 187 188func BenchmarkChannelDrain(b *testing.B) { 189 c := make(chan []byte, 100) 190 var wg sync.WaitGroup 191 wg.Add(1) 192 193 go func() { 194 wg.Done() 195 for range c { 196 } 197 }() 198 199 wg.Wait() 200 b.ResetTimer() 201 202 for i := 0; i < b.N; i++ { 203 data := randData(i) 204 select { 205 case c <- *data: 206 default: 207 drainChannel(c) 208 } 209 } 210} 211 212func BenchmarkManyWritersDiode(b *testing.B) { 213 d := diodes.NewWaiter(diodes.NewManyToOne(10000, diodes.AlertFunc(func(int) { 214 // NOP 215 }))) 216 217 var wg sync.WaitGroup 218 wg.Add(1) 219 220 go func() { 221 wg.Done() 222 for { 223 d.Next() 224 time.Sleep(100 * time.Millisecond) 225 } 226 }() 227 228 wg.Wait() 229 b.ResetTimer() 230 b.RunParallel(func(pb *testing.PB) { 231 var i int 232 for pb.Next() { 233 data := randData(i) 234 i++ 235 d.Set(diodes.GenericDataType(data)) 236 } 237 }) 238} 239 240func BenchmarkManyWritersChannel(b *testing.B) { 241 c := make(chan []byte, 10000) 242 243 var wg sync.WaitGroup 244 wg.Add(1) 245 246 go func() { 247 wg.Done() 248 for range c { 249 time.Sleep(100 * time.Millisecond) 250 } 251 }() 252 253 wg.Wait() 254 b.ResetTimer() 255 b.RunParallel(func(pb *testing.PB) { 256 var i int 257 for pb.Next() { 258 data := randData(i) 259 i++ 260 select { 261 case c <- *data: 262 default: 263 drainChannel(c) 264 } 265 } 266 }) 267} 268 269func drainChannel(c chan []byte) { 270 for { 271 select { 272 case <-c: 273 default: 274 return 275 } 276 } 277} 278 279func randDataGen() func(int) *[]byte { 280 var ( 281 data [][]byte 282 ) 283 284 for j := 0; j < 5; j++ { 285 buffer := make([]byte, 100) 286 rand.Read(buffer) 287 data = append(data, buffer) 288 } 289 290 return func(i int) *[]byte { 291 return &data[i%len(data)] 292 } 293} 294