2013年5月30日~6月1日の3日間、お台場にある東京国際交流館にてRubyKaigi 2013 が開催されました。基調講演をそれぞれレポートします。
3日目最後の基調講演は、open-uri、socketをはじめとし、たくさんのライブラリの開発に携わっているRubyコミッター、田中哲さんによる、Ruby開発における「多様性との戦い」についての講演でした。
自己紹介
始めに「お台場」で「多様性=ダイバーシティ」といえば……。と言ってダイバーシティの写真を映す、と言う和やかな冗談から始まった田中哲さんの発表は、Rubyのコミッターならではの切り口からみた多様性との戦いの記録でした。
田中さんは2008年度のRubyKaigiでも多様性がテーマであったことを取り上げつつ、逆に、「 多様性は無条件で良いものと言えるだろうか?」と問いかけました。一つの例として、ウェブブラウザの多様性を取り上げ、その対応に苦労した人も多いのではないか、と言います。
そうして、ご自身がRubyの開発を通してプラットフォーム多様性と戦ってきた話を始めました。
Rubyを多様な環境で動くようにするには
Rubyの開発のフローにおいては、ある機能や修正を実装したあとでも、その変更をプラットフォームメンテナにより様々な環境にポートしていく作業が必要になるとのことでした。そしてこの「様々なプラットフォーム」での多様性こそが今回のテーマだと言います。
dbmライブラリ
多様性との戦いの現場の例として、dbmライブラリ について取り上げました。
dbmとはいわゆるKVSの一種であるそうです。データベースのファイルをdbmライブラリでオープンすると、ハッシュのように読み込みや書き込みをすることができ、また他のプロセスからも読み書きができるようなシンプルなデータベースです。
便利そうなライブラリなのですが、会場にいるRubyist達にはあまり知られていないようでした。
Rubyのネイティブ拡張の仕組みとextconf.rb
最初に田中さんは、Rubyにおけるネイティブ拡張の方法について説明しました。
rubyのソースディレクトリの中のextディレクトリの配下には、dbm.cというC拡張のソースと、extconf.rbというRubyのスクリプトが存在します。このextconf.rb は、ビルド時に様々な環境を調査するものだとのことです。様々なCのプログラムで利用されているconfigureスクリプトのようなものですが、こちらはRubyで書けるものとなります。
extconf.rbの内部ではmkmfと言う名前のライブラリを利用しています。最も簡単な例は次のような2行のスクリプトです。
require 'mkmf'
create_makefile('fcntl' )
mkmf.rbを利用すると、Cのライブラリや型などが、現在のプラットフォームで利用可能かの調査ができるそうです。そして、Rubyでは標準で様々な拡張ライブラリのためのextconf.rbが添付されていますが、dbmのもの は254行あり、Ruby標準ライブラリの中でも第3位の大きさだそうです。
dbmの歴史
次に、dbmはRubyのライブラリ名でもあると同時に、Cのライブラリの名前であると言うことで、Cのdbmライブラリの歴史を話しました。
dbm
まず、dbmは、AT&Tが提供するUnix version 7に添付されていたものが最初だったそうです。ヘッダファイルもなく、キーと値のサイズにも厳しい制限がありました。この段階のdbmはRubyではサポートしていません。
ndbm
一方で、4.3 BSDには、Unix Version 7から派生したndbmが添付されていました。こちらもAT&Tのライセンスだったそうです。そしてこの段階でAPIが標準化され、Rubyもサポートするようになりました。こちらのndbmライブラリはlibcで標準で含まれているので、コンパイラにリンカを指定しなくとも利用可能だそうです。
gdbm
また、GNU operating systemの開発の上で、AT&Tライセンスでない自由なdbmが必要になりました。そこでGNUライセンスのgdbmが誕生することとなりました。gdbm独自のAPIに加えdbm、ndbm互換APIを持っているそうです。
Berklay DB
Berklay大学でもAT&Tでないライセンスのndbmの代替が必要となり、Berklay DBが開発されました。Berklay DBは比較的高機能だそうです。また、他のdbmと違ってファイルが一つだけとなります。
qdbm
比較的最近のものではqdbmと言うものも存在し、こちらも高機能であるとのことでした。
ライブラリを正しく使うには?
RubyのDBMライブラリでは先に述べたCのDBMライブラリのうち、ndbm、gdbm、Berklay DB、qdbmの4種類を、Rubyからはどのライブラリを使っているか意識することなく同じAPIで利用することができるそうです。そのためにはRubyのDBMライブラリからCライブラリを正しく使う必要があると田中さんは述べました。
Cライブラリを正しく利用するためには、対応するライブラリとヘッダを正しく読み込めば良いのですが、現実ではなかなか大変な例もあるとのことでした。例えば、ndbm.hをインクルードする場合でも、実態が4.3BSDのndbmかもしれないし、Berklay DBかもしれない、あるいは入っていないかもしれない、という現象が起こりうると言います。
dbmに関する過去のバグ
そして、かつてのruby-listでの投稿をもとに、いくつかのバグを紹介しました。プラットフォームによってrequire 'dbm'
と言う単純なコードが動かなくなる事例があったそうです。
1.0リリース直後の時代
このような事例として、シンボルdbm_clearerr
が見つからないと言うエラーがでてしまうと言う問題が、ruby 1.0-971021のリリース一週間後にruby-list MLに投稿されました。
これは、根本的にはdbm_clearerr
の定義に、プラットフォームによってよってミスマッチがあることが原因でした。差異を埋めるために、 #ifdefを宣言したところ、typoをしてしまったため、どういう環境にしても使われないので呼び出されなくなり、コンパイルエラーにはならなくなった、と言うエピソードを披露しました。
このtypoも含めRuby 1.3.6で直ったとのことでしたが、新たな問題を呼び込んでしまったそうです。
1.3.6以降でのバグ
新たな問題は、dbm_clearerr
を正しくチェックするようになったことが原因で、オブジェクトファイルのリンク状況が変わり、プラットフォームによっては結果的に複数のオブジェクトファイルで同じ名前の宣言がされてしまって、エラーになる現象が起こってしまいました。
こちらは、dbm_clearerr
のチェックを外すことで結果的に動くようになりましたが、よく考えないとなぜ直ったかが分からない、「 薄氷を踏むような感じ」の修正だったとのことです。
正しく組み合わせを検知すること
続けて、Ruby内部でライブラリを検出する仕組みがどうなっているかの解説を始めました。
今の環境を整理する
田中さんによると、基本的には、正しい組み合わせは通して、間違った組み合わせは通さないようにすれば良い、とのことでした。
組み合わせには次の要素があります。
このうち、dbmではヘッダーは5種類、リンクする対象のライブラリは8種類、libcの実装は3種類について考慮する必要があるそうです。これら5 * 8 * 3 = 120の組み合わせのうち、正しくコンパイルできる込み合わせは20通り程度とのことです。効率よく間違ったものを除外する方法を考えていきます。
正しい組み合わせの探し方
組み合わせの絞り込みは、次のような段階で行っていったそうです。
dbm_open
がリンクできるかどうか
dbm_clearerr
のリンク可能性を判定
多くのCライブラリでは、上記のようなリンク可能性の判定で絞り込みができるそうなのですが、dbmのCライブラリの場合はこれだけでは絞り込み条件が足りないため、仕方なく次のような泥くさい判定を追加していきました。
_GDBM_H_
の定義を探す
gdbm_version
が利用できるか
ヘッダーの型、ライブラリの名前をみる
現在の状況と残りの課題
しかし、ここまでやっても、まだ若干だけ検知しきれない間違った組み合わせが残っているそうです。しかし、基本的には全く違う組み合わせはきちんとfailするような状況にはできたと言います。いくつか、まだインストールが失敗する環境があり、把握はしているが、通常のインストール方法では起こり得ないケースなので、優先的な作業はしていないようでした。
dbm自体については、ライブラリによってファイルの拡張子、数、フォーマットも違うなど、他にも問題があるとのことです。
ここまでのdbmに関する問題を踏まえ、「 ndbmの未来の開発者へのお願い」として、大きく次の事柄を主張しました。
判断のしやすいマクロを定義してほしい
コンフリクトが起きないようにしてほしい
「db」のような一般的にすぎる名前はやめて、十分にユニークに名付けをしてほしい
実際にndbmをこれから開発する人はわずかでしょうが、Cのライブラリ、あるいはその他のライブラリの開発一般に言える注意点だろうと思います。
まとめ
田中さんは最後に、これらの話のまとめとして、次のような事柄を話しました。
dbmの状況
まず、dbmの状況として、Rubyはいくつかのdbmをサポートしていること、多くの環境では正しく動作することを改めて述べました。そのような状況にするために、いろいろなライブラリのソースコードを探してきて、読んで、調べる必要があったそうです。そのため、ソースコードが自由であることは重要であったと言及しました。
広がる一方の多様性との戦い
そしてもう一つの言いたいこととして、多様性はあらゆる場面で起こっているし、進みつつあることを指摘しました。
dbmやブラウザの他にも、Rubyに関することに限っても様々な多様性が存在します。例えば、OSは、特に組み込みやLinux関係に顕著であるように、常に増え続けていることを取り上げました。libcやkernelのソースコードにも様々なバリエーションがあると言及しました。
また、Rubyの実装も多様になってきていることを取り上げました。昨日のJose Valimの話 にもあった通り、実装ごとの差異が分かりづらい問題を起こすような状況は考えられます。このように、Rubyの開発ではこれからも多様性との戦いは続くであろうとのことです。
最後に、そのような状況の中でも、多様性との戦いは「チャレンジしがいのある」ことだ、と締めくくりました。
コミッタでないいちRubyの利用者からは、なかなか体験できないような世界の一端を教えてくれた田中さんの基調講演も、再起動したRubyKaigiのコンテンツにふさわしい、非常にディープなものだったように思いました。