我正在尝试为大量文件构建一个解析器,而且我找不到关于我称之为“嵌套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
我的问题主要针对性能问题。
感谢您达成该判决!
答案 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延迟。