Goのメモリ管理:アロケータ、ガベージコレクション

Go言語

開発をしていてあまりに気にしないが重要なアロケータや、ガベージコレクションについて解説をしていきます。

アロケータ

Goのアロケータはオブジェクトを操作するのに必要なメモリブロックを動的に割り当てられ、ロックや断片化を回避してOSヘの遅いシステムコールを軽減できる。
GoのアロケータはTCMallocを厳密にモデル化したアロケータである。

TCMalloc

TCMallocは、マルチスレッド時代に合わせて設計されているmalloc(動的メモリを確保する)実装で、メモリを複数のレベルに分割してロックの粒度を下げる。
メモリのロックはメモリがスワップエリアにページングされるのを防ぐ。ページングは予期しないプログラムの実行遅延をもたらす原因になる。

メモリ管理は以下の2つに分かれている

  • スレッドメモリ
  • ページヒープ

スレッドメモリ

各メモリーページは、複数の固定割り当て可能サイズのクラスの空きリストに分割され、断片化の削減に役立ちます。各スレッドにはロックのない小さなオブジェクトのキャッシュがあり、並列プログラムで小さなオブジェクト(32KB以下)を割りてるのが非常に効率的になる。

ページヒープ

GCMallocによって管理されるヒープはページコレクションで構成される。割り当てられたオブジェクトが32KBより大きい場合、割り当てにはページヒープが使用される。
小さなオブジェクトを割り当てるためのメモリが足りてない場合は、ページヒープにメモリを割り当てる。メモリが足りてな場合、ページヒープはOSにさらにメモリを要求する。
このように割り当てることで、ユーザー空間のメモリプール*1を維持するため、メモリの割り当てと解放の効率が良くなる。

*1:メモリプールは、コンピュータプログラムの実行時に素早く動的に必要なメモリ領域を確保するために、プログラムの起動時などにメインメモリの空き領域からある程度大きな領域を一括して確保したもの。

ガベージコレクション

Goのアロケータを使ってメモリブロックのメモリを効率的に確保できますが、メモリブロックを削除できなければ無制限にメモリを確保ができないです。そのためにガーベージコレクション(GC)というプログラムのヒープから未使用のオブジェクトを取り除く処理をするバックグランドルーチンがある。
GCの回収のタイミングが大事で、GCの実行頻度が低いとゴミ(未使用オブジェクト)がたまって、メモリがいっぱいになってしまう。逆に頻度が高いと、機能を実行する代わりにプログラム時間とCPUのほとんどをGCの実行に使ってしまう可能性がある。
GCの実行間隔は時間に基づくものではなく、GOGC、GOMEMLIMITの2つの変数によって決まる。
GOGCはデフォルト100で設定されていて、ヒープサイズが最後のGCサイクルの終了時に持っているサイズの100%に拡張されたときに、次のGCの回収が行われる。
GOMEMLIMITはGo1.19で導入され、デフォルトでは無効になっている。設定されたメモリ制限に近いまたは超えている場合、頻繁にGCを実行する。

理解度チェック

今回の内容がわかっているかの問題を作成しています。
問題をクリックすると、答えが表示されますので、今回の内容を理解できたかチェックをしてみてください。

Q.Goのアロケーターの役割とは?
A.オブジェクトを操作するのに必要なメモリブロックを動的に割り当てられ、ロックや断片化を回避してOSヘの遅いシステムコールを軽減できる。

Q.Goのガーベージコレクションが実行されるタイミングを決める変数は?
A.GOGC、GOMEMLIMIT

まとめ

今回はメモリ管理に必要なアロケータとガベージコレクションについて解説をしてきました。
仮想記憶というメモリ管理の基本や、Goについての記事が他にもありますので、こちらも読んでもらえたらと思います。

【おすすめ記事のリンク】

参考

A visual guide to Go Memory Allocator from scratch (Golang)
A visual guide of how Go memory allocator works for everyone.

mlock - システムコールの説明 - Linux コマンド集 一覧表
mlock - システムコールの説明。mlock - メモリのロックとロック解除を行う。

効率的なGo
本書は、Goアプリケーションの効率やスケーリングに関する疑問に対して、実用的な答えを与えてくれる書籍です。レイテンシー、CPU、メモリ資源についての知識、またOSやGoがそれらを抽象化している方法について、またソフトウェアの効率に関わるデー...

コメント

タイトルとURLをコピーしました