On Mon, 19 Mar 2001, Jean-Sebastien ROY wrote:

> I recently came across a little performance problem I have difficulties 
> to explain.
...
> So I tried to disable the Garbage Collector (GC.disable) :
> 
> With GC.disable, tmax = 1000 and const = 1, the code take 1.52s to run.
> With GC.disable, tmax = 1000 and const = 1.0, the code take 1.89s to run.
> 
> Could someone explain to me why the floating point addition seems to 
> trigger the GC ?

You almost got it. The reason is just what you thought it to be. It's
about GCing.

First your code created a bunch of objects. Then it looped
and measured the time to sum linearly one million integers. It was
fast. It was fast because integers are kept in the object reference
itself. (And Ruby just pretends to have them in a real objects.)

Calculating with floats was slower for couple of reasons. First each
summation generated a new float object (new object instead of no object
for integer). But the majority of speed decrease came from GC. Once the
memory was filled with once used floats which were abandoned and Ruby ran
out of memory it GCed. Then it had to go through the pre-allocated objects
to see if they're referring to any other objects in order to release the
memory taken by object which are not used anymore. So each normal GC
besides out-of-memory-GC generated a pass through all the objects in
memory and a major slowdown.

The next version of Ruby incorporates a generational GC which should be
much faster regarding cases like this. I suppose it works by moving
"old" objects (like the ones you pre-allocated) after dozen of GC marking
passes to a separate "old object" pool which is checked not so often.

I expect the performance in cases of lots of object creating will be
boosted quite much.

	- Aleksi