golang程序1mb能创建多少串联执行的goroutine流水线

60 阅读2分钟

测试代码:

package main

import (
   "fmt"
   "runtime"
)

func main() {
   done := make(chan struct{})
   defer close(done)

   // 创建初始数据源
   numbers := generator(done)

   var stages []chan int
   stages = append(stages, numbers)

   for {
      m := runtime.MemStats{}

      runtime.ReadMemStats(&m)
      //if m.Alloc > uint64(runtime.NumCPU()*1*1024*1024) { // 8核 * 2mb
      if m.Alloc > uint64(1024*1024) { //1mb
         break
      }

      //这里,在创建了10万个goroutine后结束
      //if runtime.NumGoroutine() > 1e5 {
      // break
      //}

      newStage := createStage(done, stages[len(stages)-1], func(x int) int {
         return x + 1
      })

      stages = append(stages, newStage)
      fmt.Printf("已创建 %d 个处理阶段\n", len(stages))
      fmt.Printf("已创建 %d 个goroutine, mem: %d\n", runtime.NumGoroutine(), m.Alloc)

   }

   // 从最后一个阶段读取结果
   for i := 0; i < 10; i++ {
      select {
      case res, ok := <-stages[len(stages)-1]:
         if !ok {
            fmt.Println("cloased:", res)
         } else {
            fmt.Printf("结果: %d\n", res)
         }
      }

   }

}

func generator(done chan struct{}) chan int {
   out := make(chan int)
   go func() {
      defer close(out)
      for i := 0; ; i++ {
         select {
         case out <- i:
         case <-done:
            return
         }
      }
   }()
   return out
}

// 创建一个处理阶段
func createStage(done chan struct{}, in chan int, fn func(int) int) chan int {
   out := make(chan int)
   go func() {
      defer close(out)
      for n := range in {
         select {
         case out <- fn(n):
         case <-done:
            return
         }
      }
   }()
   return out
}

结果输出:

...
已创建 1274 个goroutine, mem: 1047800
已创建 1274 个处理阶段
已创建 1275 个goroutine, mem: 1048392
结果: 1273
结果: 1274
结果: 1275
结果: 1276
结果: 1277
结果: 1278
结果: 1279

分析: 在堆内存1mb情况下,可以创建一千个以上的并发串联运行的goroutine pipeline

当把内存占用扩大到 100mb if m.Alloc > uint64(1024*1024),测试结果显示,可以运行15万以上的pipeline stage:

已创建 157782 个处理阶段
已创建 157783 个goroutine, mem: 104856448
已创建 157783 个处理阶段
已创建 157784 个goroutine, mem: 104857040
结果: 157782
结果: 157783
结果: 157784
结果: 157785
结果: 157786
结果: 157787
结果: 157788
结果: 157789