我昨天用几乎相同的代码发布了一个问题,询问如何在可变参数函数中进行并发。解决之后,我预计程序与一台发电机的运行时间几乎相同,与30+一样。它似乎并非如此。
我看到的时间是一台发电机,大约5ms。使用下面的代码中的内容,150毫秒。 (出于某种原因,play.golang显示0)。
为什么慢?我的期望是,对于多个goroutines,它需要相当长的时间。旋转goroutines有什么关系?
package main
import (
"fmt"
"sync"
"time"
)
func main() {
t := time.Now()
_ = fanIn(
generator(4, 5, 6, 7),
generator(1, 2, 6, 3, 7),
generator(12, 15, 33, 40, 10),
generator(18, 13, 20, 40, 15),
generator(100, 200, 64000, 3121, 1237),
generator(4, 5, 6, 7),
generator(1, 2, 6, 3, 7),
generator(12, 15, 33, 40, 10),
generator(18, 13, 20, 40, 15),
generator(100, 200, 64000, 3121, 1237),
generator(4, 5, 6, 7),
generator(1, 2, 6, 3, 7),
generator(12, 15, 33, 40, 10),
generator(18, 13, 20, 40, 15),
generator(100, 200, 64000, 3121, 1237),
generator(4, 5, 6, 7),
generator(1, 2, 6, 3, 7),
generator(12, 15, 33, 40, 10),
generator(18, 13, 20, 40, 15),
generator(100, 200, 64000, 3121, 1237),
generator(4, 5, 6, 7),
generator(1, 2, 6, 3, 7),
generator(12, 15, 33, 40, 10),
generator(18, 13, 20, 40, 15),
generator(100, 200, 64000, 3121, 1237),
generator(4, 5, 6, 7),
generator(1, 2, 6, 3, 7),
generator(12, 15, 33, 40, 10),
generator(18, 13, 20, 40, 15),
generator(100, 200, 64000, 3121, 1237),
generator(4, 5, 6, 7),
generator(1, 2, 6, 3, 7),
generator(12, 15, 33, 40, 10),
generator(18, 13, 20, 40, 15),
generator(100, 200, 64000, 3121, 1237),
)
fmt.Println(time.Now().Sub(t))
}
func generator(nums ...int) <-chan int {
out := make(chan int, 10)
go func() {
defer close(out)
for _, v := range nums {
out <- v
}
}()
return out
}
func fanIn(in ...<-chan int) <-chan int {
var wg sync.WaitGroup
out := make(chan int, 10)
wg.Add(len(in))
go func() {
for _, v := range in {
go func(ch <-chan int) {
defer wg.Done()
for val := range ch {
out <- val
}
}(v)
}
}()
go func() {
wg.Wait()
close(out)
}()
return out
}
答案 0 :(得分:2)
go run
和go build
(编译时)之间略有不同:
对于我17ms
(在2个核心上)和3ms
(在8个核心上)go1.7 amd64
:
go run
和go build
之间的差异:
951.0543ms-934.0535ms = 17.0008ms (在2个核心上)
575.3447ms-572.3914ms = 2.9533ms (在8个核心上)
8个核心与2个核心之间的差异go build
:
934.0535ms-572.3914ms = 361.6621ms
要获得良好的基准统计数据,请使用大量样本
尝试更新到最新的Go版本(1.7
)。
尝试使用此工作示例代码,并将结果与这些输出进行比较:
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func main() {
t := time.Now()
cs := make([]<-chan int, 1000)
for i := 0; i < len(cs); i++ {
cs[i] = generator(rand.Perm(10000)...)
}
ch := fanIn(cs...)
fmt.Println(time.Now().Sub(t))
is := make([]int, 0, len(ch))
for v := range ch {
is = append(is, v)
}
fmt.Println("len=", len(is))
}
func generator(nums ...int) <-chan int {
out := make(chan int, len(nums))
go func() {
defer close(out)
for _, v := range nums {
out <- v
}
}()
return out
}
func fanIn(in ...<-chan int) <-chan int {
var wg sync.WaitGroup
out := make(chan int, 10)
wg.Add(len(in))
go func() {
for _, v := range in {
go func(ch <-chan int) {
defer wg.Done()
for val := range ch {
out <- val
}
}(v)
}
}()
go func() {
wg.Wait()
close(out)
}()
return out
}
输出2个核心(go run
):
951.0543ms
len= 10000000
输出2个核心(go build
):
934.0535ms
len= 10000000
输出8个核心(go run
):
575.3447ms
len= 10000000
输出8个核心(go build
):
572.3914ms
len= 10000000