Forum: Ruby Resetting ruby

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ccfe7d097475a32dc3ff78d6fc42c852?d=identicon&s=25 List Recv (lstrecv)
on 2006-01-16 02:28
I'm looking for a fast way to "reset" Ruby.  That is, to reset the
interpreter back to a fresh state, or, even better, a fresh state +
keeping some required ruby-gems.

My goal is to make a continuos test runner, and avoid the overhead of
having to restart ruby and require the gems each times.

I could do this with fork (copy-on-write), except I want this to run on
Win32 as well.

Any ideas?
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-01-16 02:42
(Received via mailing list)
On Jan 15, 2006, at 8:29 PM, List Recv wrote:

>
> Any ideas?
>
> --
> Posted via http://www.ruby-forum.com/.
>

I'm confused, why do you need to "reset" ruby everytime? Can't you
stick the tests in a loop?
Ccfe7d097475a32dc3ff78d6fc42c852?d=identicon&s=25 List Recv (lstrecv)
on 2006-01-16 02:47
Logan Capaldo wrote:
> I'm confused, why do you need to "reset" ruby everytime? Can't you
> stick the tests in a loop?

The code - and it's require files - are constantly changing.  (That's
the whole point of continuos testing!).  I want to a) make sure to
reload all required files and b) make sure to start with a fresh slate,
in terms of class definitions, ObjectSpace, and the like.
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-01-16 03:00
(Received via mailing list)
On Jan 15, 2006, at 8:47 PM, List Recv wrote:

> --
> Posted via http://www.ruby-forum.com/.
>

Ok, so change the 'require's to 'load's and then stick it in a
loop ;). In seriousness though, all the work involved with undefining
everything, and you might as well just start a new ruby executable.
Perhaps I'm not understanding you correctly, how would you do this
with fork, and avoid the overhead of requiring things?
Ccfe7d097475a32dc3ff78d6fc42c852?d=identicon&s=25 List Recv (lstrecv)
on 2006-01-16 06:03
Logan Capaldo wrote:
> On Jan 15, 2006, at 8:47 PM, List Recv wrote:
>
>> --
>> Posted via http://www.ruby-forum.com/.
>>
>
> Ok, so change the 'require's to 'load's and then stick it in a
> loop ;). In seriousness though, all the work involved with undefining
> everything, and you might as well just start a new ruby executable.
> Perhaps I'm not understanding you correctly, how would you do this
> with fork, and avoid the overhead of requiring things?

fork would save the overhead of loading ruby itself
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 Jacob Fugal (Guest)
on 2006-01-16 06:37
(Received via mailing list)
On 1/15/06, List Recv <listrecv@gmail.com> wrote:
> Logan Capaldo wrote:
> > Ok, so change the 'require's to 'load's and then stick it in a
> > loop ;). In seriousness though, all the work involved with undefining
> > everything, and you might as well just start a new ruby executable.
> > Perhaps I'm not understanding you correctly, how would you do this
> > with fork, and avoid the overhead of requiring things?
>
> fork would save the overhead of loading ruby itself

However, with fork you'd need to be careful about open filehandles and
the like which are shared between the processes. Getting consistent
results between a stay alive process like this and a new process each
time can be really tricky.

Jacob Fugal
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 Jacob Fugal (Guest)
on 2006-01-16 06:40
(Received via mailing list)
On 1/15/06, Logan Capaldo <logancapaldo@gmail.com> wrote:
> On Jan 15, 2006, at 8:47 PM, List Recv wrote:
> > The code - and it's require files - are constantly changing.  (That's
> > the whole point of continuos testing!).  I want to a) make sure to
> > reload all required files and b) make sure to start with a fresh
> > slate,
> > in terms of class definitions, ObjectSpace, and the like.
>
> Ok, so change the 'require's to 'load's and then stick it in a
> loop ;).

That's not quite sufficient. 'load' simply loads the file again. It
doesn't replace the result of previously loading the file. So if the
"signature" of the file is the same (all the same classes, methods,
variables, etc. declared only with different values/implementations)
you're good. But in the more frequent case where the signature changes
in a non-additive way (e.g. a method is removed), that change is *not*
propagated by a new load. That means the method that was removed is
still available within the test script, which may cause some tests to
pass which should fail and would fail if run under a new instance.

Jacob Fugal
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-01-16 06:46
(Received via mailing list)
On Jan 16, 2006, at 12:39 AM, Jacob Fugal wrote:

