【Ruby ことはじめ!?】やらなくても困らないことをやってみる

何の記事??

タイトルの通り、Ruby 関連で「やらなくても特に困らないのに、あえてやってみる」をテーマにちょーっとだけマニアックな話をしていきたいと思います。

Ruby についてプログラミング技法的な部分、明日使えるノウハウ的なことをメインに話すわけではないので読み物としてお楽しみいただければと思います。

目次的には以下の通りです。

  • Ruby 自体のソースコードから Ruby をインストールしよう
  • Ruby 自体の実装をデバッグしよう
  • Ruby の GC の仕組み

それでは見ていきましょう〜!!


Ruby 自体のソースコードから Ruby をインストールしよう

さて、Mac を使っている方は Ruby がそもそも入っています。
Windows の方は、Cygwin を入れるなどして Ruby の開発環境を自分の PC 上に作成するかと思います。

さて、ここであまりやらない方法で Ruby をインストールしてみようと思います。 (一応 Ruby のサイトで紹介はされているので変なやり方ではありません。)

www.ruby-lang.org

その方法は、Ruby のソースコードからのビルドです。
何の意味があるの??的な質問が飛んできそうですね(笑)
安心してください、意味はあります!!← 古いかw

それは、Ruby 自体の実装を改造することができることにあります。Ruby はオープンソースのプログラミング言語であるために Ruby 自体のプログラムをみることはでき、自分用 Ruby を作るなどの拡張ができるんです。

それでは、早速 Ruby のソースコードを取得してみましょう。

Subversiongit で取得することができます。

■Subversion 編

svn co http://svn.ruby-lang.org/repos/ruby/trunk 任意の名前

■git 編

git clone git://github.com/ruby/ruby.git

これで皆さんのローカルPCに Ruby のプログラムを持ってくることができました。
実際に中身をみてみると C ファイルだらけですね。Ruby は C言語で実装されているため Ruby の拡張機能なんかを作りたい場合は、このCファイルを拡張する必要があります。

それでは実際に使えるようにコンパイル・インストールを行なっていきます。

基本的に普通のプロジェクトインストールの流れと似ていて、
「設定ファイル作成→makeファイル作成→make→インストール」
という流れになります。

大前提ですが、先ほど持ってきたディレクトリに移動し、下記コマンドで設定ファイルを作成します。

autoconf

設定ファイルができたら(上記コマンドが正常に終了したら)make ファイルを作成しましょう。

./configure

それでは make コマンドでコンパイルを行なっていきましょう。

make
make check

make check の結果「check succeeded」が出力されれば OK です。
下記コマンドでインストールしていきましょう。

make install

最後にパスを通して完成です!!

export PATH=/usr/local/bin:$PATH

Ruby 自体の実装をデバッグしよう

せっかく Ruby 自体のソースコードを入れたのでどのように動いているかを見てみましょう。
・・・といきたいのですが、それを書き始めると本一冊レベルになるので今回はデバッグの方法を紹介します!

デバッグモードに切り替えるために先ほどの工程で、make ファイルを作成するときに下記に変更してください。

./configure CFLAGS=-g

あとは先ほど同様に make, make install を行なってください。

デバッガには gdb を使用します。

実際に動かしたい Ruby プログラムを作成し、下記コマンドでデバッグしてみてください。(gdb の使い方は今回は主旨とはずれるので割愛します。)
Ruby の実装(Cプログラム)がどう動いているのかがわかります!!

gdb --args ruby ~~.rb

Ruby の GC の仕組み

Ruby の GC のお話です。
さすがに難しく、以下の素敵な記事の要約的な部分があります。お許しください(笑)

blog.codeship.com

まず根本的な問題として GC(Gabage Collection) って何??というと事から解説します。

オブジェクトを作成場合などにコンピュータ上のメモリ領域をそのオブジェクトのために割り当てます。子供ができたので子供部屋を作成してあげるイメージですね。
さて、プログラム中で使わなくなった変数やオブジェクトのためにいつまでもメモリを確保しておくわけにはいきません。いわゆるメモリリークの原因になります。

そこで不要になったオブジェクトを自動で(プログラマが意識せずに)掃除するというのが GC です。GC は Gabage Collection の略なので直訳で「ごみ集め」です。まさに言葉の通りの機能ですね。

それでは Ruby の GC について見ていきましょう。以下のプログラムをご覧ください。

class Node
  def initialize(val)
    @value = val
  end
endNode.new(1)
p Node.new(2)

上記コードで Node クラスのインスタンスを作成している(Node.new の部分)時の動きを見ていきます。

実はこれといって何もしていないそうです!!というのも Ruby ではあらかじめ何千ものオブジェクトを作成し、それを freelist という連結リスト上に配置します。

イメージ的には以下の図のようです。

freelist
freelist

オブジェクトの作成を繰り返すことで

object
オブジェクトの作成

さて、あらかじめ作っていた freelist を使い切りました。
この時、Ruby は Mark and sweep アルゴリズムを用いて汚染オブジェクトをマークします。

さらに stop the world(必殺技みたいww) によってアプリケーションに処理を一時停止し、汚染オブジェクトを掃除(sweep)した結果が下図になります。

sweep 結果
sweep 結果

freelist に空きができたのでオブジェクトを格納するスペースが生まれましたね!!
このような仕組みでプログラマはあまりメモリを意識しないで Ruby がかけているわけです!!


最後に

さて早速 Ruby のスレッド部分について自分でも拡張してみました。
まだ完成していないため、いつか公開できるようになりたいなと思っています。

なかなか言語自体の実装に興味を持つ人っていないですが、設計思想とか本当にコードを見ているだけでもとても勉強になります。

この記事が、少しでも興味を持つきっかけになれば嬉しいです。

それではまた次回〜〜