高性能go协程池,代码清晰易懂

gowp

  • 高性能go协程池,代码清晰易懂

安装

go get github.com/linzhepeng/gowp

为什么要用协程池

  • go的协程虽然轻量级,单个goroutine只有2KB,但毫无止境地使用也会占据大量的系统资源,导致调度性能下降、GC 频繁、内存暴涨, 引发一系列问题。
  • 可以测试如下代码,无限开启goroutine很快会造成系统的崩溃
func main() {
    for i:=0;;i++ {
        go func(i int) {
            fmt.Println(i)
            time.Sleep(time.Second)
        }(i)
    }
}
  • gowp限制了最多可启动的goroutine数量,并保持原有性能,在海量并发的场景中性能优势明显

原理

  • 生产者消费者模型:

    1、创建一个容量为n的线程池(gpwp)

    2、生成任务(job)放入任务通道(jobChan)

    3、协程池未满时,每放入一个任务起一个goroutine,否则任务会被已有的n个goroutine抢占执行

使用方法

  • 例子
package main

import (
"fmt"
"github.com/linzhepeng/gowp"
"sync"
)

var wg sync.WaitGroup

func main() {
    //初始化协程池,容量为10
    pool, err := gowp.NewPool(10)
    if err != nil {
        panic(err)
    }
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        //生成1000个任务
        job := &gowp.Job{
            Handler: func(v ...interface{}) {
                wg.Done()
                fmt.Println(v)
            },
            Params: []interface{}{i,i*2},
        }
    // 将任务放入协程池
        _ = pool.Put(job)
    }
    wg.Wait()
    //安全关闭协程池
    pool.ClosePool()
}

benchmark性能测试

测试环境

goos:windows
goarch:amd64
cpu:Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz

测试代码详见gowp_test.go文件

  • 100w次加互斥锁的自增操作
操作模式 操作时间消耗ns/op 内存分配大小B/op 内存分配次数
未使用协程池 11872802400 312577056 1175045
开启容量为20的协程池 5018586500 456 19
  • 100w次原子增量操作
操作模式 操作时间消耗ns/op 内存分配大小B/op 内存分配次数
未使用协程池 1678428700 6950496 16375
开启容量为20的协程池 1613707000 3848 40
Similar Resources
Related tags