我注意到gzip包uses bufio
internally用于读取gzip文件,但不是用于编写它们。我知道缓冲对于I / O性能很重要,那么缓冲gzip编写器的正确方法是什么?
// ignoring error handling for this example
outFile, _ := os.Create("output.gz")
// Alternative 1 - bufio.Writer wraps gzip.Writer
gzipWriter, _ := gzip.NewWriter(outFile)
writer, _ := bufio.NewWriter(gzipWriter)
// Alternative 2 - gzip.Writer wraps bufio.Writer
writer, _ := bufio.NewWriter(outFile)
gzipWriter, _ := gzip.NewWriter(writer)
// Alternative 3 - replace bufio with bytes.Buffer
buf := bytes.NewBuffer()
gzipWriter, _ := gzip.NewWriter(&buf)
另外,在关闭它之前,我是否需要Flush()gzip writer或bufio writer(或两者),或者是否会关闭它自动刷新writer?
UPDATE :我现在明白两个读取和写入都是用gzip缓冲的。所以缓冲gzip.Writer
实际上是双缓冲。 @peterSO认为这是多余的。 @Steven Weinberg认为双缓冲可能会减少系统调用的数量,但建议确定基准测试。
答案 0 :(得分:3)
使用bufio的正确方法是为每次写入调用包装一个高开销的编写器。任何需要系统调用的编写器都是这种情况。在这种情况下,您的" outFile"是一个OS文件,每次写入都是系统调用。
outFile, err := os.Create("output.gz")
defer outFile.Close()
buf := bufio.NewWriter(outFile)
defer buf.Flush()
gz := gzip.NewWriter(buf)
defer gz.Close()
io.Copy(gz, src)
return
在这种情况下,我们使用bufio将写入分组到outFile,以避免不必要的系统调用。订单是src - > gzip - >缓冲区 - >文件。
现在,当我们完成写作时,我们有多个需要关闭的缓冲区。我们需要告诉gzip我们已经完成了它可以刷新缓冲区并将最终信息写入缓冲区。 然后我们需要告诉bufio.Writer我们已经完成了它可以写出它为下一次批量写入保存的内部缓冲区。最后,我们需要告诉操作系统我们已完成该文件。
这种破坏以与创造相反的顺序发生,因此我们可以使用延迟来使其更容易。返回时,延迟以相反的顺序执行,因此我们知道我们正在以正确的顺序刷新,因为销毁的延迟就在函数调用创建的旁边。