2

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

3 Answers 3

6

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.

Sign up to request clarification or add additional context in comments.

5 Comments

ruby 1.8 does not support OS-level thread. If upgrade to ruby 1.9 is an option, try fibers. ruby-doc.org/core-1.9/classes/Fiber.html. Another option is using JRuby
This sucks. What could be the reason behind this?
umm...found a better article, it explains the reason why the ruby thread was implemented this way. blog.grayproductions.net/articles/the_ruby_vm_episode_iii
another idea, rather than use system call, why not try ruby's own ping library, ruby-doc.org/stdlib/libdoc/ping/rdoc/index.html. I have not tried it, but it might work
Updated URL for the article that @ez. mentioned: graysoftinc.com/the-ruby-vm-interview/the-ruby-vm-episode-iii
3

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.

Comments

1

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).

1 Comment

ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]. The thing is, this runs as if ran sequentially. If I make a subclass of Thread, it runs much better.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.