Goはガベージコレクションされた言語です。
http://golang.org/doc/go_faq.html#garbage_collection
ここでは、マークアンドスイープガベージコレクターであると述べていますが、詳細については掘り下げていません。代わりのものが現在準備中です...しかし、Goがリリースされて以来、この段落はあまり更新されていないようです。
それはまだマークアンドスイープですか?それは保守的ですか、それとも正確ですか。それは世代ですか?
Goはガベージコレクションされた言語です。
http://golang.org/doc/go_faq.html#garbage_collection
ここでは、マークアンドスイープガベージコレクターであると述べていますが、詳細については掘り下げていません。代わりのものが現在準備中です...しかし、Goがリリースされて以来、この段落はあまり更新されていないようです。
それはまだマークアンドスイープですか?それは保守的ですか、それとも正確ですか。それは世代ですか?
回答:
Go 1.4以降のガベージコレクターの計画:
Go 1.1に加えてGo 1.3ガベージコレクターの更新:
Go 1.1ガベージコレクター:
Go 1.0ガベージコレクター:
GCを別のGCに交換することは、議論の余地があります。たとえば、次のようになります。
(Go 1.8-2017年第1四半期については、以下を参照してください)
次のGo 1.5 コンカレントガベージコレクターでは、gcが「ペース」を上げることができる必要があります。このペーパーで
提示されている提案は、Go 1.5に役立つかもしれませんが、GoのGCを理解するのにも役立ちます。
1.5 以前の状態を見ることができます(Stop The World:STW)
Go 1.5より前のバージョンでは、Goはパラレルストップザワールド(STW)コレクターを使用していました。
STWコレクションには多くの不利な点がありますが、少なくとも予測可能で制御可能なヒープ拡張動作があります。
(GopherCon 2015プレゼンテーション「Go GC:Go 1.5でのレイテンシー問題の解決」の写真)
STWコレクターの唯一の調整ノブは、コレクション間の相対的なヒープ成長である「GOGC」でした。デフォルト設定の100%では、前回のコレクションの時点で、ヒープサイズがライブヒープサイズの2倍になるたびにガベージコレクションがトリガーされました。
STWコレクターのGCタイミング。
Go 1.5では、並行コレクターが導入されています。
これにはSTWコレクションよりも多くの利点がありますが、ガベージコレクターの実行中にアプリケーションがメモリを割り当てることができるため、ヒープの増加を制御することが難しくなります。
(GopherCon 2015プレゼンテーション「Go GC:Go 1.5でのレイテンシー問題の解決」の写真)
同じヒープ増加の制限を実現するには、ランタイムがガベージコレクションをより早く開始する必要がありますが、どれだけ早く多くの変数に依存するか、その多くは予測できません。
- コレクターの開始が早すぎると、アプリケーションがガベージコレクションを実行しすぎて、CPUリソースが浪費されます。
- コレクターの開始が遅すぎると、アプリケーションが望ましい最大ヒープ増加を超えてしまいます。
同時実行性を犠牲にすることなく適切なバランスを実現するには、ガベージコレクターを慎重に調整する必要があります。
GCペーシングは、ヒープの増加とガベージコレクターによって使用されるCPUの2つの側面に沿って最適化することを目的としています。
GCペーシングの設計は、4つのコンポーネントで構成されています。
- GCサイクルが必要とするスキャン作業の量の見積もり
- ヒープ割り当てがヒープ目標に到達するまでに、ミューテーターがスキャン作業の推定量を実行するためのメカニズム
- ミューテーターがCPUバジェットを十分に活用していない場合のバックグラウンドスキャンのスケジューラー、および
- GCトリガーの比例コントローラー。
デザインは、CPU時間とヒープ時間という2つの異なる時間の見方のバランスをとっています。
- CPU時間は標準のウォールクロック時間に似ていますが、時間の経過が
GOMAXPROCS
速くなります。
つまり、GOMAXPROCS
8の場合、1秒ごとに8 CPU秒が経過し、GCは1秒ごとに2秒のCPU時間を取得します。
CPUスケジューラは、CPU時間を管理します。- ヒープ時間の経過はバイト単位で測定され、ミューテーターが割り当てるにつれて前進します。
ヒープ時間とウォール時間の関係は割り当て率に依存し、常に変化する可能性があります。
Mutatorはヒープ時間の経過の管理を支援し、ヒープが目標サイズに達するまでに推定スキャン作業が完了することを保証します。
最後に、トリガーコントローラーは、これら2つの時間ビューを結び付けるフィードバックループを作成し、ヒープ時間とCPU時間の両方の目標を最適化します。
これはGCの実装です:
https://github.com/golang/go/blob/master/src/runtime/mgc.go
ソースのドキュメントから:
GCはミューテータースレッドと同時に実行され、タイプが正確(別名:正確)であり、複数のGCスレッドを並行して実行できます。これは、書き込みバリアを使用するマークとスイープの同時実行です。それは非世代的でコンパクトではありません。割り当ては、P割り当て領域ごとに分離されたサイズを使用して行われ、一般的なケースでロックを排除しながら断片化を最小限に抑えます。
Go 1.8 GCは、「STWスタックの再スキャンを排除する」という提案により、再び進化する可能性があります
Go 1.7の時点で、制限のない、潜在的に重要なStop-the-World(STW)時間の残りのソースの1つはスタックの再スキャンです。
Yuasaスタイルの削除書き込みバリア[Yuasa '90]とDijkstraスタイルの挿入書き込みバリア[Dijkstra '78]を組み合わせたハイブリッド書き込みバリアに切り替えることで、スタックの再スキャンの必要性を排除することを提案します。
予備実験では、これにより、最悪の場合のSTW時間を50µs未満に短縮できることが示されています。このアプローチにより、STWマークの終端を完全に排除することが実際的になる可能性があります。