为什么这样运行就像没有线程一样?

时间:2009-09-05 14:35:50

标签: windows ruby multithreading ping

我正在编写一个可以ping我的ip范围的脚本。这是我到目前为止所做的:

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 个答案:

答案 0 :(得分:6)

Ruby线程由Ruby Interpreter控制。对于操作系统,Ruby Interpreter仍然只是一个进程(就像任何其他进程一样)。 Ruby Interpreter将一个进程拆分为多个ruby线程。

`ping #{xaddr}`  

此行强制Ruby解释器暂时放弃其控制权,因为您要求操作系统执行另一个进程。在'ping'完成之后,ruby解释器才会重新获得控制权。这可能是代码缓慢的原因。

答案 1 :(得分:3)

您可以像这样使用IO.popen

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

即使使用绿色线程,您也可以获得更多的并发性。原因是解释器不必等到ping的完整输出发送完毕。

答案 2 :(得分:1)

您正在运行什么Ruby实现?在标准的Ruby中,线程是“绿色线程”,即不是真正的操作系统线程,而是由Ruby运行时提供的。

在JRuby中,线程是真正的操作系统线程,因为这是JVM实现它们的方式。

因此,您可能会发现Ruby的不同实现之间的线程性能存在差异。请注意,JRuby被认为比Ruby 1.8.6更快,尽管Ruby 1.9比JRuby快(至少在一些基准测试中)。

答案 3 :(得分:0)

嗯,好像我的性能相同

`...`

IO.popen ...

是相同的:http://gist.github.com/511599

我疯了吗?