今回のテーマ
筆者がCRuby実装を読んでみようという記事です。第四回です。
CRuby本体にコミットを送ってみようとかいろいろしていた結果数日空きました。
今回はコードを掘るのではなくてCRubyのコードに対するベンチマークの取り方について。
必要に駆られてやったことなので、その記録もかねて。
benchmarkディレクトリ
CRubyのコードをpullして持ってくると、ルートにはbenchmarkディレクトリがあります。
なんだ、これを使えばよさそうですね。
中に入ると、いくらかの具体的なbenchamrk対象のrubyソースファイル(bm_xxxxxx.rb)にまぎれて、
run.rb, runc.rb, driver.rb
など起動に使えそうなそれっぽい物が。
これ叩けばよいのかな?と想像してmake installしたrubyバイナリで起動してみますと……
~/.rubydev/bin/ruby ./benchmark/run.rb
……。パーミッション関連のエラーが出ます。
contrib以下のファイルが読み込めていないようです。
いや、ファイルがないんですね。これは。
うーん。
灯台下暗し
そういえばMakefileからこういう操作はできてほしいです。そもそもそちらが基本なのではないかと思いました。
grep benchmark *.mk
とするとcommon.mkにbenchmarkルールが見つかりました。
またhelpルールも見つかりまして、make help
でその他のMakefileの用法もきれいに出力してもらえるのが分かりました。(ああ、これはすぐ試すべきだった。。。)
make golf
なんていう興味深い物もあるのですが、ともかくmake help
でbenchmarkのことをしらべます。
<前略>
:
benchmark: benchmark this ruby and COMPARE_RUBY
:
<後略>
とのことで、「COMPARE_RUBY」と現在のrubyの比較を行うようですね。COMPARE_RUBYってなんでしょうか?
grep COMPARE_RUBY *.mk
を見ると……
grep COMPARE_RUBY *.mk
common.mk:COMPARE_RUBY = $(BASERUBY)
common.mk: --executables="$(COMPARE_RUBY); built-ruby::$(RUNRUBY)" \
common.mk: --executables="$(COMPARE_RUBY); built-ruby::$(RUNRUBY)" \
common.mk: --executables="$(COMPARE_RUBY); built-ruby::$(RUNRUBY)" \
common.mk: " benchmark: benchmark this ruby and COMPARE_RUBY" \
uncommon.mk:COMPARE_RUBY = $(BASERUBY)
uncommon.mk: --executables="$(COMPARE_RUBY); built-ruby::$(RUNRUBY)" \
uncommon.mk: --executables="$(COMPARE_RUBY); built-ruby::$(RUNRUBY)" \
uncommon.mk: --executables="$(COMPARE_RUBY); built-ruby::$(RUNRUBY)" \
uncommon.mk: " benchmark: benchmark this ruby and COMPARE_RUBY" \
これは環境変数参照ですね。つまるところ環境変数にCOMPARE_RUBYを設定して実行するだけで2つのバイナリ間で比較できそうですね!
バイナリ作りそのものはブランチごとに./configure --prefix=$HOME/.rubydev_orig
とかやってあげればできますからきっと簡単ですね!
画餅に帰す
COMPARE_RUBYに事前にビルドしておいた$HOME/.rubydev_orig/bin/ruby
を設定して実行してみたところ問題無くベンチマークが実行され、結果がファイルとして書き出されました。
よし。中身を見てみましょう。
ん……?COMPARE_RUBYに設定したバイナリではなくて、システムのrubyがつかわれてしまっています。
簡単にできそうと思いましたがそんなことはなかった。。。
改めてMakefileのCOMPARE_RUBY該当行周辺を読んでみましょう。
COMPARE_RUBY = $(BASERUBY)
ん?COMPARE_RUBYは強制的に$(BASERUBY)に設定されていますね。これは書換えできないのでしょうか。
(実際にはあたふたいろいろしてしまいましたが)Makefileのmanページを読んでみることにしました。man make
<前略>
:
-e, --environment-overrides
Give variables taken from the environment precedence over variables from makefiles.
:
<後略>
makeは-eオプションをつけることで、内部で変数を設定する時、強制的に上書きができる、と。なるほど。
make benchmark -e COMPARE_RUBY=$HOME/.rubydev_orig/bin
今度こそ上手く動きました。
取ったベンチマークの分析は……頑張りましょう。
ベンチマーク手順・まとめ
- 開発中のrubyの速度を計測したい場合は
make benchmark
が利用できる- 複数のrubyをインストールするには
./configure --prefix
を普通に使えばよいので、任意のブランチ間の差を見たければこれを使う。 - この時COMPARE_RUBYを環境変数で、比較対象のruby実行バイナリを設定しておけば、2つの速度比を測ることができる
- ただしMakefileの中で上書きされるので、makeの-eオプションを使い強制的に設定しなければ動作しない。
- 複数のrubyをインストールするには