- Go言語は 未定義動作 がほとんどなく、シンプルなGC(ガベージコレクション)のセマンティクス を持っている
- Goでは 手動メモリ管理 が可能で、これはGCと協調して行える
- Arena は同じ寿命を持つメモリを効率的に割り当てるためのデータ構造であり、Goでこれを実装する方法を説明している
- Mark and Sweep アルゴリズムを通じてGCがメモリを管理する方法を説明している
- Arenaを使って メモリ割り当て性能 を改善でき、これはさまざまな最適化によって可能になる
- Write barrierの除去、メモリ再利用、chunk pooling などを通じて性能向上とGC負荷の最小化を試みる
- Reallocの実装、Arenaの再利用と初期化(Reset) などにより、実際の大規模メモリ処理における安全で高速なパターンを提示する
GoにおけるArenaベースの手動メモリ割り当ての概要
- Goは 明確なGCの動作 と ほとんど存在しないUndefined Behavior のおかげで安全な言語である
unsafe パッケージを活用して GCの内部実装に合わせたメモリの直接制御 が可能である
- この記事は、GoでGCと協調可能な Arena構造ベースのメモリ割り当て器 を作る方法を説明している
Arenaの定義と必要性
- Arenaは 同じ寿命を持つオブジェクトを効率的に割り当てる ための構造
- 一般的な
append が 指数的に配列を拡張 する方式であるのに対し、Arenaは 新しいブロックを追加してポインタを返す
- 標準インターフェースは次のとおり:
Alloc(size, align uintptr) unsafe.Pointer
ポインタとGCの動作方式
- GCは メモリを追跡(mark)し回収(sweep)する 方式で動作する
- 正確なGC のために、ポインタ位置情報を知らせる pointer bits というメタデータを使う
- Arenaでポインタを誤って扱うと、GCがポインタを追跡できず Use-After-Freeエラーが発生する可能性 がある
Arenaの設計方法
- Arena構造は次のようなフィールドを持つ:
- すべての割り当ては8バイトアラインメントで処理し、不足した場合は
nextPow2 で新しいchunkを生成する
- chunkは
[]uintptr の代わりに struct { A [N]uintptr; P *Arena } 型で割り当てられ、GCがArenaを追跡できるようにする
Arenaのポインタ安全性を確保する方法
- Arena内部でのみ割り当てられたポインタを使う場合、GCがArena全体を保持する
- ポインタがArenaを参照するよう設定して Arena全体がGCで生存保証される
- Arenaの割り当てメソッドは次を行う:
allocChunk() でArenaポインタをchunkの末尾に保存する
性能ベンチマーク結果
- 基本の
new と比べてArena割り当ては平均 2〜4倍以上の性能向上 を示す
- GC負荷が大きい状況でもArena方式は最大 2倍以上優れた性能 を示す
- Write barrierの除去、
uintptr の活用などの最適化は 小さな割り当てで最大20%の性能向上 をもたらす
Chunk再利用とHeap排除戦略
sync.Pool を活用してchunkを再利用できる
runtime.SetFinalizer() によりArenaが消えるときchunkをpoolへ返す
- 性能は小さな割り当てで非常に良くなるが、大きな割り当てでは
new より遅くなることがある
Arenaの初期化と再利用機能
Reset() メソッドでArenaを初期状態に戻せる
- 危険性は高いが、メモリを再割り当てせずに同じ構造を再利用できる
- 再利用時にもchunkを再利用して性能が大幅に向上する
Realloc機能の実装
- Arenaで
realloc 機能を実装し、直近の割り当てに対して 動的拡張が可能
- 不可能な場合は新しいメモリを割り当てた後にコピー処理を行う
結論と全コードの提供
- GoのGCメカニズムを深く理解し、内部実装に基づいて Arenaベースのメモリ管理器 を完成させている
- 安全性と性能の両方を備えた構造であり、適切に使えば大規模データ構造の処理に非常に有用である
- 全実装コードにはArena構造体と
New, Alloc, Reset, allocChunk, finalize などが含まれる
1件のコメント
Hacker Newsのコメント
この記事は面白い読み物だ
Reference[T]型で置き換える最近Goでパフォーマンスチューニングをしていて、性能を最大化するために非常によく似たアリーナ設計を使うことになった
いくつか簡単な改善点
話題とはそれるが、横にあるミニマップが気に入った
長い記事を読む気になれない人向けの要約
関連: 標準ライブラリに「メモリ領域」を追加する議論
興味深い内容だ
Goはエコシステムを壊さないことを優先している
簡単なメタノート