Go/メモリアロケータ
表示
< Go
Goのメモリ管理システムは元々tcmallocに基づいていましたが、現在では大きく進化しています。以下に主要なポイントを解説します。
主要なデータ構造
[編集]- fixalloc: 固定サイズのオフヒープオブジェクトを管理するフリーリストアロケータ
- mheap: mallocヒープで、ページ(8192バイト)単位で管理
- mspan: mheapで管理される使用中のページ群
- mcentral: 同じサイズクラスのmspanを集めたもの
- mcache: P(プロセッサ)ごとのmspanキャッシュ
- mstats: 割り当て統計情報
小オブジェクトの割り当てプロセス
[編集]- mcacheでの割り当て:
- サイズを小さいサイズクラスに切り上げ
- 対応するmspanのフリービットマップをスキャン
- ロック不要で高速に処理
- mcentralからの取得:
- mspanに空きがない場合、該当サイズクラスのmspanをmcentralから取得
- スパン全体を取得するためロックコストを償却
- mheapからのページ取得:
- mcentralのリストが空の場合、mheapからページ群を取得
- OSからのメモリ取得:
- mheapが空または十分な連続ページがない場合、OSから新しいページ群(最低1MB)を割り当て
メモリ解放プロセス
[編集]- 割り当て応答としてスイープ中のmspanはmcacheに返却
- 割り当て済みオブジェクトがあるmspanはmcentralのフリーリストに配置
- 全てのオブジェクトが解放されたmspanはmheapに返却
大オブジェクトの処理
[編集]- mcacheとmcentralをバイパスし、直接mheapを使用
ゼロ初期化の最適化
[編集]- `mspan.needzero`がfalseの場合、解放済みスロットは既にゼロ初期化済み
- trueの場合は割り当て時にゼロ初期化
- 遅延ゼロ初期化の利点:
- スタックフレーム割り当てでゼロ初期化を完全に回避可能
- 時間的局所性が向上(プログラムがすぐに書き込む可能性が高い)
- 再利用されないページはゼロ初期化しない
仮想メモリレイアウト
[編集]- ヒープはアリーナ(64ビットで64MB、32ビットで4MB)の集合で構成
- 各アリーナには対応するheapArenaオブジェクトがあり、メタデータを保持
- アリーナマップ(mheap_.arenas)はアドレス空間全体をカバー
- 連続したアリーナを維持するよう努め、大きなスパン(大きなオブジェクト)がアリーナを跨げるようにする
このアロケータ設計は、小オブジェクトの高速割り当て、大オブジェクトの効率的な処理、メモリ使用量の最適化を実現しています。特に、スレッドローカルなmcacheを使用することで、並行処理環境でのロック競合を最小限に抑えています。