2011/08/19

Rubyのメモリ利用

GCとcompactionについて色々理解が進んだのでメモ的に書いてみる。

Garbage collectionとは、参照されていないオブジェクトを解放する操作のことである。ここでいう解放とは、必ずしもCで言う所のfree()的な操作とは一致していない。まず、ここをよく理解していなかった。理解してないとどういうことになるかというと、例えばメモリリークについて調べようとしたときに、OSサイドから見える情報で問題が起きているだとかないだとか言ってしまう。

というか、そもそもGCとは逆の確保という操作についてもmalloc()的な操作が絡むとも言えない。これらは、GCがどういう実装になっているかによって、定義が変わってくる。

今回は、Rubyで長時間走るプロセスについてメモリの増加をできるだけ抑えたいという目的があった。ので、ここに書いてあることはRubyはこんな感じにメモリを使うものですよというだけのことである。ややこしいのは、Rubyにはいくつも異なる実装があり、それぞれが異なるGCを持っているということだ。同じ系統の実装でも、バージョンが変われば実装も変わっていることも考えられる。なので、この関係の話をするときはは、どの実装について話をしているのかはっきりさせてすすめるのが良さそうだ。

CRuby 1.8.7 と1.9.2で幾つかテストプログラムを書いて試したところ、こんな流れで動くことがわかった。

a=[]
99999.times { a << {} }

などどすると、Rubyのプロセスが膨れ上がる。
a.clear
とすると、Arrayオブジェクトがimmutableだったとしても、99999個分のHashオブジェクトは解放の対象となるはず。そこで
GC.start
として明示的にGCを走らせる。しかし、psなどから見えるOSプロセスとしてのメモリの利用量の変化はほとんどない。次に同じように、

99999.times { a << {} }

ともう一度やる。今度はOSプロセスとしてメモリの利用量はあまり増えない。

同じように、a.clearしても特に目立った変化はない。ここまでやってみてわかったことは、

  1. CRubyは、必要なメモリがないときはmalloc()的な動作を行いメモリの確保を行う。
  2. オブジェクトへの参照をなくして、明示的にGC.startして解放の処理を行っても、free()的な処理を行ってOSへメモリを返却しているわけではない。
  3. 一度確保されたメモリ領域を超えない範囲で新規オブジェクトの生成を行うと、確保済みの領域を再利用するようだ。
こんな状態なので、CRuby VMの外側からは細かくは何が起きているのかうかがい知ることはできない。

これ以上のことを知るためには、CRuby VMから必要な情報を取得するメモリプロファイラを使うしかない。1.9.2には、GC::Profilerという簡易プロファイラが内蔵されており、それを使っていろんな内容を試すことができる。1.8.7にはmemprof gemがあり、機能的にはこちらのほうが充実しているようだがx86_64環境でしか動かないという事が書いてあった。

もう眠たいので簡単に書くと、GC::Profilerを使うとGC.startする前と後とで大きく変化する値があることが分かる。結果、プロファイラを使うことで分かったことは、「3」で内部的に何が起きていたのかということだけであった。あとは、Rubyのプログラムとしてメモリリークが起こっていそうという時は、これらのツールを積極的に使わないと分からないということもある。

そろそろまとめに入ると、CRubyにとってのGCとは、参照のなくなったオブジェクトを解放することではあるが、確保したメモリの解放を行うという操作ではないということだ。このGCの目的は、メモリをOSに返すことではなく、確保済みのメモリをできるだけ他の新しいオブジェクトで再利用したい、という所にあるようだ。まぁ、こんなことはRubyの本などにはしっかり書いてありそうだけど、ようやく意味が理解できるところまで来たということで。

以上のことから、OSからみたCRubyのメモリ利用の傾向は、
  1. メモリをある程度のサイズずつ必要となるタイミングでmallocしていく。
  2. mallocした範囲はfreeしない。
であることがわかった。デーモンプロセスのような常時起動型のプログラムをRubyで書いているのに、なんて厳しい。

でも、よくよく考えてみると本当に厳しい内容なのかというと実はそうでもないかもしれない。という話を次回やってみたい。


http://www.theirishpenguin.com/2009/10/29/understanding-how-ruby-stores-objects-in-memory-the-ruby-heap/



Comments: コメントを投稿



<< Home

This page is powered by Blogger. Isn't yours?