我可以无痛使用多少goroutines?例如,维基百科说,在Erlang中,可以创建2000万个进程,而不会降低性能.

Update:我只有investigated in goroutines performance点,结果是这样的:

  • 看起来goroutine的生存期比计算sqrt()要长1000倍(对于我来说大约是45µs),唯一的限制是内存
  • Goroutine成本为4-4.5KB

推荐答案

如果Goroutine被阻止,除了以下情况外不会涉及任何成本:

  • 内存使用
  • 较慢的垃圾收集

成本(就内存和实际开始执行goroutine的平均时间而言)为:

Go 1.6.2 (April 2016)
  32-bit x86 CPU (A10-7850K 4GHz)
    | Number of goroutines: 100000
    | Per goroutine:
    |   Memory: 4536.84 bytes
    |   Time:   1.634248 µs
  64-bit x86 CPU (A10-7850K 4GHz)
    | Number of goroutines: 100000
    | Per goroutine:
    |   Memory: 4707.92 bytes
    |   Time:   1.842097 µs

Go release.r60.3 (December 2011)
  32-bit x86 CPU (1.6 GHz)
    | Number of goroutines: 100000
    | Per goroutine:
    |   Memory: 4243.45 bytes
    |   Time:   5.815950 µs

在安装了4 GB内存的计算机上,这将Goroutines的最大数量限制为略低于100万.


源代码(如果您已经理解上面打印的数字,则无需阅读本文):

package main

import (
    "flag"
    "fmt"
    "os"
    "runtime"
    "time"
)

var n = flag.Int("n", 1e5, "Number of goroutines to create")

var ch = make(chan byte)
var counter = 0

func f() {
    counter++
    <-ch // Block this goroutine
}

func main() {
    flag.Parse()
    if *n <= 0 {
            fmt.Fprintf(os.Stderr, "invalid number of goroutines")
            os.Exit(1)
    }

    // Limit the number of spare OS threads to just 1
    runtime.GOMAXPROCS(1)

    // Make a copy of MemStats
    var m0 runtime.MemStats
    runtime.ReadMemStats(&m0)

    t0 := time.Now().UnixNano()
    for i := 0; i < *n; i++ {
            go f()
    }
    runtime.Gosched()
    t1 := time.Now().UnixNano()
    runtime.GC()

    // Make a copy of MemStats
    var m1 runtime.MemStats
    runtime.ReadMemStats(&m1)

    if counter != *n {
            fmt.Fprintf(os.Stderr, "failed to begin execution of all goroutines")
            os.Exit(1)
    }

    fmt.Printf("Number of goroutines: %d\n", *n)
    fmt.Printf("Per goroutine:\n")
    fmt.Printf("  Memory: %.2f bytes\n", float64(m1.Sys-m0.Sys)/float64(*n))
    fmt.Printf("  Time:   %f µs\n", float64(t1-t0)/float64(*n)/1e3)
}

Go相关问答推荐

Kafka消费者在需要时不会暂停

获取作为类型参数传递给方法接收方中的类型参数的切片的基础类型

埃拉托塞尼筛:加快交叉关闭倍数步骤

go-jwt 令牌验证错误 - 令牌签名无效:密钥类型无效

转到 bufio.Writer、gzip.Writer 并上传到内存中的 AWS S3

使用Dockertest进行Golang SQL单元测试的基本设置

在VSCode中如何使用特定的文件名提供编译命令

GORM中是否可能自动迁移具有循环关系的表?

判断不同 go map 类型中的重复键

Get 请求在 Thunder 客户端/Postman 中返回数据,但在 Golang 代码中给出空白数据

从Go中的随机日期开始以天为单位获取时间

枚举的 Golang 验证器自定义验证规则

CBC Decrypter 解密加密文本,但部分文本被随机字符替换

如何使用带有方法的字符串枚举作为通用参数?

如何模仿联合类型

使用 GO 在侧 tar 文件中提取 tar 文件的最快方法

Golang Getrlimit 返回与 ulimit 不同的值

有没有办法在一个 goroutine 返回后延迟后取消上下文?

正则表达式处理数字签名的多个条目

在 Go 中表达函数的更好方法( struct 方法)