缓冲版Go io.Pipe

时间:2017-07-13 19:14:41

标签: go

在我自己推出之前,是否有io.Pipe的缓存版本(在标准库或第三方库中)?

上下文:我尝试使用this solution解析用bzip2压缩的JSON数据,以便解压缩和解析并行发生,但发现加速非常小。解析未压缩数据每百万条记录大约需要22秒。解压缩那么多数据需要大约相同的时间。正如预期的那样,在单个线程上执行它们需要大约44秒。使用上述解决方案需要约41秒。

io.Pipe的文档说:

  

管道上的读取和写入是一对一匹配,除非   消耗单个Write需要多次读取。也就是说,每一个   写入PipeWriter块,直到它满足一个或多个   从完全使用写入数据的PipeReader读取。该   数据直接从Write复制到相应的Read(或   读取);没有内部缓冲。

我怀疑这可能是一个问题,这取决于bzip2解压缩程序写入数据的方式以及JSON解析器读取数据的方式,因此我想尝试缓冲版本。

4 个答案:

答案 0 :(得分:4)

这是bufio包的用途。它允许您将任何io.Reader转换为使用NewReader或任何io.Writer的缓冲读者,并将其转换为NewWriter的缓冲作者。

(缓冲IO是否真的会帮助解决您的具体问题,我不知道......)

答案 1 :(得分:1)

您可以使用https://github.com/djherbis/nio中的缓冲管道,如下所示:

import (
    "github.com/djherbis/buffer"
    "github.com/djherbis/nio"
)

...

b := buffer.New(32*1024)
pr, pw := nio.Pipe(b)

...

答案 2 :(得分:0)

如果要进行异步操作,即在单独的goroutine上进行读取,则还可以使用几年前使用的readahead

https://github.com/klauspost/readahead

示例:

ra := readahead.NewReader(input)
defer r.Close()
pr, pw := nio.Pipe(ra)

使用默认设置时,它将在管道准备就绪时最多读取四个将发送的1MB缓冲区。

答案 3 :(得分:0)

我的https://github.com/acomagu/bufpipe界面简单并且运行良好。

r, w := bufpipe.New(nil)
io.WriteString(w, "abc") // No blocking.
io.WriteString(w, "def") // No blocking, too.
w.Close()
io.Copy(os.Stdout, r)
// Output: abcdef

Playground