github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/14_concurrent/disruptor/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "github.com/smartystreets/go-disruptor" 6 "runtime" 7 "sync" 8 "time" 9 ) 10 11 const ( 12 RingBufferSize = 1024 * 64 13 RingBufferMask = RingBufferSize - 1 14 ReserveOne = 1 15 ReserveMany = 16 16 ReserveManyDelta = ReserveMany - 1 17 DisruptorCleanup = time.Millisecond * 10 18 ) 19 20 var ringBuffer = [RingBufferSize]int64{} 21 22 type countConsumer struct { 23 Count int64 24 TotalIterations int64 25 WG sync.WaitGroup 26 } 27 28 func (cc *countConsumer) Consume(lower, upper int64) { 29 for lower <= upper { 30 message := ringBuffer[lower&RingBufferMask] 31 if message != lower { 32 warning := fmt.Sprintf("\nRace condition--Sequence: %d, Message: %d\n", lower, message) 33 fmt.Printf(warning) 34 panic(warning) 35 } 36 lower++ 37 cc.Count++ 38 //fmt.Printf("count: %d, message: %d\n", cc.Count-1, message) 39 if cc.Count == cc.TotalIterations { 40 cc.WG.Done() 41 return 42 } 43 } 44 } 45 46 func main() { 47 NumPublishers := runtime.NumCPU() 48 totalIterations := int64(1000 * 1000 * 20) 49 iterations := totalIterations / int64(NumPublishers) 50 totalIterations = iterations * int64(NumPublishers) 51 52 fmt.Printf("Total: %d, Iterations: %d, Publisher: %d, Consumer: 1\n", totalIterations, iterations, NumPublishers) 53 54 runtime.GOMAXPROCS(NumPublishers) 55 var consumer = &countConsumer{TotalIterations: totalIterations, Count: 0} 56 consumer.WG.Add(1) 57 58 controller := disruptor.Configure(RingBufferSize).WithConsumerGroup(consumer).BuildShared() 59 controller.Start() 60 defer controller.Stop() 61 var wg sync.WaitGroup 62 wg.Add(NumPublishers + 1) 63 var sendWG sync.WaitGroup 64 sendWG.Add(NumPublishers) 65 for i := 0; i < NumPublishers; i++ { 66 go func() { 67 writer := controller.Writer() 68 wg.Done() 69 wg.Wait() 70 current := disruptor.InitialSequenceValue 71 for current < totalIterations { 72 current = writer.Reserve(ReserveMany) 73 for j := current - ReserveMany + 1; j <= current; j++ { 74 ringBuffer[j&RingBufferMask] = j 75 } 76 writer.Commit(current-ReserveMany, current) 77 } 78 sendWG.Done() 79 }() 80 } 81 wg.Done() 82 t := time.Now().UnixNano() 83 wg.Wait() //waiting for ready as a barrier 84 fmt.Println("start to publish") 85 sendWG.Wait() 86 fmt.Println("Finished to publish") 87 consumer.WG.Wait() 88 fmt.Println("Finished to consume") //waiting for consumer 89 t = (time.Now().UnixNano() - t) / 1000000 //ms 90 fmt.Printf("opsPerSecond: %d\n", totalIterations*1000/t) 91 92 }