> in a non-additive way (e.g. a method is removed), that change is *not*
> propagated by a new load. That means the method that was removed is
> still available within the test script, which may cause some tests to
> pass which should fail and would fail if run under a new instance.
>
> Jacob Fugal
>

I know, hence the smiley face. I still think this idea is a little
extreme for the minor savings you'd get out of it.
16387c93f47b571515a116d3a11847e3?d=identicon&s=25 Dalibor Sramek (Guest)
on 2006-01-16 12:35
(Received via mailing list)
On Mon, Jan 16, 2006 at 02:45:46PM +0900, Logan Capaldo wrote:
> I know, hence the smiley face. I still think this idea is a little
> extreme for the minor savings you'd get out of it.

The possibility to reset the interpreter would be IMHO useful also for
other
situations where you have persistent Ruby processes (think mod_ruby).

Dalibor Sramek
52a177e9dbd3e614825aabc4e45f8cd6?d=identicon&s=25 Mark Volkmann (Guest)
on 2006-01-16 14:45
(Received via mailing list)
On 1/16/06, Dalibor Sramek <dali@insula.cz> wrote:
> On Mon, Jan 16, 2006 at 02:45:46PM +0900, Logan Capaldo wrote:
> > I know, hence the smiley face. I still think this idea is a little
> > extreme for the minor savings you'd get out of it.
>
> The possibility to reset the interpreter would be IMHO useful also for other
> situations where you have persistent Ruby processes (think mod_ruby).

It would also be useful for debuggers so you could rerun the program
without having to re-enter breakpoints. As far as I know, this isn't
currently possible with the built-in Ruby debugger. Can any Ruby
debuggers do this now?
A6d3a37b5badfdd2f47655aa0e46604e?d=identicon&s=25 Eivind Eklund (Guest)
on 2006-01-16 15:18
(Received via mailing list)
On 1/16/06, List Recv <listrecv@gmail.com> wrote:
> I'm looking for a fast way to "reset" Ruby.  That is, to reset the
> interpreter back to a fresh state, or, even better, a fresh state +
> keeping some required ruby-gems.
>
> My goal is to make a continuos test runner, and avoid the overhead of
> having to restart ruby and require the gems each times.

I've got code for this kind of testrunner; no specific optimizations,
though.  It's a plain testrunner using pipes for communication and a
fork to separate out the execution.  There's something clumsy about it
- I don't remember what it was.

If you're dead set on doing this inside a single Ruby process, this
won't help - if you want an easy way out, I'll try to dig up the code
- it wasn't in the obvious places :-/

Eivind.
6ec6f77ea603dd75b3a7a7775b059e79?d=identicon&s=25 John W. Long (Guest)
on 2006-01-16 15:39
(Received via mailing list)
List Recv wrote:
 > I'm looking for a fast way to "reset" Ruby.  That is, to reset the
 > interpreter back to a fresh state, or, even better, a fresh state +
 > keeping some required ruby-gems.
 >
 > My goal is to make a continuous test runner, and avoid the overhead
of
 > having to restart ruby and require the gems each times.

One thing you could do would be to load up all of your libraries and
pause on the terminal waiting for user input. As soon as the user
unpaused the process it would load in the test cases and run them. As
the user was looking at the output and fixing tests you could load up
another instance and pause waiting for user input. Stir and repeat...

I've thought for a long time that something like this would be very
useful for Rails testing where loading up the library code takes 2-3
seconds, making unit testing tedious.
Ccfe7d097475a32dc3ff78d6fc42c852?d=identicon&s=25 List Recv (lstrecv)
on 2006-01-16 16:27
Dalibor Sramek wrote:
> The possibility to reset the interpreter would be IMHO useful also for other
> situations where you have persistent Ruby processes (think mod_ruby).

John W. Long wrote:
> I've thought for a long time that something like this would be very
> useful for Rails testing where loading up the library code takes 2-3
> seconds, making unit testing tedious.

Okay, Ruby core hackers, can you answer our call?!
6ec6f77ea603dd75b3a7a7775b059e79?d=identicon&s=25 John W. Long (Guest)
on 2006-01-16 16:40
(Received via mailing list)
List Recv wrote:
> Okay, Ruby core hackers, can you answer our call?!

I don't think there's a need for Ruby core hacking if you follow my
suggestion:

 >> One thing you could do would be to load up all of your libraries and
 >> pause on the terminal waiting for user input. As soon as the user
 >> unpaused the process it would load in the test cases and run them.
As
 >> the user was looking at the output and fixing tests you could load
