2

IP範囲にpingを実行するスクリプトを作成しています。これが私がこれまでに持っているものです:

lines = `ipconfig`.split("\n")
thr = []
ip_line = lines.detect { |l| l=~/Ip Address/i }
matcher = /\d+\.\d+\.\d+\.\d+/.match(ip_line)
if matcher.length > 0
    address = matcher[0]
    address.sub!(/\.\d+$/,"")
    (1 .. 254).each do |i|
        xaddr = address + "." + i.to_s
        puts "pinging #{xaddr}"
        thr << Thread.new {
            `ping #{xaddr}` 
        }
    end

    thr.each do |t|
        t.join
        output = t.value
        puts output
    end
end

問題は、これは非常に遅く実行されるということです。アプリがスレッド化されていないように。何故ですか?Threadをサブクラス化すると、全体がはるかに高速に実行されることに気付きました。どうしたの?スレッドは直接使用するためのものではありませんか?

4

3 に答える 3

6

RubyスレッドはRubyインタープリターによって制御されます。オペレーティングシステムにとって、Ruby Interpreterはまだ1つのプロセスにすぎません(他のプロセスと同じように)。Ruby Interpreterは、その1つのプロセスを複数のrubyスレッドに分割しました。

`ping #{xaddr}`  

この行は、オペレーティングシステムに別のプロセスを実行するように要求しているため、Rubyインタープリターに一時的に制御を放棄させます。ルビーインタプリタは、「ping」が終了するまで制御を取り戻すことはありません。それがおそらくコードが遅い理由です。

于 2009-09-05T17:36:52.400 に答える
3

このようにIO.popenを使用できます

thr << Thread.new xaddr do |adr|
  IO.popen "ping #{adr}" do |io|
    io.each {|l| puts l}
  end
end

そうすれば、グリーンスレッドでもより多くの並行性を得ることができます。その理由は、インタプリタはpingの完全な出力が送信されるまで待つ必要がないためです。

于 2009-09-07T14:23:31.773 に答える
1

どのRuby実装を実行していますか?標準のRubyでは、スレッドは「グリーンスレッド」です。つまり、実際のオペレーティングシステムスレッドではなく、Rubyランタイムによって提供されます。

JRubyでは、スレッドは実際のOSスレッドです。これは、JVMがスレッドを実装する方法だからです。

そのため、Rubyの異なる実装間でスレッドのパフォーマンスに違いが見られる場合があります。JRubyはRuby1.8.6よりも高速であると見なされていますが、Ruby 1.9はJRubyよりも高速であることに注意してください(少なくとも一部のベンチマークでは)。

于 2009-09-05T14:46:05.997 に答える