如何在Go中有效地处理大型数据阵列(超过10MiB)?

时间:2014-03-31 20:47:17

标签: go buffer

我正在处理从一台服务器上下载文件,并在操作将文件发送到另一台服务器之后。

文件大小可以从1MB到200MB不等。

目前,我的代码非常简单,我使用的是http.Client和bytes.Buffer。
需要花费大量时间来处理大量文件(100MB到200MB),其中有很多文件。

快速分析后,我发现大部分时间都是字节。(*缓冲区).grow,
如何为16MB创建大缓冲区?

为了提高代码效率,我该怎么办?处理大型http请求的一般提示?

修改

我将解释,正是我想要做的。 我有couchdb文件(附件),我试图复制到另一个couchdb实例。 couchdb文件大小可以从30MB到200MB,复制微小的(2-10MB)couchdb文件 - 非常快。

但通过电线发送文件真的很慢。 我目前正在尝试分析,并尝试使用@Evan回答来查看我的问题。

3 个答案:

答案 0 :(得分:5)

查看bytes.NewBufferhttp://golang.org/pkg/bytes/#NewBuffer

的说明

听起来你可以创建一个16MB的字节切片并用它来初始化缓冲区。

答案 1 :(得分:2)

如果您需要做的只是复制,您可以考虑您的程序无需保留内存中的数据这一事实。

现在,Go标准库的强大功能是对接口的合理使用:http.Response的{​​{1}}成员实现了Body接口,并且满足{{1}的类型1}} io.ReadCloser的{​​{1}}方法的参数。

所以你可以像这样滚动:

  1. 执行文档请求 - 您将获得body的实例,其中http.Client成员的类型为Post

    请注意,此时您还没有真正开始从“源”服务器接收正文,因为要这样做,您将不得不耗尽http.Response的{​​{1}}。

  2. 发起另一个(假设Body)请求发送数据,并在发出请求时提供第一步中获得的io.readCloser成员。< / p>

    完成此请求管道您的数据后,请致电io.ReadCloser成员{/ 1}}。

  3. 这样的事情:

    Body

    在此代码中,POST will read from src.Body and then Close() it itself

    可能Body添加到混合中,希望减少执行的系统调用量,但除非普通方法不起作用,否则不要这样做。

答案 2 :(得分:1)

正如@Evan已经指出的那样:您可以在创建新缓冲区时选择初始缓冲区大小。

由于缓冲区的分配非常昂贵(这就是为什么grow调用需要这么长时间;如果大小不再适合,它们会重新分配),选择正确的缓冲区大小是关键。选择正确的缓冲区分配策略取决于很多因素。您可以根据应用程序配置文件选择自己的增长缓冲区方法。

您还应该考虑回收缓冲区以防止堆碎片:http://blog.cloudflare.com/recycling-memory-buffers-in-go