问题
I'm writing a script that will ping my ip range. Here's what I have so far:
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
The thing is, this executes extremely slow. Like the app isn't threaded. Why is that? I noticed that if I subclass Thread, the whole thing runs much, much faster. What's wrong? Isn't Thread intended for direct usage?
回答1:
Ruby threads are controlled by Ruby Interpreter. to operating system, Ruby Interpreter is still just one process(just like any other processes). Ruby Interpreter split that one process into multiple ruby threads.
`ping #{xaddr}`
this line forces the Ruby Interpreter to temporarily give up its control, since you are asking the operating system to execute another process. The ruby interpreter will not regain its control until after the 'ping' finishes. That's probably why the code is slow.
回答2:
You can use IO.popen like this
thr << Thread.new xaddr do |adr|
IO.popen "ping #{adr}" do |io|
io.each {|l| puts l}
end
end
That way you get more concurrency even with green threads. The reason is that the interpreter does not have to wait until the full output of ping has been sent.
回答3:
What Ruby implementation are you running on? In standard Ruby, threads are "green threads", i.e. not real operating system threads but provided by the Ruby runtime.
In JRuby, threads are real OS threads because that's how the JVM implements them.
So, you may see a difference in threading performance between different implementations of Ruby. Note that JRuby is regarded as faster that Ruby 1.8.6, though Ruby 1.9 is faster than JRuby (at least on some benchmarks).
来源:https://stackoverflow.com/questions/1383470/why-is-this-running-like-it-isnt-threaded