RPythonで書かれたRuby処理系Topazで遊ぶ
TopazというRuby処理系が話題となっているようだ。RPythonで書かれており、CRuby(YARV)よりも高速だという。
同僚でもあるパイパニスト(語弊ある)id: rokujyouhitoma がTopazをビルドできない!と言っていた。そんなに難しいのならチャレンジしてみよう。今日はなぜかPython Tシャツを着ているし。昨日はなぜか職場でNode.jsとPerlのコードを読んでいたし。
ビルド
python環境はpythonbrewで、今回はvirtualenvは使わない。OSはMountain Lion。git/Mercurial/各種ビルドツールは入っている感じで。
mkdir topazos cd topazos git clone http://github.com/topazproject/topaz hg clone https://bitbucket.org/pypy/pypy cd topaz pip install -r requirements.txt python ../pypy/rpython/bin/rpython -Ojit targettopaz.py
RPythonが出すマンデルブロ集合をぼーっと見ていると、ビルドが終わる。 最適化をかけたあと、RPythonの実行系も含んだC言語のソースコードを吐き出し、それをビルドするようだ。
起動してみる
まずは試しに起動、と。
> bin/topaz RPython traceback: File "topaz_main.c", line 128, in entry_point File "topaz_main.c", line 2163, in _entry_point Fatal RPython error: NotImplementedError [1] 99870 abort bin/topaz
Oh。なんか失敗した。-eでワンライナーするか、スクリプトファイルが必要らしい。
> bin/topaz -e "puts 'Hello Topaz.'" Hello Topaz.
やたー、動いた。
簡単なベンチマーク
差が6つの素数の組である、セクシー素数を求めるRubyコードを動かしてみる。セクシーな結果は出るのかな。
> ruby -v ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-darwin12.0.0] > time ruby sexy_prime.rb 51.774221 ruby sexy_prime.rb 51.76s user 0.03s system 99% cpu 51.793 total > time bin/topaz sexy_prime.rb 10.434968 bin/topaz sexy_prime.rb 10.42s user 0.02s system 99% cpu 10.444 total [/shell]
Oh, Sexy! 確かにこのベンチマークコードではかなり速くなっているようだ。
実装を見てみる
せっかくなので、実装も見てみよう。topazのディレクトリ構成はこんな感じ。
- lib-ruby: Rubyで書かれたRubyの標準クラス/モジュール。FileUtilsとかppとか。
- topaz: RPythonで書かれた本体。構文解析とか。
- topaz/modules: RPythonで書かれた標準モジュール。KernelとかMathとか。
- topaz/objects: RPythonで書かれた標準クラス。BignumとかFileとかRegexpとか。
ためしに、topaz/modules/math.pyを見てみよう。
from __future__ import absolute_import import math from topaz.module import Module, ModuleDef class Math(Module): moduledef = ModuleDef("Math", filepath=__file__) @moduledef.setup_module def setup_module(space, w_mod): space.set_const(w_mod, "PI", space.newfloat(math.pi)) space.set_const(w_mod, "E", space.newfloat(math.e)) @moduledef.function("exp", value="float") def method_exp(self, space, value): return space.newfloat(math.exp(value)) @moduledef.function("sin", value="float") def method_sin(self, space, value): return space.newfloat(math.sin(value)) @moduledef.function("sqrt", value="float") def method_sqrt(self, space, value): return space.newfloat(math.sqrt(value)) @moduledef.function("log", value="float", base="float") def method_log(self, space, value, base=math.e): if base == math.e: return space.newfloat(math.log(value)) else: return space.newfloat(math.log(value) / math.log(base))
どうみてもRPythonです。本当にありがとうございました。
もっと突っ込んだベンチマーク
調子に乗って、The Computer Language Benchmarks Gameにあるベンチマークプログラムを動かそうとしたけど、めんどそうなので挫折。動かし方が書いてあるページがあるので、誰かチャレンジしてほしいす。おっさんねむいっす。