我们应该做嵌套的goroutines吗?

时间:2014-02-14 20:50:32

标签: concurrency go goroutine

我正在尝试为大量文件构建一个解析器,而且我找不到关于我称之为“嵌套goroutines”的资源(也许这不是正确的名字?)。

鉴于有很多文件,每个文件都有很多行。我应该这样做:

for file in folder:
    go do1

def do1:
    for line in file:
        go do2

def do2:
    do_something

或者我应该只使用“一级”goroutines,并执行以下操作:

for file in folder:
    for line in file:
        go do_something

我的问题主要针对性能问题。

感谢您达成该判决!

2 个答案:

答案 0 :(得分:7)

如果你使用你指定的架构,你很有可能耗尽CPU / Mem /等等,因为你将创建任意数量的工作者。我建议,改为使用允许您通过频道限制的架构。例如:

在您的主要流程中,将文件输入频道:

for _, file := range folder {
  fileChan <- file
}

然后在另一个goroutine中将文件分成几行并将它们输入到一个频道中:

for {
  select{
  case file := <-fileChan
    for _, line := range file {
      lineChan <- line
    }
  }
}

然后在第3个goroutine中弹出线条并按照你的意愿行事:

for {
  select{
  case line := <-lineChan:
    // process the line
  }
}

这样做的主要优点是你可以创建尽可能多的例程,因为你的系统可以处理并传递它们所有相同的通道,无论哪个常规到达通道都会处理它,所以你是能够限制你正在使用的资源量。

以下是一个工作示例:http://play.golang.org/p/-Qjd0sTtyP

答案 1 :(得分:1)

答案取决于每条线上操作的处理器密集程度。

如果线路操作是短暂的,绝对不要为每一行产生一个goroutine。

如果价格昂贵(约5秒或更长),请谨慎行事。你可能会耗尽内存。从Go 1.4开始,产生一个goroutine会分配一个2048字节的堆栈。对于200万行,您可以单独为goroutine堆栈分配超过2GB的RAM。考虑是否值得分配这个记忆。

简而言之,您可能会通过以下设置获得最佳效果:

for file in folder:
    go process_file(file)

如果文件数量超过CPU数量,您可能具有足够的并发性来掩盖从磁盘读取文件所涉及的磁盘I / O延迟。