ガベージ コレクターを回避/最小化したい場合があるため、その方法を確認したいと思います。
次が正しいと思います。
- 関数の先頭で変数を宣言します。
- スライスの代わりに配列を使用するには。
もう?
ガベージ コレクターを回避/最小化したい場合があるため、その方法を確認したいと思います。
次が正しいと思います。
もう?
Go でガベージ コレクションを最小限に抑えるには、ヒープ割り当てを最小限に抑える必要があります。ヒープ割り当てを最小限に抑えるには、いつ割り当てが行われるかを理解する必要があります。
次のことは常に割り当てを引き起こします (少なくとも Go 1 の gc コンパイラでは):
new
組み込み関数の使用make
(まれなまれなケースを除く)&
演算子を含む構造体である場合の複合リテラルstring
、[]byte
、および間の変換[]rune
m[string(b)]
。ここm
で、 はマップで、b
は[]byte
string
defer
ステートメントgo
ステートメント詳細に応じて、次のことが原因で割り当てが発生する可能性があります。
a.b()
のアドレスを取得する場合があります。a
a
b
append
組み込み関数の使用リストは完全であることを意図しており、私はそれにかなりの自信を持っていますが、喜んで追加や修正を検討します。
割り当てがどこで行われているかわからない場合は、他の人が提案したようにいつでもプロファイリングするか、コンパイラによって生成されたアセンブリを確認できます。
ごみを避けることは比較的簡単です。割り当てが行われている場所を理解し、割り当てを回避できるかどうかを確認する必要があります。
まず、関数の先頭で変数を宣言しても役に立ちません。コンパイラは違いを知りません。しかし、人間はその違いを知り、それが彼らを悩ませます。
スライスの代わりに配列を使用しても機能しますが、これは配列が (逆参照されない限り) スタックに置かれるためです。配列には、関数間で値渡し (コピー) されるという事実など、他の問題があります。関数が戻るときに解放されるため、スタック上のものはすべて「ガベージではありません」。関数をエスケープする可能性のあるポインタまたはスライスは、ガベージ コレクタがある時点で処理する必要があるヒープに置かれます。
あなたができる最善のことは、割り当てを避けることです。不要な大量のデータの処理が完了したら、それらを再利用します。これは、Go ブログのプロファイリング チュートリアルで使用されている方法です。読むことをお勧めします。
プロファイリング チュートリアルの例以外の別の例:[]int
という名前の型のスライスがあるとしますxs
。条件に達するまで継続的に追加し、[]int
それをリセットして最初からやり直すことができます。実行するxs = nil
と、スライスの基になる配列が収集されるガベージとして宣言されます。Append は、次に使用するときに xs を再割り当てします。代わりに を実行xs = xs[:0]
すると、まだリセットされますが、古い配列は保持されます。
ほとんどの場合、ガベージの作成を回避しようとするのは時期尚早の最適化です。ほとんどのコードでは問題ありません。しかし、実行されるたびに多くの割り当てを行う関数が何度も呼び出されることがあります。または、再利用する代わりに再割り当てするループ。船外に出る前に、ボトルネックが見えるまで待ちます。