我认为协程池运行任务会比直接go协程更慢,在go1.13版本甚至老版本中才会有消耗时间上的优势

遇到个问题,使用go关键字直接开协程快还是使用go协程池快。

我自己在千万任务(模拟任务执行都是10微秒)测了下,发现协程池要慢很多。

请问大家有没有测过呢?协程池会在时间上效率会降低这个结论对吗

实验一:使用go1.13版本,对比无协程池和Ants协程池(n=1千万)

```go

func TestNoPool(t *testing.T) { //花费时间 150.829s
    var wg sync.WaitGroup
    wg.Add(n)
    for i := 0; i < n; i++ {
        go func() {
            time.Sleep(10 * time.Microsecond)
            wg.Done()
        }()
    }
    wg.Wait()
}

func TestAntsPool(t *testing.T) { //花费时间 6.899s
    defer Release()
    var wg sync.WaitGroup
    wg.Add(n)
    for i := 0; i < n; i++ {
        _ = Submit(func() {
            time.Sleep(10 * time.Microsecond)
            wg.Done()
        })
    }
    wg.Wait()
}

**实验二**:改变wg.Add()的位置:
func TestNoPool(t *testing.T) { //花费时间 3.387s
    var wg sync.WaitGroup
    for i := 0; i < n; i++ {
        wg.Add(1)
        go func() {
            time.Sleep(10 * time.Microsecond)
            wg.Done()
        }()
    }
    wg.Wait()
}

func TestAntsPool(t *testing.T) { //花费时间 6.159s
    defer Release()
    var wg sync.WaitGroup
    for i := 0; i < n; i++ {
        wg.Add(1)
        _ = Submit(func() {
            time.Sleep(10 * time.Microsecond)
            wg.Done()
        })
    }
    wg.Wait()
}

```

  • 之前,我猜测,协程池可能在go的旧版本上比如go1.13比直接go一个协程会有执行时间上的优势。而新版本的go,如1.18。走协程池远不如直接go一个协程快。所以我就做了如上面实验一,并查询文档自go1.14起goroutine支持异步抢占式调度,认为自己的猜测是对的。

  • 但是,昨天改变了下wg.Add()的位置,测的数据完全不一样,这就让我很困惑。因为之前的结果很可能是wg.Add()放在for外导致耗费了大量时间,而不是直接go协程所造成的消耗。

  • 当然,我在go1.18上做如上的两个实验,wg.Add()放哪里时间花费都一样,结果都是直接开协程更快。协程池在时间上完全没优势。

讨论数量: 11

协程池是主要是控制协程数量,防止任务太多创建太多协程导致资源不足。

1周前 评论

嗯嗯,所以请问时间上会不会有提升?(go1.13版本)wg.Add()的位置不一样,为什么差这么多时间

1周前 评论
滚球兽进化 1周前
fichtner (作者) (楼主) 1周前

我这边测的结果都很接近。你的那个慢很多应该是池子设置的比较小导致的吧,这是我看你代码唯一产生阻塞导致运行变慢的地方

package main

import (
    "sync"
    "testing"
    "time"

    "github.com/panjf2000/ants"
)

var n = 10000000

func TestPower(t *testing.T) {
    var wg sync.WaitGroup
    for i := 0; i < n; i++ {
        wg.Add(1)
        go func() {
            time.Sleep(10 * time.Microsecond)
            wg.Done()
        }()
    }
    wg.Wait()
}

func TestPower2(t *testing.T) {
    var wg sync.WaitGroup
    wg.Add(n)
    for i := 0; i < n; i++ {
        go func() {
            time.Sleep(10 * time.Microsecond)
            wg.Done()
        }()
    }
    wg.Wait()
}

func TestPower3(t *testing.T) {
    var wg sync.WaitGroup
    wg.Add(n)
    for i := 0; i < n; i++ {
        _ = ants.Submit(func() {
            time.Sleep(10 * time.Microsecond)
            wg.Done()
        })
    }
    wg.Wait()
}

func TestPower4(t *testing.T) {
    var wg sync.WaitGroup

    for i := 0; i < n; i++ {
        wg.Add(1)
        _ = ants.Submit(func() {
            time.Sleep(10 * time.Microsecond)
            wg.Done()
        })
    }
    wg.Wait()
}
1周前 评论
fichtner (楼主) 1周前
滚球兽进化 (作者) 1周前

你这个直接睡眠没啥意义啊,睡眠会阻塞线程,然后直接迁移到新的线程上面运行

1周前 评论
fichtner (楼主) 1周前
__golang__ (作者) 3天前

还有个问题 go 多开出来线程 好像是不会销毁 只会睡眠 是不是这样

2天前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!