Ruby メモリ管理について理解してみようと思う件
はじめに
とある技術書を読んでいて、「(メソッドの速度や)メモリ管理を意識しよう」的な文章を目にしたとき、Ruby / RoRに置き換えると「そういえばめちゃめちゃ意識しているわけではないな」と思い調べてみよう、と思った。というか、そもそもメモリ管理って何さ、というところからのスタート。
そんなかんやで「メモリ管理」という未知のダンジョンに潜ってきたわけである。少しずつ理解していこうと思う。
コアとなる(であろう)記事(以下、コア記事と呼ぶことにする)
RVALUE
コア記事では以下のように紹介している。
Rubyプログラムでは、動的なメモリアロケーションにヒープ(heap)メモリを利用しており、ヒープの基本単位はスロット(slot)です。個別のスロットはRVALUEと呼ばれる値を占有します。RVALUEのサイズは40バイトで、ArrayやStringやClassなどのあらゆる型のオブジェクトを保存するコンテナです。
◉ メモリアロケーションって何ですか?
プログラム君が自分の仕事で使うメモリ(作業机)を他のプログラム君たちが使わないように陣地を確保すること
↓めっちゃ分かりやすい記事
◉ ヒープメモリって何ですか?
動的に割り当てたり、解放したりできるメモリ領域のこと。プログラムに必要なデータやオブジェクトを一時的に保存できる。割り当てたり、解放したりできるタイミングは好きなタイミングでできる。
ヒープページ
16KBの領域を持つコンテナみたいなイメージ。ヒープの基本単位であるスロットの集合体。
ヒープページの中身は、隙間なくスロットが連続している。
フリーリストとオブジェクトの割り当て
FreeListとは、空のスロットをリンクで結んだリスト。これは最後に辿ったスロットのアドレスからその直前のスロットのアドレスを導き出すことができる。
最初にヒープページが作成されると、その中の各スロットは T_NONE
という特殊な型を持ったRVALUEという値を所有する。このT_NONE
は空のスロットであることを意味し、フラグ1個とklassポインタ値(nextポインタと呼ぶ)を持つ。
ヒープページの最初のスロットにfreelistポインタが設定されて、そこから順番にスロットを辿っていく。その時に、現在のスロットのアドレスにfreelistポインタを設定して、nextポインタに直前のスロットのアドレスを設定する。
オブジェクトを保持する必要が出てきたとき、Rubyは空のスロットを要求する。
このとき、FreeListは空のスロットへのアドレスを持ったfreelistポインタを返す。
freelistポインタは次の空のスロットへのアドレスに更新をして、返したスロットへのアドレスのリンクを解除して、Rubyがそこにデータを置く。
それが繰り返されて、スロットが全て埋まると、当然ながらデータを置くことができなくなる。
そこで、Rubyではメモリスペースを確保するために使われなくなったオブジェクトを自動的に検出して解放するガベージコレクションが行われる。
◉ 参考になりそうな記事