tixture55’s diary

主にプログラミング関係の日記です。

CRubyの仕様周り(文法、コンパイルとか)

※この記事は古い記事を参考に書いておりますので、最新のrubyの仕様とは異なる可能性があります。

 

Rubyのクラス

 

rubyでは、すべてのオブジェクトがObjectクラスの子孫である。これはC++と際立って異なる点である。 既存のRubyクラスを編集して、任意のメソッドを追加する方法を明白に示しています。

サンプル. Ruby では既存のクラスを変更することができます
1
2
3
4
5
6
7
8
9
10
11
irb(main):035:0> y = String.new("racecar")
=> "racecar"
irb(main):036:0> y.methods.grep(/palindrome/)
=> [ ]
irb(main):037:0> class String
irb(main):038:1> def palindrome?
irb(main):039:2> self == self.reverse
irb(main):040:2> end
irb(main):041:1> end
irb(main):050:0> y.palindrome?
=> true

上記では、Stringクラスに palindrome?メソッドを追加しました。このようにRubyのクラスは実行時に編集することができます。

 

Rubyではselfキーワードを使って静的メソッドを定義できます。C++同様にオブジェクトなしで非静的メソッドを呼び出すことはできません。 また、メタクラスやメソッド名の前にクラス名を追加するという方法でも静的メソッドを定義できます。

rubyには予め用意された組み込みクラスがあるが、ユーザが独自クラスを定義することもできる。 仮に、ユーザがclass式を使って既存クラスと同名のクラスを定義した場合、それは既存クラスの書き換えではなく拡張となります。 もっとも同名のメソッドを再定義すれば、それは基のメソッドの上書きになるので注意を要します。

 

並列処理

rubyは1.8の段階では真の並列処理はサポートしていませんでした。Thread 構成体のThread.new は呼び出されるたびに真のオペレーティング・システム・スレッドを作成することはしません。Ruby がサポートしているスレッドは、「グリーン・スレッド」です。

このグリーン・スレッド(仮想VM上で実行されるスレッド)では、便利なことに、あるスレッドが何らかの I/O 処理が行われるのを待機している間、別の Ruby スレッドを簡単にスケジューリングして CPU を有効に利用することができます。ただし、この構成体は、最近のマルチコア CPU には対応していません。

Rubyでも並列処理はできるが、時系列でスレッドを切り替えているだけなので、処理速度の大幅な向上は期待できない。ただし、IO待ちが発生する際に一時的にGILが解放されるため、大容量のデータにアクセスするような場合であれば並行処理による高速化が期待出来る。

 

コンパイル、高速化


rubyの高速化を目的に、RubyバイトコードC言語などを経由して機械語へ変換するというアプローチもある。

 

コンパイル済みコードに求められる特徴

●ロードにかかる時間が少ないこと

●メモリ消費量を削減するために、サイズが小さいこと

スクリプトを変更した場合、コンパイル済みコードを無視、もしくは更新すること


コンパイル済みコードが古くなったかどうかを判定するために、タイムスタンプを利用することは 直接的な手段だが、タイムスタンプを取得するためには、オーバヘッドが必要。


コンパイルされたコードのロード処理には、インタプリタプロセスに非依存の情報を、プロセスに依存した形に変換する処理 がそれにあたる
例えばmmapシステムコールにより、ファイルをメモリにマップするだけで済めば、前処理の時間も少なく、また実際に必要になるまで ディスクアクセスを遅延することができます。
rubyにはMarshalという機能があり、インタプリタプロセスやオブジェクトを適切にエンコードし、コンパイル済みコードとして 構成し実行時にはロードする仕組みを提供する。異なるRuby間プロセスでデータを受け渡す仕組みとして利用する。

 

ファイルフォーマットは このような状況を踏まえ、下記のようなヘッダ部を持つ。

 

struct ibf_header {char magic[4]; /* YARB */unsigned int major_version;unsigned int minor_version;unsigned int size;ibf_offset_t iseq_list_offset;ibf_offset_t id_list_offset;ibf_offset_t object_list_offset;};

 

まとめ

Rubyはいろいろ奥が深いですよね。機会があったら、C++rubyのライブラリとか作ってみようと思います。