[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

run test scripts concurrently

Chris McMahon

10/24/2006 10:02:00 PM

I've been futzing with this for some time and I am out of ideas.
I have a number of files named "test_something.rb" that each contain
one test like so:

class TC_foo < Test::Unit::TestCase
def test_foo
#do some stuff
#assert some things
end
end

I have a little harness that runs them one after another like so:

topdir = File.join(File.dirname(__FILE__))
Dir.chdir topdir do
tests = Dir["test*"]
tests.each{|x| require x}
end

But I would like to be able to run each individual script file in it's
own process simultaneously. I have been fooling around with
Thread.new, system(), exec(), and it seems that no matter what I try,
each script file has to finish before the next one will run.

Any suggestions for running all of my test files at the same time from
one controller/harness?

6 Answers

Ara.T.Howard

10/24/2006 10:29:00 PM

0

Paul Lutus

10/25/2006 12:09:00 AM

0

ara.t.howard@noaa.gov wrote:

> threads.each{|t| t.join}

In my expereince, if you join all the spawned threads to the current thread,
this guarantees that they will run sequentially. They will certainly run,
which is a good thing, but they won't run concurrently.

BTW I am not saying this about threads in general, I am saying it about Ruby
threads.

--
Paul Lutus
http://www.ara...

Joel VanderWerf

10/25/2006 12:39:00 AM

0

Paul Lutus wrote:
> ara.t.howard@noaa.gov wrote:
>
>> threads.each{|t| t.join}
>
> In my expereince, if you join all the spawned threads to the current thread,
> this guarantees that they will run sequentially. They will certainly run,
> which is a good thing, but they won't run concurrently.
>
> BTW I am not saying this about threads in general, I am saying it about Ruby
> threads.

This seems concurrent to me, or did you mean something different:

threads = (0..9).map {|i| Thread.new {sleep rand(5); puts i}}
threads.each {|t| t.join}

__END__

Output:

4
8
9
0
7
5
2
1
6
3

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Paul Lutus

10/25/2006 6:20:00 AM

0

Joel VanderWerf wrote:

> Paul Lutus wrote:
>> ara.t.howard@noaa.gov wrote:
>>
>>> threads.each{|t| t.join}
>>
>> In my expereince, if you join all the spawned threads to the current
>> thread, this guarantees that they will run sequentially. They will
>> certainly run, which is a good thing, but they won't run concurrently.
>>
>> BTW I am not saying this about threads in general, I am saying it about
>> Ruby threads.
>
> This seems concurrent to me, or did you mean something different:
>
> threads = (0..9).map {|i| Thread.new {sleep rand(5); puts i}}
> threads.each {|t| t.join}
>
> __END__
>
> Output:
>
> 4
> 8
> 9
> 0
> 7
> 5
> 2
> 1
> 6
> 3

I tried to think of an explanation apart from the obvious one, but it seems
I am wrong. I think the fact that they are all sleeping their time away may
partly explain this outcome, but the threads are clearly running
concurrently.

Threads that are not sleeping may not live up to the promise of this
example. My threads tend not to run concurrently, but your example is an
excellent refutation.

--
Paul Lutus
http://www.ara...

Charles Oliver Nutter

10/25/2006 7:05:00 AM

0

Paul Lutus wrote:
> I tried to think of an explanation apart from the obvious one, but it seems
> I am wrong. I think the fact that they are all sleeping their time away may
> partly explain this outcome, but the threads are clearly running
> concurrently.
>
> Threads that are not sleeping may not live up to the promise of this
> example. My threads tend not to run concurrently, but your example is an
> excellent refutation.

Threads that are 100% Ruby code will yield and timeslice correctly.
However they still will never run concurrently, other than timeslicing.
Threads that make system calls will run sequentially, since system calls
can't be scheduled by Ruby's thread scheduler. If you have a thread make
a system call, that call must complete before the thread will yield.

There's some trickery with IO in some cases, but for the general case
this is how it works. You may try JRuby, which has fully concurrent
native thread support, but not everything in normal Ruby is 100%
supported yet...and Kernel#system isn't quite perfect yet.

--
Charles Oliver Nutter, JRuby Core Developer
headius@headius.com -- charles.nutter@sun.com
Blogging at headius.blogspot.com

Joel VanderWerf

10/25/2006 6:47:00 PM

0

Charles Oliver Nutter wrote:
> Paul Lutus wrote:
>> I tried to think of an explanation apart from the obvious one, but it
>> seems
>> I am wrong. I think the fact that they are all sleeping their time
>> away may
>> partly explain this outcome, but the threads are clearly running
>> concurrently.
>>
>> Threads that are not sleeping may not live up to the promise of this
>> example. My threads tend not to run concurrently, but your example is an
>> excellent refutation.
>
> Threads that are 100% Ruby code will yield and timeslice correctly.
> However they still will never run concurrently, other than timeslicing.
> Threads that make system calls will run sequentially, since system calls
> can't be scheduled by Ruby's thread scheduler. If you have a thread make
> a system call, that call must complete before the thread will yield.

That's true at the C API level, but not always true at the Ruby API
level, as you say...

> There's some trickery with IO in some cases, but for the general case
> this is how it works. You may try JRuby, which has fully concurrent
> native thread support, but not everything in normal Ruby is 100%
> supported yet...and Kernel#system isn't quite perfect yet.

Is select() really trickery? Anyway, in addition to the IO trickery,
there is also a concurrent #system, as this example shows:

$ cat x.rb
t = Thread.new do
system "sleep 1; echo SYSTEM; sleep 1; echo SYSTEM; sleep 1; echo SYSTEM"
end

3.times do
sleep 1
puts "RUBY"
end

t.join

$ ruby x.rb
RUBY
SYSTEM
RUBY
SYSTEM
RUBY
SYSTEM

For some purposes (networking) ruby's threads are pretty good, to a
point. For some other purposes, we can use #fork plus drb. There are
cases where one is SOL though.

We're all looking forward to native threads in future ruby VMs and JRuby.

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407