2014年11月にオーム社から「Rubyのしくみ -Ruby Under a Microscope-」というRubyの処理系を解説する本が出版されました。
https://amazon.co.jp/dp/9784274050657
須藤がこの本を紹介します。
内容
この本はRubyの処理系(主にCRuby、GCまわりはJRubyとRubyinusも)がどうやってRubyスクリプトを実行しているかを解説しています。図をたくさん用いて解説していることが特徴で、直感的に理解しやすくなっています。るびまのYARV Maniacsシリーズでピンとこなかった人はこの本で再チャレンジしてみるとよいでしょう。
Rubyスクリプトが動くためのベースのルールも一緒に紹介しています。自分が知らなかったRubyの動きがわかるかもしれません。私は定数探索にレキシカルスコープを使っているとは知りませんでした。
例えば、A::X
が定義されている状態で次のコードを実行するとエラーになります。
module A::B
class C
p X
end
end
しかし、次のコードではA::X
を参照できます。
module A
module B
class C
p X
end
end
end
この挙動は知っていて、module A::B
のような書き方が好きじゃない理由だったのですが、この挙動がレキシカルスコープに由来していたことは知りませんでした。
読むとどうなるか
まぁ、内容の紹介はどうでもいいんですよ。Rubyがどう動いているかに興味がある人は、この本を勝手に見つけて勝手に読むはずなんです。
そんなことよりも、この本を読むことによりRuby処理系の実装について考えるまとまった時間ができることが大事なんですよ。付録でささださんが「読みながら実装の非効率な部分などを見つけてしまい」と書いているように、Rubyの処理系は完成されたものではなく、今でも徐々に改良されているものです。なので、「今はこういうしくみで動いているんだ」だけでなく、「だったらこう変わったらもっとよくなるかも?」と考える、もっと言えば、その考えを実装してみて実験してみる、という風になると素晴らしいじゃないですか。そのきっかけになるのがこの本のよいところです。
私はこんなアイディアが浮かびました。(メモなのでなにを言っているかわからないかもしれません。)
- ゴミになったStringオブジェクトはfreeしてからフリーリストに戻して再利用するんじゃなくて、truncateして別のStringオブジェクトとして再利用したら効率がよくならないか
- 本にはStringオブジェクトはアロケートしたメモリーと文字列の長さは別管理していると書いている(知っていた)
- 本には遅延スイープだと書いている(知っていた)
- → Stringオブジェクトを完全にfreeしないで、文字列の長さだけ0に切り詰めて、アロケートしたメモリーを再利用すればアロケート回数が減るので速くなるのではないか。
- →→ この方法が効果があるならArrayとかHashでも使えるかも。
- スコープを抜けたときにゴミオブジェクトを検出できないか
- 本にはスコープが増えるたびに環境を作ってどうこう書いていた(そうだろうなぁとは思っていたけどあまり考えていなかった)
- 本にはライトバリアのしくみがすでに導入されていると書いていた(知っていた)
- → スコープを抜けるときに環境が破棄されるだろうからそこに残っているオブジェクトが参照されているかだけを低コストで確認できないかしら。できるなら、GCの頻度を減らせそう。Pythonだとスコープを抜ける毎にオブジェクトが回収されているけど、Pythonはリファレンスカウンター方式だからできるのかしら。
思いついたことをささっと実装して実験できるようになりたいものです。
まとめ
Rubyのしくみという本を紹介しました。
まえがきで、まつもとさんが「本書の読者のうちの誰か、もしかするとあなたがRubyの開発に関わるようになるかもしれませんし、そうなれば我々は大歓迎します」と書いています。興味が湧いてきたら、この本を読んで「あなた」になってみてはいかがでしょうか。