Go Academy · レッスン

メモリ割り当ての削減:sync.PoolとArena

オブジェクトの再利用、sync.Pool、GC負荷の削減

レッスン 4/413 ステップ

「メモリ割り当ての削減:sync.PoolとArena」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

割り当てを減らす理由

ヒープへの各割り当ては、最終的にGCの作業を発生させます。割り当てを減らすとGCの頻度と停止時間が低下し、高トラフィックのサービスでスループットとテールレイテンシが向上します。

まずプロファイリング

最適化する前に、必ずプロファイリングを行ってください。go test -benchmemと-alloc_spaceヒーププロファイルを使用して、実際に割り当てが集中している経路を特定します。直感だけを頼りに最適化しないでください。

sync.Pool

sync.Poolは、再利用可能なオブジェクトのスレッドセーフなプールです。頻繁に割り当てと破棄が行われる短命なオブジェクト(バイトバッファ、作業用マップ、リクエストコンテキスト)に使用します。

var pool = sync.Pool{
    New: func() any { return &bytes.Buffer{} },
}
func process(data []byte) {
    buf := pool.Get().(*bytes.Buffer)
    buf.Reset()
    buf.Write(data)
    // use buf...
    pool.Put(buf)
}

Poolはキャッシュではありません

GCはいつでもプール内のアイテムをクリアできます。Poolは割り当ての負荷を減らすためのものであり、長期間保持するデータのキャッシュには使用しません。取得したオブジェクトは、どのgoroutineのものか分かりません。

再利用する前に必ずReset

使用する前に、プールされたオブジェクトをクリアしてください。以前の呼び出し元のデータが残っている可能性があります。bytes.Bufferの場合はReset()を呼び出し、スライスの場合は[:0]に再スライスします。

スライスの事前割り当て

最終的な長さが分かっている場合は、make([]T, 0, n)でスライスを事前に割り当てます。これにより、スライスの拡張に伴う繰り返しの倍増とコピーを避けられます。

results := make([]Result, 0, len(input)) // no reallocations

String builder

ループ内で中間的な文字列の割り当てが発生するのを避けるため、文字列の連結ではなくstrings.Builderを使用します。

var sb strings.Builder
for _, s := range parts { sb.WriteString(s) }
result := sb.String()

bytes.Bufferのプール

bytes.Bufferは、プールで管理されることが特に多い型の1つです。JSONエンコード、HTTPレスポンスの構築、テンプレートのレンダリングで繰り返し発生する割り当てを避けるためにプールします。

Goのアリーナ(実験的)

Go 1.20以降には、実験的なアリーナパッケージ(golang.org/x/exp/arena)が含まれています。アリーナでは多数のオブジェクトを1つの大きなブロックに割り当て、そのブロックを一度に解放するため、オブジェクトごとのGCを回避できます。

値型

小さな構造体を値渡しすると、ヒープ割り当てを完全に避けられます。性能が重要なコードでは、小さな構造体へのポインタを使うパターンを避けてください。値を返すほうがコストが低い場合がよくあります。

影響の測定

前後で-benchmemを付けてベンチマークを実行し、benchstatで比較します。ns/opだけでなく、処理の主要経路におけるallocs/opの削減を目指してください。

BenchmarkProcess-8  1000000  125 ns/op  64 B/op  2 allocs/op
// After pooling:
BenchmarkProcess-8  1000000   48 ns/op   0 B/op  0 allocs/op

クイックチェック

割り当てを減らす用途でsync.Poolを安全に使えるのは、どのような特徴があるためですか?

まとめ:割り当ての削減

重要なポイント:

  • まずプロファイリングを行い、最適化前に-benchmemとヒープの-alloc_spaceを確認します
  • 頻繁に割り当てと破棄が行われるオブジェクトにはsync.Poolを使用し、再利用前には必ずResetします
  • make([]T, 0, n)でスライスを事前に割り当て、連結にはstrings.Builderを使用します
  • 値型はヒープ割り当てを避けます。改善をベンチマークで検証してください
無料で開始

AI チューターと学ぶ Go — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
51
レッスン
203

よくある質問

「メモリ割り当ての削減:sync.PoolとArena」レッスンは無料ですか?

はい。「メモリ割り当ての削減:sync.PoolとArena」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「メモリ割り当ての削減:sync.PoolとArena」で何を学びますか?

オブジェクトの再利用、sync.Pool、GC負荷の削減 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「メモリ割り当ての削減:sync.PoolとArena」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. スタックとヒープ、エスケープ解析
  2. GoのメモリモデルとHappens-Before
  3. ガベージコレクターの内部
  4. メモリ割り当ての削減:sync.PoolとArena
← Go Academyに戻る