golang 单协程和多协程的性能测试
|
测试数据:单协程操作1亿数据,以及多协程(10条协程)操作1亿数据(每条协程操作1kw数据) 废话少说,贴代码: 单协程测试运算: package main
import (
"fmt"
"time"
)
func testNum(num int) {
for i := 1; i <= 10000000; i++{
num = num + i
num = num - i
num = num * i
num = 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 main
import (
"fmt"
"time"
"sync"
)
var synWait sync.WaitGroup
func testNum(num int) {
for i := 1; i <= 10000000; i++{
num = num + i
num = num - i
num = num * i
num = 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 main
import (
"fmt"
"time"
"sync"
)
var synWait sync.WaitGroup
var normalMap map[int]int
var synMutex sync.Mutex
func testNum(num int) {
for i := 1; i <= 10000000; i++{
synMutex.Lock()
normalMap[i] = num
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 ? 协程通道测试map: package main
import (
"fmt"
"time"
"sync"
)
var synWait sync.WaitGroup
var normalMap map[int]int
func 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 := <- data
normalMap[i] = i
}
}
运行时间为:53.554329275 通道内部实现也是加锁,这肯定是要比纯用锁慢一点的,这也正好验证了(网上有些人说通道要比加锁快,这是错误的)。但是使用通道是golang的一种哲学意义,规定了入口,里面的数据 结构就不要再担忧,是否要加锁了,因为全部都是安全的(可以避免很多bug,毕竟程序大部分问题还是出自程序员的逻辑代码),还是那句话 ? 总结一下吧:(map性能 单协程 > 多协程 > 通道 ) 多协程去运算确实快比单协程要快,因为golang会默认根据多核去跑,但是操作map的时候,就要注意,map并发操作效率不及单协程(有点违背多核的感觉)。通道又比纯加锁要慢。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Inno Setup打包的安装程序在Vista/Win7上自动提示需要管理员
- Perl Class :: Accessor失败,简单的例子 – 为什么?
- [bigdata-040] cloudera manager web服务故障处理
- 在Golang中复制文件的简单方法
- 数据挖掘-关联分析频繁模式挖掘Apriori、FP-Growth及Eclat算
- 基于Delphi的Excel动态报表技术
- thinkphp隐藏index.php/home并允许访问其他模块的实现方法
- vb.net – vb 2008使用一行代码设置数组项
- delphi – 如何强制SConscript构建器更改目录?
- Delphi中本年、本月、本周的第一天和最后天