up
 >> another instance and pause waiting for user input. Stir and
repeat...
8a85c693f13ef7cb542ef94d2a403d4d?d=identicon&s=25 Luc Heinrich (Guest)
on 2006-01-17 02:07
(Received via mailing list)
On 16 janv. 06, at 12:33, Dalibor Sramek wrote:

> The possibility to reset the interpreter would be IMHO useful also
> for other
> situations where you have persistent Ruby processes (think mod_ruby).

(going slightly offtopic)

I have recently dived into Tcl (the "Practical Programming in Tcl and
Tk" book by Welch, Jones and Hobbs is pretty good) and while I still
haven't managed to go past the "o-m-f-g-YUCK!" state as far as the
core language is concerned, I must say that the core implementation
provides some *really* nifty features which I would *really* love to
see in Ruby and which would incidentally make the original poster
question trivial to do.

For example, you can spawn clean and fresh "sub-interpreter(s)" which
you can then use as isolated (and optionally safe) sandboxe(s).
Here's a sample usage:

% interp create worker
worker
% interp eval worker {set a 42}
42
% puts $a
can't read "a": no such variable
% interp delete worker

In the first line we create a sub-interpreter and name it 'worker'.
In the second line we execute a simple command: we set assign the
value 42 to the variable 'a'. In the third line we try to print the
value of 'a', which causes an error. This shows that the 'main'
interpreter and our 'worker' sub-interpreter are clearly isolated
from each other. Finally, we get rid of the sub-interpreter.

Another (different) aspect of Tcl which I really like is how event
loops are used to provide ultra-simple interthreads communication
with message queuing and all that jazz:

% package require Thread
% set worker [thread::create]
% thread::send -async $worker {...some longish calculation...}
% thread::send -async $worker {...some other longish calculation...}
% ...continue on the main thread...

Rite is supposed to be reentrant, so I guess that it shouldn't be
very hard to build such things upon Ruby 2.0. Oh my, I am *so*
looking forward to it... :)
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-01-17 04:04
(Received via mailing list)
Luc Heinrich wrote:
...
> Rite is supposed to be reentrant, so I guess that it shouldn't be very
> hard to build such things upon Ruby 2.0. Oh my, I am *so* looking
> forward to it... :)

Aside from the use of native threads in this tcl example (IIRC), this is
not hard to do in ruby. And with 2.0, we'll have native threads...

Anyway here's one way to do worker threads:

require 'thread'

class WorkerThread < Thread
  def initialize
    super do
      @queue = Queue.new
      loop do
        @queue.pop.call
      end
    end
  end

  def push(&bl)
    @queue << bl
  end
end

def very_long_calculation; (10**10000).to_s.size; end

qt = WorkerThread.new
results = Queue.new

qt.push do
  results.push(very_long_calculation)
end

p results.pop
F91f1034d620825594db83db92ca1711?d=identicon&s=25 Michael Ulm (Guest)
on 2006-01-17 08:59
(Received via mailing list)
John W. Long wrote:

>  >> unpaused the process it would load in the test cases and run them. As
>  >> the user was looking at the output and fixing tests you could load up
>  >> another instance and pause waiting for user input. Stir and repeat...
>

That would work in this one case where resetting is useful. As this
thread has shown, there are others. Here is mine: I want to use an
irb-like environment in conjunction with gsl as a kind of super
calculator/numerical test engine. A reset method would be tremendously
useful as one often wants to start with a clean slate, without losing
all the output from the previous computations.

So, I second List Recv's plea to the core hackers: ideas anyone?
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-01-17 19:52
(Received via mailing list)
Michael Ulm wrote:
>>  >> One thing you could do would be to load up all of your libraries and
> useful as one often wants to start with a clean slate, without losing
> all the output from the previous computations.
>
> So, I second List Recv's plea to the core hackers: ideas anyone?
>

Doesn't GC clean the slate well enough for calculations?
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 Eric Hodel (Guest)
on 2006-01-18 00:09
(Received via mailing list)
On Jan 15, 2006, at 5:29 PM, List Recv wrote:

> I'm looking for a fast way to "reset" Ruby.  That is, to reset the
> interpreter back to a fresh state, or, even better, a fresh state +
> keeping some required ruby-gems.
>
> My goal is to make a continuos test runner, and avoid the overhead of
> having to restart ruby and require the gems each times.

In order to ensure your tests won't fail or pass when they should do
the opposite you should start up from a clean interpreter.

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com
This topic is locked and can not be replied to.