2014-03-31 43 views
2

我正在使用go從一臺服務器下載文件,並在操作將文件發送到另一臺服務器之後。如何在Go中有效地處理大數據數組(超過10MiB)?

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

目前,我的代碼非常簡單,我使用http.Client和bytes.Buffer。
處理大量文件(100MB到200MB)需要很多時間。 (*緩衝區).grow,
如何創建16MB的大緩衝區?例如,如何創建大緩衝區,例如16MB?

我該怎麼做才能提高我的代碼效率?處理大HTTP請求的一般技巧?

編輯

我會解釋,正是我試圖做的。 我有我試圖複製到另一個couchdb實例的couchdb文檔(附件)。 couchdb文件大小可以從30MB到200MB,複製微小的(2 - 10MB)couchdb文件 - 速度非常快。

但是通過電線發送文件非常慢。 我目前正在嘗試配置文件,並嘗試使用@Evan的回答來查看我的問題。

+0

你能發佈一些代碼?如果我們對如何執行您執行的任務有一些瞭解,那麼看到您的問題就容易得多。現在你的任務非常模糊。 – fuz

+0

我的代碼非常難看,我會寫一些我想要做的事情的描述 – Yosi

回答

5

看看說明了bytes.NewBufferhttp://golang.org/pkg/bytes/#NewBuffer

聽起來像是你可以創建一個16MB字節的片,並用它來初始化緩衝區。

+0

這解決了我的問題,在創建正確的緩衝區大小後,它改進了io.Copy很多 – Yosi

2

你可以考慮你的程序有沒有必要的事實保持內存中的數據,如果它需要做的一切都是爲了複製它。

走到現在的標準庫的強大的功能是明智的接口用途:http.ResponseBody成員是實現io.ReadCloser界面的東西,並且滿足http.Clientbody參數的類型的Post方法。

所以,你可以滾這樣的:

  1. 的文件—執行的請求,你會得到的http.Response實例回,其中有io.readCloser類型的Body成員。

    請注意,此時您並未真正開始從「源」服務器接收正文,因爲要這樣做,您必須排空io.ReadCloser,Body

  2. 啓動另一個(據說POST)請求發送中的數據,並使其在第一步驟中獲得Body構件請求供應時。

    一旦這個請求完成管道您的數據,請致電Close()對該Body成員。

事情是這樣的:

import "net/http" 

func Pipe(from, to string) (err error) { 
    src, err := http.Get(from) 
    if err != nil { 
     return 
    } 
    dst, err := http.Post(to, myPostType, src.Body) 
    if err != nil { 
     return 
    } 
    // Now read and then Close() the dst.Body member. 
} 

在這段代碼,http.Postwill read from src.Body and then Close() it itself

可能加入bytes.Buffer到希望減少系統調用的執行量,但不這樣做,除非普通的方法不起作用。

+0

一個問題是 - 我沒有隻是取得一個機構,併發送出去,我改變json和multiparts。 – Yosi

+0

@Yosi,但你自己說:「我有我想*拷貝*到另一個couchdb實例」的couchdb文件(帶附件),對吧? (重點是我的。)所以下次請儘量更精確,不要浪費別人的時間。 – kostix

1

正如@Evan已經指出的那樣:您可以在創建新緩衝區時選擇初始緩衝區大小。由於緩衝區的分配如此昂貴(這就是爲什麼你的grow調用需要這麼長時間;如果尺寸不適合,它們會重新分配),選擇正確的緩衝區大小是關鍵。選擇正確的緩衝區分配策略取決於很多因素。您可以根據您的應用程序配置文件選擇自己的緩衝區增長方法。

你也應該考慮回收利用的緩衝區,以防止堆碎片:http://blog.cloudflare.com/recycling-memory-buffers-in-go

相關問題