为什么goroutines这么慢?

内森·海兰德(Nathan Hyland):

昨天我用几乎相同的代码发布了一个问题,询问如何在可变函数之间同时进行。解决之后,我希望该程序使用一台生成器运行与运行30+几乎相同的时间。似乎并非如此。

我看到的时间是一台发电机,大约5毫秒。与下面的代码是150ms。(由于某种原因,play.golang显示为0)。

为什么慢呢?我的期望是,使用多个goroutine,大约需要很长时间。与旋转goroutine有关吗?

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
}
用户6169399:

go rungo 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核(with go run):

575.3447ms
len= 10000000

输出8核(with go build):

572.3914ms
len= 10000000

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章