TimeoutX 0.2.0 を公開しました
今更感漂う過去の遺物がHDDの奥底から発掘されたのを記念してTimeoutX 0.2.0を公開致しました。
TimeoutXとは激烈に速いtimeout関数を提供するだけのライブラリです。ちなみに最初の公開は2002年。あまりにキワモノなのでどこかの闇に失なわれてもう五年。時代の流れにあがなうようにgem化することでついにいつでもどこでもTimeoutXが使えるようになりました。
timeout関数が速いとはどういうことよ?と思う方もいらっしゃるでしょうから分かり易いベンチマーク結果を載せておきます。まずベンチマークは以下のようになります。
n = 100000 Benchmark.bmbm(10) do |x| x.report("Timeout") { 1.upto(n) do ; Timeout.timeout(1){true}; end } x.report("TimeoutX") { 1.upto(n) do ; TimeoutX.timeout(1){true}; end } end
この実行結果は1.8.6の場合以下のようになります。
Rehearsal --------------------------------------------- Timeout 5.960000 0.460000 6.420000 ( 6.521520) TimeoutX 0.780000 0.050000 0.830000 ( 0.851778) ------------------------------------ total: 7.250000sec user system total real Timeout 5.650000 0.790000 6.440000 ( 6.516992) TimeoutX 0.760000 0.080000 0.840000 ( 0.863438)
おお、激烈に速い!という程でもない気もしますが、まぁ10万回も呼び出せばさすがに体感出来るくらいには違います。そういうわけですからtimeout関数を10万回も呼び出しちゃいたいような奇特な方は是非ともTimeoutXをご使用下さい。ご利用にはgemを使うのが便利だと思います。
sudo gem install timeoutx
一応、何故このような差が出るのかを解説しておきます。Ruby標準添付のtimeout.rbはtimeout関数を一回呼び出す毎に新たなスレッドをひとつ作成します。よって上のように10万回連続で呼び出すと10万ものスレッドを作成してしまうわけです。スレッド作成のコストはちょこっとありますので、これを10万回も繰り返しますとさすがにそれなりに時間がかかります。TimeoutXではこのスレッド生成を避けるため、timeout専用のスレッドをひとつ作成し、そこでタイムアウト処理を行なっています。簡単に言うと、手抜き!
TimeoutXを作った歴史的な経緯は元々Webrickの高速化用専用です。というか、タイムアウト処理を短時間の内に繰り返す必要のあるRubyのアプリケーションなんてそうそうあるわけないのであって。しかもWebrick(当然mongrelも)は今やtimeout.rbを使用せず独自にタイムアウト処理を実装しているため、もう使い道がありません。そういうわけで長らく闇に葬られていたのですが、先日たまたまHDDの奥底から発見しましたので、モニュメントとしてgem化した次第です。
ちなみに 1.9.0 のベンチマーク結果にちょっとびっくり。
Rehearsal --------------------------------------------- Timeout 12.140000 2.760000 14.900000 ( 15.333607) TimeoutX 0.490000 0.010000 0.500000 ( 0.518974) ----------------------------------- total: 15.400000sec user system total real Timeout 11.210000 2.390000 13.600000 ( 14.337455) TimeoutX 0.490000 0.010000 0.500000 ( 0.512449)
というわけで、1.8.6よりもスレッド生成のコストが上昇しているようです。あまり1.9系の事情はよく分かっていないのですが、このことを頭の片隅に留めておこうかな、と思いました。