ガベージコレクション

提供: MonoBook
2021年10月28日 (木) 02:35時点におけるAdministrator (トーク | 投稿記録)による版
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

ガベージコレクション英語:garbage collection、略称:GC)とは、プログラムで動的に確保したメモリ領域のうち、不要になったものを自動的に解放する機構のことである。

概要[編集 | ソースを編集]

ガベージコレクションを日本語に直訳すると「ゴミ収集」である。大雑把に言えばクソみたいなプログラマーメモリを食い散らかしても、賢いコンピューターが勝手に掃除してくれるというもので、実世界でいうところの自動掃除ロボットルンバみたいなものである。

人間は必ずミスをするものであり、たとえ天才プログラマーであってもプログラムが巨大化するにつれ、メモリリークは必ずと言っていいほど発生する。ガベージコレクションはそのような問題を回避するために考えられたもので、ライブラリ、またはランタイムによって使い終わったメモリを自動的に解放する機構を提供する。

C言語などで使われているライブラリ実装のものは、ソースコードが若干煩雑になる傾向がある。なお、C++Boostや、Boostから取り込まれたC++11(旧C++0x)のスマートポインターはこの点が大幅に改善している。

.NETJavaPHPで使われているランタイム実装のものは、プログラムプロジェクト)が小規模なうちはプログラマーは特に何も考える必要がなく、非常に手軽である。

問題点[編集 | ソースを編集]

タイミングが不確定[編集 | ソースを編集]

ガベージコレクションは非常に便利ではあるが、全自動であるがために痒いところに手が届かないことも多い。たとえば画像処理などのように大量のメモリを必要とするプログラムでは部分的に手動で解放できた方が都合の良い場合もある。

もっと具体的な例を挙げれば、Mac OS XFaceTimeカメラを使ったビデオキャプチャでは、1フレームごとにメモリが確保されるが、Objective-C標準のガベージコレクションに頼ると、メモリ確保を繰り返すスピードが速すぎて解放が追いつかなくなり、最終的にメモリ不足となりプログラムクラッシュする。実はこれ、アップルが公式配布しているサンプルプログラムに含まれる問題点で、被写体の動きが遅いと問題ないが、激しく動き続けるとダメになる。[1]

このため、.NETのように基本は全自動解放だが、手動解放(CG強制呼び出し)の手段も残している半自動なものもある。

ストップ・ザ・ワールド[編集 | ソースを編集]

また、ガベージコレクションの処理が重すぎる「ストップ・ザ・ワールド」なる現象も問題となることが多い。ゴミ収集が回ってきた(動いた)瞬間にコンピューターが超高負荷になり、まるでフリーズしたかのような状態になり、処理が終わると何事もなかったかのように動き出す、というものである。

このストップ・ザ・ワールドなる現象は、24時間365日止まってはいけないサーバーなどで突如数十秒間の一時停止が発生し問題になることが多い。巨大なサーバーほどアホみたいに大量のメインメモリを搭載している傾向があり、それに比例してガベージコレクションによる回収にも時間がかかる。

最近ではストップ・ザ・ワールドを回避する新しい方式も登場してきている。

主なガベージコレクション方式[編集 | ソースを編集]

ガベージコレクションと一言でいっても様々な方式や実装が発表されている。どれも一長一短はあるが、1950年代のLISPに実装された最初のガベージコレクションから日進月歩で良くなりつつある。

参照カウンター
メモリを使うとカウンタを+1、使い終わるとカウンタ-1、カウンタが0なら解放というシンプルな方式。循環参照によって破綻しメモリリークが発生する。
マーク・アンド・スイープ
間違いなく使われているオブジェクトランダムでひとつ選び、そこから別のオブジェクトへと参照を次々に辿ることを繰り返し、到達出来なかったオブジェクトは使ってないと見なし破棄する方法。
コピーGC
通常使用するメモリ領域と同じ容量のメモリ領域をもうひとつ用意し、ガベージコレクションの際に有効なオブジェクトのみをもう一方のメモリ領域にコピーする方法。メモリ領域をデータ保持に必要な容量の2倍消費すること、コピーの際にオブジェクトアドレスが変更されることなどの欠点があるが、ガベージコレクションとコンパクションが同時に行える利点がある。
世代別ガベージコレクション
マークアンドスイープコピーGCのハイブリッド方式。メモリが使われ始めてからの経過時間や、確保されたメモリサイズなどでグループを分け(このグループを「世代」という)、それぞれに異なるGC方式を適用するというもの。

主なガベージコレクション実装[編集 | ソースを編集]


その他[編集 | ソースを編集]

MonoMacではメインスレッド以外からSystem.GC.Collect()を呼び出しても効果がない。 必ずメインスレッドで実行する必要がある。

関連項目[編集 | ソースを編集]

参考文献[編集 | ソースを編集]