2017-08-04 5 views
2

私は20MBより小さいファイルをダウンロードするために以下の機能を使用しています。それは、ディスクに書き込まれる前に別の関数がバイトに対する作業を実行しなければならないので、内容全体をメモリに読み込みます。未使用メモリを解放しますか?

func getURL(url string) ([]byte, error) { 
    resp, err := http.Get(url) 
     if err != nil { 
      return nil, fmt.Errorf("getURL: %s", err) 
    } 
    defer resp.Body.Close() 

    body, err := ioutil.ReadAll(resp.Body) 
    if err != nil { 
      return nil, fmt.Errorf("getURL: %s", err) 
    } 

    return body, nil 
} 

これは問題なく動作しますが、すべてのメモリがシステムで消費されます。

bodyが別の関数によって処理されたメモリを解放することはできますか?そのため、メモリ使用量は現在処理されているバイト数よりも大きくなりませんか?

答えて

6

まず私は、次の質問/回答を読むことをお勧めします。

FreeOSMemory() in production

Golang - Cannot free memory once occupied by bytes.Buffer

あなたはruntime.GC()で使用されていないオブジェクトを解放するために、GCをトリガすることができ、あなたがメモリを解放するためにあなたのGoランタイムを促すことdebug.FreeOSMemory()でOSに戻ってきますが、これらはすべて消火戦です。よく書かれたGoアプリは、これらを呼び出す必要はありません。

実行する必要があるのは、大量のメモリを割り当てる必要がなくなるためです。

どうすればよいですか?いくつかの手段(あなたも、これらのソリューションを組み合わせることができます):それについての詳細大量のメモリを必要とする要求を処理する

  • リミット、:Process Management for the Go Webserver。またIs this an idiomatic worker thread pool in Go?

  • 使用メモリ/バッファプール、それについてより大きな配列/スライスのすべての時間を、割り当てない:How to implement Memory Pooling in Golang

  • が作成/バイトスライスではなくio.Readerの上で動作しない、あなたの処理単位を変更したがって、すべてのコンテンツをメモリに読み込む必要はありません。ただresp.Bodyを渡すことができます。複数のユニットがボディを読み書きする必要があっても、それを一度だけ読み取って処理し、メモリに保持しないことが可能であることに注意してください。手段は、io.Pipe(),io.TeeReader()またはカスタムソリューションです。

関連する問題