Ruby Execution

If you have a script with a lot of classes, does the interpreter read
through and ‘execute’ each class even though they haven’t yet been
called? Similarly, if you ‘require’ other libraries, does the
interpreter insert the code and execute it all, rather than if and when
each class is first referenced?

P.S. If you want to defer loading of classes until when they are used,
have a look at Kernel#autoload

Mike S. wrote:

If you have a script with a lot of classes, does the interpreter read
through and ‘execute’ each class even though they haven’t yet been
called?

Yes. Everything is done at runtime.

  • require ‘foo’ just loads and executes the code in foo.rb.

  • Code of the form “class X; def m; …” has the runtime effect of
    defining methods in classes.

  • It’s quite common to have code which sets up variables and/or
    constants too. For example:

class X
@count = 0

def self.create(*args)
@count += 1
new(*args)
end

def self.count
@count
end
end

a = X.create
b = X.create
puts X.count

Brian C. wrote:

P.S. If you want to defer loading of classes until when they are used,
have a look at Kernel#autoload

Is this the norm? I would have thought it would be a real problem
parsing big frameworks with myriads of classes everytime you want to
make a simple call. Is there a way of keeping a parsed script cached eg
for a web site that is handling hundreds of users doing the same sorts
of things eg browsing product lists?

Mike S. wrote:

Brian C. wrote:

P.S. If you want to defer loading of classes until when they are used,
have a look at Kernel#autoload

Is this the norm? I would have thought it would be a real problem
parsing big frameworks with myriads of classes everytime you want to
make a simple call.

Once a library has been require’d once, then the fact that this has been
done is recorded (in variable $LOADED_FEATURES), and so it won’t be
loaded again. If you want to check this out: require returns ‘true’ if
it had to load something, and ‘false’ if it didn’t.

Autoload goes one stage further: it won’t load the file unless the
constant doesn’t exist.

-------------------------------------------------------- Kernel#autoload
autoload(module, filename) => nil

 Registers _filename_ to be loaded (using +Kernel::require+) the
 first time that _module_ (which may be a +String+ or a symbol) is
 accessed.

    autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")

That is: the first time you try to do MyModule.foo, the file is
required, which (presumably) defines MyModule. Since it now exists, the
next call to MyModule.bar won’t touch any source files.

Is there a way of keeping a parsed script cached eg
for a web site that is handling hundreds of users doing the same sorts
of things eg browsing product lists?

As I say, once the file has been loaded, it’s loaded.

The only problem comes if you quit the process and restart it, as then
it obviously has to load everything again from scratch. I wrote
something which can help with that:

On 04.06.2009 13:40, Mike S. wrote:

Brian C. wrote:

P.S. If you want to defer loading of classes until when they are used,
have a look at Kernel#autoload

Is this the norm? I would have thought it would be a real problem
parsing big frameworks with myriads of classes everytime you want to
make a simple call. Is there a way of keeping a parsed script cached eg
for a web site that is handling hundreds of users doing the same sorts
of things eg browsing product lists?

Maybe this additional bit of information helps. When you run a Ruby
script the first thing that happens is that it is parsed and translated
into an internal binary representation (which one depends on the version
and platform used, e.g. ruby 1.9 is differently than 1.8 than JRuby).
Only then it is executed, which basically means that the internal
representation is interpreted in some way. This is typically pretty
efficient compared to the bourne shell approach of doing the parsing
line based.

I have no insights into JRuby but knowing the JVM it would even be
possible that eventually your Ruby code has become machine code when the
hot spot engine decides it should compile it.

To sum it up: you shouldn’t be too concerned about the efficiency of
that approach. The issue you are bringing up is rather valid in
situations where a largish application (i.e. multiple files) is needed
to execute only small interactions (for example when doing classic CGI
where a new process is started for each request).

Kind regards

robert