5分で分かるガベージコレクションの仕組み

みなさん、“ガベージコレクション”をご存知ですか?「聞いたことはあるけど、それがどんなものかよく理解していない」という方は多いのではないでしょうか。ここでは、そんなガベージコレクションの正体を分かりやすく解説していきます。

ガベージコレクションって何?

20160224_1

今回は、ガベージコレクションを”掃除のおばちゃん”に例えてご説明します。実は、ガベージコレクションとは、プログラムにおける掃除のおばちゃんのような存在なのです。

「意味がピンとこない。いったいどういうことなの?」と思ってしまう方が多そうですね。では、なぜガベージコレクションが掃除のおばちゃんに例えられるかを、「プログラム実行時にメモリ上ではどのようなことが起こっているか」の解説を通して、お話していきましょう。

20160224_2

プログラムが動作する際には、

1. プログラム処理に必要な情報をメモリ上に読みこむ
2. 読みこんだ情報をもとに、処理を実行する

という2つのステップを踏みます。
読みこまれた情報は、処理をしている間はもちろん必要なものですが、その処理が終わってしまうと途端に不要になってしまいます。つまり、”メモリに残されたゴミ”のような状態になってしまうのです。

20160224_3

そこで登場するのが、掃除のおばちゃんこと“”ガベージコレクション”です。これは、「プログラムが確保したメモリ領域のうち、不要になった箇所だけを解放してくれる」機能です。

このように、必要に応じてメモリ領域を割り当てたり、開放したりすることを“メモリ管理”と言いますが、ガベージコレクションは、プログラマがメモリ管理のためのコードをわざわざ書かなくても、「この領域は必要かそうでないか」を自動的にチェックしてくれます。
JavaやPHPのような高級言語は、このガベージコレクションを標準機能として備えていることが多いです。

ガベージコレクションが登場する前

20160224_4

それでは、ガベージコレクションが登場する前はどのようにしてメモリ管理が行われていたのでしょうか?
実は、プログラマ自身がメモリの確保と開放を行うためのコードをわざわざ書いていました。現在でも、ガベージコレクションの搭載されていないC言語などでは、プログラマはその処理を自分たちで書いています。

しかし、なんとなく想像がつくと思うのですが、この方法はバグをよく生み出します。「処理が終わったのにもかかわらず、メモリを開放し忘れる」というミスをしやすいのです。この状態になってしまうと、プログラムが実行されるたびにメモリ上にゴミがたまり続けます。そうして最終的には、使用可能なメモリを食いつぶしてしまい、プログラムが動作不可能な状態となってしまうのです。これを“メモリリーク”と呼びます。

20160224_5

メモリリークは熟練したプログラマでも回避するのは困難でした。しかし、ガベージコレクションによってメモリ管理をそれほど意識しなくてもよくなり、プログラミングの敷居がぐっと低くなったのです。

Scavenge GCとFull GC

ガベージコレクションには、大きくわけて2つの種類があります。それは、“Scavenge GC(スキャベンジ・ジーシー)”“Full GC(フル・ジーシー)”。それぞれの違いはどのようなところにあるのでしょうか? 順に見ていきましょう。

■Scavenge GC

「あるプログラムが使用できるメモリ領域」のことを「ヒープ領域」と言います。そして、このヒープ領域はさらに「New領域」と「Old領域」に分けられるのです。New領域には生成されたあとすぐに廃棄されるオブジェクトが入り、Old領域にはもっと長い寿命を持つオブジェクトが入ります。

Scavenge GCはそのうちNew領域のみを対象としたもので、比較的短時間で終了します。掃除のおばちゃんを例にとると、「テーブルの上やフロアだけをサッと掃除する」ような状態です。

■Full GC

一方のFull GCは、Old領域をふくむ全領域を対象にしたものです。(状況によっては、一部領域が除外されます)Scavenge GCほど高頻度では発生しないかわりに、終了するまでに時間がかかります。これも掃除のおばちゃんを例にとると、「部屋全体の大掃除をする」といった感じでしょうか。

20160224_6

ガベージコレクションによるパフォーマンスへの影響

Webアプリケーションのように、「ほんの少しだけレスポンスが遅くなるのは許容できるけれど、システムそのものが数秒~数十秒間停止してしまうのは避けなければいけない」という条件がある場合、Scavenge GCは発生してよくても、Full GCが発生することは何としても防がなければいけません。※
それは非常に重い処理であるため、システムのパフォーマンスに大きな影響をあたえてしまうからです。Full GCをおさえるには、具体的には次のような点に注意することが必要になります。

■オブジェクトをできるだけ使い回さないこと

オブジェクトの寿命が長くなるため、Old領域にわり当てられる可能性が高くなります。Old領域がふえればふえるほど、Full GCが発生しやすいのです。

■新しいオブジェクトを大量に使用する場合は、New領域を大きめにとること

プログラムの起動オプションなどで指定可能です。これも同じように、Old領域に割り当てられるオブジェクトを少なくする意図があります。

※ただし一部のゲームアプリのように、ほんのわずかの処理速度遅延が許容できないときには、このケースが当てはまらない場合があります。

おわりに

ふだんあまり意識することのないガベージコレクションという機能。そこには、私たちの代わりにせっせとゴミを回収してくれている掃除のおばちゃんが住んでいます。耳をすませば、無機質なソースコードのすき間から、おばちゃんの声が聞こえてくるかもしれませんよ。

20160224_7

この記事を書いた人:ぞの

img_zono

Webアプリケーションエンジニアとして様々な現場に参画し、多種多様な言語を習得。エンジニアとしての強みは汎用性の高さと、メンバーとコミュニケーションを取り合いながら円滑に案件を進められること。趣味は音楽と将棋。Ruby愛好家。Twitter : @zono1009

関連する記事

facebook

案件情報や最新記事をお届けします。
ぜひチェックしてみてください。