github.com/bruceshao/lockfree@v1.1.3-0.20230816090528-e89824c0a6e9/example/perfect/main.go (about) 1 /* 2 * Copyright (C) THL A29 Limited, a Tencent company. All rights reserved. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 */ 7 8 package main 9 10 import ( 11 "fmt" 12 "github.com/bruceshao/lockfree" 13 "os" 14 "runtime/pprof" 15 "sync" 16 "sync/atomic" 17 "time" 18 ) 19 20 var ( 21 goSize = 10000 22 sizePerGo = 10000 23 cap = 1024 * 1024 24 timeAnalyse = false 25 ) 26 27 func main() { 28 f, _ := os.OpenFile("cpu.pprof", os.O_CREATE|os.O_RDWR, 0644) 29 defer f.Close() 30 pprof.StartCPUProfile(f) 31 defer pprof.StopCPUProfile() 32 // 启动命令: .exe [all/lockfree/chan] [time] 33 arg := "all" 34 if len(os.Args) > 1 { 35 arg = os.Args[1] 36 } 37 if len(os.Args) > 2 { 38 timeAnalyse = true 39 } 40 if arg == "all" { 41 fmt.Println("start lockfree and channel test") 42 // 表示全部启动 43 var wg sync.WaitGroup 44 wg.Add(2) 45 go func() { 46 defer wg.Done() 47 lockfreeMain() 48 }() 49 go func() { 50 defer wg.Done() 51 chanMain() 52 }() 53 wg.Wait() 54 } else if arg == "chan" { 55 fmt.Println("start channel test") 56 // 表示启动chan 57 var wg sync.WaitGroup 58 wg.Add(1) 59 go func() { 60 defer wg.Done() 61 chanMain() 62 }() 63 wg.Wait() 64 } else if arg == "lockfree" { 65 fmt.Println("start lockfree test") 66 // 表示启动lockfree 67 var wg sync.WaitGroup 68 wg.Add(1) 69 go func() { 70 defer wg.Done() 71 lockfreeMain() 72 }() 73 wg.Wait() 74 } 75 fmt.Println("all queue is over") 76 } 77 78 func lockfreeMain() { 79 var ( 80 t1_10us = uint64(0) // 1-10微秒 81 t10_100us = uint64(0) // 10-100微秒 82 t100_1000us = uint64(0) // 100-1000微秒 83 t1_10ms = uint64(0) // 1-10毫秒 84 t10_100ms = uint64(0) // 10-100毫秒 85 t100_ms = uint64(0) // 大于100毫秒 86 slower = uint64(0) 87 ) 88 // 创建事件处理器 89 eh := &longEventHandler[uint64]{} 90 // 创建消费端串行处理的Lockfree 91 lf := lockfree.NewLockfree[uint64](cap, eh, lockfree.NewSleepBlockStrategy(time.Millisecond)) 92 // 启动Lockfree 93 if err := lf.Start(); err != nil { 94 panic(err) 95 } 96 // lockfree计时 97 ts := time.Now() 98 // 获取生产者对象 99 producer := lf.Producer() 100 var wg sync.WaitGroup 101 wg.Add(goSize) 102 for i := 0; i < goSize; i++ { 103 go func(start int) { 104 if timeAnalyse { 105 for j := 0; j < sizePerGo; j++ { 106 //写入数据 107 tb := time.Now() 108 err := producer.Write(uint64(start*sizePerGo + j + 1)) 109 tl := time.Since(tb) 110 ms := tl.Microseconds() 111 if ms > 1 { 112 atomic.AddUint64(&slower, 1) 113 if ms < 10 { // t1_10us 114 atomic.AddUint64(&t1_10us, 1) 115 } else if ms < 100 { 116 atomic.AddUint64(&t10_100us, 1) 117 } else if ms < 1000 { 118 atomic.AddUint64(&t100_1000us, 1) 119 } else if ms < 10000 { 120 atomic.AddUint64(&t1_10ms, 1) 121 } else if ms < 100000 { 122 atomic.AddUint64(&t10_100ms, 1) 123 } else { 124 atomic.AddUint64(&t100_ms, 1) 125 } 126 } 127 if err != nil { 128 panic(err) 129 } 130 } 131 } else { 132 for j := 0; j < sizePerGo; j++ { 133 err := producer.Write(uint64(start*sizePerGo + j + 1)) 134 if err != nil { 135 panic(err) 136 } 137 } 138 } 139 wg.Done() 140 }(i) 141 } 142 wg.Wait() 143 fmt.Println("===== lockfree[", time.Now().Sub(ts), "] =====") 144 fmt.Println("----- lockfree write complete -----") 145 time.Sleep(3 * time.Second) 146 // 关闭Lockfree 147 lf.Close() 148 if timeAnalyse { 149 fmt.Printf("lockfree slow ratio = %.2f \n", float64(slower)*100.0/float64(goSize*sizePerGo)) 150 fmt.Printf("lockfree quick ratio = %.2f \n", float64(goSize*sizePerGo-int(slower))*100.0/float64(goSize*sizePerGo)) 151 fmt.Printf("lockfree [<1us][%d] \n", uint64(goSize*sizePerGo)-slower) 152 fmt.Printf("lockfree [1-10us][%d] \n", t1_10us) 153 fmt.Printf("lockfree [10-100us][%d] \n", t10_100us) 154 fmt.Printf("lockfree [100-1000us][%d] \n", t100_1000us) 155 fmt.Printf("lockfree [1-10ms][%d] \n", t1_10ms) 156 fmt.Printf("lockfree [10-100ms][%d] \n", t10_100ms) 157 fmt.Printf("lockfree [>100ms][%d] \n", t100_ms) 158 } 159 } 160 161 func chanMain() { 162 var ( 163 t1_10us = uint64(0) // 1-10微秒 164 t10_100us = uint64(0) // 10-100微秒 165 t100_1000us = uint64(0) // 100-1000微秒 166 t1_10ms = uint64(0) // 1-10毫秒 167 t10_100ms = uint64(0) // 10-100毫秒 168 t100_ms = uint64(0) // 大于100毫秒 169 slower = uint64(0) 170 ) 171 c := make(chan uint64, cap) 172 // 启动监听协程 173 go func() { 174 for { 175 x, ok := <-c 176 if !ok { 177 return 178 } 179 if x%10000000 == 0 { 180 fmt.Println("chan [", x, "]") 181 } 182 } 183 }() 184 // lockfree计时 185 ts := time.Now() 186 // 开始写入 187 var wg sync.WaitGroup 188 wg.Add(goSize) 189 for i := 0; i < goSize; i++ { 190 go func(start int) { 191 if timeAnalyse { 192 for j := 0; j < sizePerGo; j++ { 193 //写入数据 194 tb := time.Now() 195 c <- uint64(start*sizePerGo + j + 1) 196 tl := time.Since(tb) 197 ms := tl.Microseconds() 198 if ms > 1 { 199 atomic.AddUint64(&slower, 1) 200 if ms < 10 { // t1_10us 201 atomic.AddUint64(&t1_10us, 1) 202 } else if ms < 100 { 203 atomic.AddUint64(&t10_100us, 1) 204 } else if ms < 1000 { 205 atomic.AddUint64(&t100_1000us, 1) 206 } else if ms < 10000 { 207 atomic.AddUint64(&t1_10ms, 1) 208 } else if ms < 100000 { 209 atomic.AddUint64(&t10_100ms, 1) 210 } else { 211 atomic.AddUint64(&t100_ms, 1) 212 } 213 } 214 } 215 } else { 216 for j := 0; j < sizePerGo; j++ { 217 //写入数据 218 c <- uint64(start*sizePerGo + j + 1) 219 } 220 } 221 wg.Done() 222 }(i) 223 } 224 wg.Wait() 225 fmt.Println("=====channel[", time.Now().Sub(ts), "]=====") 226 fmt.Println("----- channel write complete -----") 227 time.Sleep(3 * time.Second) 228 // 关闭chan 229 close(c) 230 if timeAnalyse { 231 fmt.Printf("channel slow ratio = %.2f \n", float64(slower)*100.0/float64(goSize*sizePerGo)) 232 fmt.Printf("channel quick ratio = %.2f \n", float64(goSize*sizePerGo-int(slower))*100.0/float64(goSize*sizePerGo)) 233 fmt.Printf("channel [<1us][%d] \n", uint64(goSize*sizePerGo)-slower) 234 fmt.Printf("channel [1-10us][%d] \n", t1_10us) 235 fmt.Printf("channel [10-100us][%d] \n", t10_100us) 236 fmt.Printf("channel [100-1000us][%d] \n", t100_1000us) 237 fmt.Printf("channel [1-10ms][%d] \n", t1_10ms) 238 fmt.Printf("channel [10-100ms][%d] \n", t10_100ms) 239 fmt.Printf("channel [>100ms][%d] \n", t100_ms) 240 } 241 } 242 243 type longEventHandler[T uint64] struct { 244 } 245 246 func (h *longEventHandler[T]) OnEvent(v uint64) { 247 if v%10000000 == 0 { 248 fmt.Println("lockfree [", v, "]") 249 } 250 }