golang 单协程和多协程的性能测试
测试数据:单协程操作1亿数据,以及多协程(10条协程)操作1亿数据(每条协程操作1kw数据)
废话少说,贴代码:
单协程测试运算:
package mainimport ("fmt""time"
)func testNum(num int) {for i := 1; i <= 10000000; i++{num = num + inum = num - inum = num * inum = num / i}
}func main() {start := time.Now()for i := 1; i <= 10; i++ {testNum(1)}end := time.Now()fmt.Println(end.Sub(start).Seconds())
}
运行时间为:0.065330877
多协程测试运算:
package mainimport ("fmt""time""sync"
)var synWait sync.WaitGroupfunc testNum(num int) {for i := 1; i <= 10000000; i++{num = num + inum = num - inum = num * inum = num / i}synWait.Done() // 相当于 synWait.Add(-1)
}func main() {start := time.Now()for i := 1; i <= 10; i++ {synWait.Add(1)go testNum(1)}synWait.Wait()end := time.Now()fmt.Println(end.Sub(start).Seconds())
}
运行时间为:0.019804929
比较结果,和预期的是一样,多协程要比单协程处理数据快,很多人还会去设置runtime.GOMAXPROCS(x),其实
这是远古程序员的做法了,因为go 1.6以上的版本就已经会自动根据计算机核的调用啦!!!
如果没有调用runtime.GOMAXPROCS 去设置CPU,Golang默认使用所有的cpu核。
以下是以map来做实验,为了测试准确性,统一都加锁
单协程/多协程测试map:
package mainimport ("fmt""time""sync"
)var synWait sync.WaitGroup
var normalMap map[int]int
var synMutex sync.Mutexfunc testNum(num int) {for i := 1; i <= 10000000; i++{synMutex.Lock()normalMap[i] = num // testslic = append(testslic, num) 这里slice也是一样的道理synMutex.Unlock()}synWait.Done() // 相当于 synWait.Add(-1)
}func main() {normalMap = make(map[int]int)start := time.Now()for i := 1; i <= 10; i++ {synWait.Add(1)testNum(1) // 单协程操作//go testNum(1) // 多协程并发操作}synWait.Wait()end := time.Now()fmt.Println(end.Sub(start).Seconds())
}
单协程操作 testNum(1), 运行时间为:19.101255922
多协程操作 go testNum(1), 运行时间为:28.210580532
是不是出乎意料!!! 多协程操作map反而慢,这说明map这个数据结构对并发操作效率比较低,如果在保证线性安全的前提下
尽量单协程去操作map,如果上面代码注释掉加锁,单协程操作就更快了, 运行时间为:16.307839364
原因为什么呢???这篇博客有所阐述:https://www.cnblogs.com/ipub520/p/7718905.html
协程通道测试map:
package mainimport ("fmt""time""sync"
)var synWait sync.WaitGroup
var normalMap map[int]intfunc testNum(data chan int, num int) {for i:=1;i<=10000000;i++{data <- i}synWait.Done()
}func main() {normalMap = make(map[int]int)data := make(chan int)start := time.Now()go concurrent(data)for i := 1; i <= 10; i++ {synWait.Add(1)go testNum(data,1) // 多协程并发操作}synWait.Wait()end := time.Now()fmt.Println(end.Sub(start).Seconds())
}func concurrent(data chan int) {for {i := <- datanormalMap[i] = i}
}
运行时间为:53.554329275
通道内部实现也是加锁,这肯定是要比纯用锁慢一点的,这也正好验证了(网上有些人说通道要比加锁快,这是错误的)。但是使用通道是golang的一种哲学意义,规定了入口,里面的数据
结构就不要再担忧,是否要加锁了,因为全部都是安全的(可以避免很多bug,毕竟程序大部分问题还是出自程序员的逻辑代码),还是那句话不要通过共享内存来通信,而要通过通信来共享内存!
slice也是和map差不多的,并发append的时候也必须加锁
我们举一个简单例子,比如,当A和B两个协程运行append的时候同时发现s[1]这个位置是空的,他们就都会把自己的值放在这个位置,这样他们两个的值就会覆盖,造成数据丢失。
总结一下吧:(map性能 单协程 > 多协程 > 通道 )
多协程去运算确实快比单协程要快,因为golang会默认根据多核去跑,但是如果操作涉及到加锁的时候(例如map,slice),就要注意,并发操作效率不及单协程(这点和erlang操作ets不一样,erlang恰好相反)。
转载于:https://www.cnblogs.com/huangliang-hb/p/10173175.html
golang 单协程和多协程的性能测试相关推荐
- Golang并发模型:轻松入门协程池
goroutine是非常轻量的,不会暂用太多资源,基本上有多少任务,我们可以开多少goroutine去处理.但有时候,我们还是想控制一下. 比如,我们有A.B两类工作,不想把太多资源花费在B类务上,而 ...
- python 协程_Python 协程与 Go 协程的区别(一)
? "Python猫" ,一个值得加星标的公众号 花下猫语:年关将近,不知各位过得怎样?我最近有些忙,收获也挺多,以后有机会分享下.吃饭时间,追了两部剧<了不起的麦瑟尔夫人& ...
- 干货 | 携程基于Quasar协程的NIO实践
作者简介 Ryan,携程Java开发工程师,对高并发.网络编程等领域有浓厚兴趣. IO密集型系统在高并发场景下,会有大量线程处于阻塞状态,性能低下,JAVA上成熟的非阻塞IO(NIO)技术可解决该问题 ...
- 携程基于Quasar协程的NIO实践
IO密集型系统在高并发场景下,会有大量线程处于阻塞状态,性能低下,JAVA上成熟的非阻塞IO(NIO)技术可解决该问题.目前Java项目对接NIO的方式主要依靠回调,代码复杂度高,降低了代码可读性与可 ...
- java 修改最大nio连接数_携程基于Quasar协程的NIO实践
IO密集型系统在高并发场景下,会有大量线程处于阻塞状态,性能低下,JAVA上成熟的非阻塞IO(NIO)技术可解决该问题.目前Java项目对接NIO的方式主要依靠回调,代码复杂度高,降低了代码可读性与可 ...
- python 协程可以嵌套协程吗_Python | 详解Python中的协程,为什么说它的底层是生成器?...
今天是Python专题的第26篇文章,我们来聊聊Python当中的协程. 我们曾经在golang关于goroutine的文章当中简单介绍过协程的概念,我们再来简单review一下.协程又称为是微线程, ...
- python携程多核_python 协程
最近对Python中的协程挺感兴趣,这里记录对协程的个人理解. 要理解协程,首先需要知道生成器是什么.生成器其实就是不断产出值的函数,只不过在函数中需要使用yield这一个关键词将值产出.下面来看一个 ...
- python 协程可以嵌套协程吗_Python学习后有哪些方向可以选择?Python有什么好的学习方法吗?(附教程)...
随着人工智能的发展,Python近两年也是大火,越来越多的人加入到Python学习大军,对于毫无基础的人该如何入门Python呢?这里整理了一些个人经验和Python入门教程供大家参考. 如果你是零基 ...
- Go 知识点(01)— 主协程与子协程执行顺序
下面代码的输出结果是什么? package mainimport ("fmt" )func main() {for i := 0; i < 10; i++ {go func( ...
- python 协程和异步的关系_python协程与异步协程
在前面几个博客中我们一一对应解决了消费者消费的速度跟不上生产者,浪费我们大量的时间去等待的问题,在这里,针对业务逻辑比较耗时间的问题,我们还有除了多进程之外更优的解决方式,那就是协程和异步协程.在引入 ...
最新文章
- python给空列表赋值_python – 赋值前引用的局部变量’list’
- 微软算法100题26 左旋转字符串
- explain ref_数据库查询优化:使用explain分析sql语句执行效率
- 思考一下消息中间件的设计
- Oracle用户system解锁
- idead断点调试_IDEA---断点调试Debug
- php解析压缩包csv文件,php解析csv文件
- Qt数据库应用11-通用数据生成器
- python画出心形图
- CEOI 2020, Day 2 A,B题解 CF1403A CF1403B
- GBK,UTF8是什么?
- ORA-00600: internal error code 内部错误代码
- Codeforces 1091F New Year and the Mallard Expedition
- buuctf old-fashion 1 世上无难事
- xilinx官网下载vivado等软件工具无法下载原因,报错:xilinx官网 由于您的帐号输出合规验证失败,我们无法满足您的请求。
- 承受自律的苦,不要承受自责的悔
- Python数据可视化:学术图表可视化(实战篇—5)
- LED点阵 1088AS(共阴) 8X8点亮
- Android测试solo,SoloPi支付宝开源的 Android 专项测试工具的介绍与快速上手
- 【makefile】Linux之Makefile(findstring)
热门文章
- Node实现的异步I/O
- mysql 怎么修改成新字段_Mysql入门第一课《建表、改表、删表》
- uc3842改可调电源教程_《学习笔记》--DC/DC电源电路设计实例
- 大一考二级c语言,大专学生计算机二级是大一考还是大二考
- centos8共享文件夹挂载_linux挂载群辉的NFS共享文件夹
- ASP.NET的TreeView和Menu控件分别绑定siteMap和xml文件并应用母版
- Windows 取消 Lock Screen 显示
- 20200922:leetcode35周双周赛题解记录(下)
- 20191021:(leetcode习题)乘积小于K的子数组
- 拉普拉斯算子属于卷积方法吗_论文笔记 - 图卷积神经网络综述