DRb.start_service が遅くなることがある

いつも使っている環境ではサクサク動いてるのに別の環境にもっていくとやけに起動が遅くなるスクリプトがあったので調べてみたら、DRb.start_service がやたら時間がかかってました。引数なしの場合。引数で uri に特定のIPアドレスかホスト名(localhostでも可)を指定するとすぐ返ってきますが、省略時は時間がかかるという。

でさらに追跡してみたら、IPSocket#addr が時間がかかっている。ext/socket/socket.c をみててはっと気がついて次のようにすると直りました。

saved = IPSocket.do_not_reverse_lookup
begin
  IPSocket.do_not_reverse_lookup = true
  DRb.start_service
ensure
  IPSocket.do_not_reverse_lookup = saved
end

ようするに省略時のアドレス "0.0.0.0" をホスト名に逆引きしようとして失敗するまでに時間がかかっていたようです。たぶんシステムの設定によるんだと思います。これを早くするのはどうすればいいのかな。

ともかく、DRb::DRbServer.new では単にポート番号が知りたくて IPSocket#addr を呼んでいるだけなので、逆引きなんて不要なので抑制したいところですが、IPSocket.do_not_reverse_lookup はグローバルに影響してしまうので drb.rb で上記のようなことをしてしまうと、マルチスレッドの場合に別のスレッドの動作に影響してしまうかもしれないからできないんでしょうね。do_not_reverse_lookup がせめてスレッド毎に制御できたら。というかソケットのオブジェクト毎に制御できればいいんですけどね。なんか以前そういう要望を ruby-dev かどこかで見た気もしますが……。

[追記] 要望があったどころか、1.9 では既に BasicSocket#do_not_reverse_lookup= が追加されていました。
と、いうことは 1.9系に添付されている drb では DRbTCPSocket.open_server で soc.do_not_reverse_lookup = true すればいいんじゃないかと。
また 1.9 に移行すべき理由がひとつできました。