我在Go中编写了一个程序,它从文件中读取单个字节并检查是否设置了哪些位。这些文件通常很大(大约10 - 100 GB),所以我不想将整个文件读入内存。该程序通常必须检查数百万个单独的字节。
现在,我执行这些读取的方式是使用os.File.ReadAt()
。这最终变得很慢,所以我尝试使用Goroutines加速它。例如:
var wg sync.WaitGroup
threadCount := 8
for i := 0; i < threadCount; i += 1 {
wg.Add(1)
go func(id int) {
defer wg.Done()
index := id
myByte := make([]byte, 1)
for index < numBytesInFile-1 { // Stop when thread would attempt to read byte outside of file
fmt.Println(file.ReadAt(myByte, index))
index += threadCount
}
}(i)
}
wg.Wait()
然而,在这里使用Goroutines根本没有加快程序的速度(事实上,它因为开销而略微变慢)。我原以为光盘上的文件可以同时读取,只要它们以只读模式打开(我在程序中这样做)。我要求的是不可能的,或者是否有某种方式我在Go中对文件进行并发读取?
答案 0 :(得分:2)
你的速度慢是因为I / O而不是CPU。添加更多线程不会加速您的程序。阅读有关Amdahl法律的内容。 https://en.wikipedia.org/wiki/Amdahl%27s_law
如果您不想将完整文件读入内存,可以使用缓冲读取器并读入部分https://golang.org/pkg/bufio/#NewReader,或者您甚至可以考虑使用实验性内存映射文件包:{{3 }}
要了解有关内存映射文件的更多信息,请参阅https://godoc.org/golang.org/x/exp/mmap