Go协程常规参考

发布时间 2023-06-01 15:18:42作者: Jrri

Go协程

协程对性能的提升:
程序性能由三者决定: 计算时长, 磁盘IO, 网络IO
协程能有效解决IO问题.
对于计算密集型程序则用处较小.

1. 最佳协程使用实践

// 子协程
func CoroutineSubFunc(wg *sync.WaitGroup, resultChannel chan int, limiter chan bool) {
	defer wg.Done()
	result := time.Now().Minute()
	result += 10000
	resultChannel <- result // 单个结果
	<-limiter
}
// 主协程
func CoroutineMainFunc() {
	var wg = &sync.WaitGroup{}  
	var limiter = make(chan bool, 10) // 限制器,10个协程  
	var resultSlice []int // 结果列表  
	var resultChannel = make(chan int, 100)  
	defer close(limiter)
	go func() {
		for response := range resultChannel {
			resultSlice = append(resultSlice, response)
		}
	}()
	for i := 0; i < 10000000; i++ {
		wg.Add(1)
		limiter <- true
		go CoroutineSubFunc(wg, resultChannel, limiter)
	}
	wg.Wait()
	close(resultChannel)
}

2. 协程限制器的必要性(双channel)

网络IO
//limiter <- true  
// 是否单独添加限制器的影响  
//before:  
//Update耗时-Git仓库信息-获取项目人员:1.8998607s  
//Update耗时-Git仓库信息-获取项目人员:1.7111329s  
//Update耗时-Git仓库信息-获取项目人员:1.7577459s  
//Update耗时-Git仓库信息-获取项目人员:1.7185806s  
//Update耗时-Git仓库信息-获取项目人员:1.796424s  
// after:  
//Update耗时-Git仓库信息-获取项目人员:1.9105957s  
//Update耗时-Git仓库信息-获取项目人员:2.0276002s  
//Update耗时-Git仓库信息-获取项目人员:1.8378465s  
//Update耗时-Git仓库信息-获取项目人员:1.9639478s  
//Update耗时-Git仓库信息-获取项目人员:1.9181765s  
计算密集型
// 10mlion, 是否单独添加限制器的影响  
//before:  

//耗时:17.7392589s
耗时:10.6744323s
耗时:12.0589872s
耗时:10.6573216s
耗时:13.3833896s
耗时:10.2832911s
// after:  
//耗时:4.862482s
耗时:4.8140741s
耗时:4.9224885s
耗时:4.8152887s
耗时:4.8263113s
耗时:4.8267736s

高并发场景为什么需要限制器?

协程本身切换是需要保存上下文的, 尽管保存每个协程的开销并不大. 但如果有极高并发的情况下, 没有对应的协程限制器, 从而无限制的制造新的协程, 反而会因为内存占用过多, 导致程序运行缓慢. 严重时会导致程序卡死.
增加协程限制器, 能避免RAM无限制增涨, 以提升效率.

3. 双等待池的处理方式(双WaitGroup)

双等待池的处理方式, 一般是在处理针对协程函数有返回数据的时候.
使用第二的等待池来对chan进行读取.

计算密集: 10milion数据

// 单Group
耗时:4.8263338s
耗时:4.8079532s
耗时:4.8333302s
耗时:4.8605043s
耗时:4.8274169s

// 双Group
耗时:4.8698299s
耗时:4.9381441s
耗时:4.8381543s
耗时:4.9011613s
耗时:4.9681705s

网络IO密集: 1000数据
// 单Group
Update耗时: 2.7795841s
Update耗时: 2.7134584s
Update耗时: 2.9046917s
Update耗时: 2.8001659s
Update耗时: 2.7793065s
// 双Group
Update耗时 :2.9160356s
Update耗时 :2.808227s
Update耗时 :2.7915349s
Update耗时 :2.8187473s
Update耗时 :2.7912972s

综上所述:
因为已经有同一个channel, 对其进行限制.
所以双WaitGroup对于协程取值来讲, 并无必要性.
反而会因为对应的开销, 导致性能相对较慢.

必要性: 保证数据完整性.
性能影响: 增加开销, 性能略微下降