An integer's life span?

Hello!

Here’s my code.


class Integer
def prime?
return false if self < 2
return @is_prime if @prime_cached
@prime_cached = true
(2…(self ** 0.5)).each do |i|
return (@is_prime = false) if i.prime? and self % i == 0
end
@is_prime = true
end
end

I want each integer to remember if it’s a prime number or not.
As the calculation uses cache of smaller prime numbers, it runs fast.
But I’m not sure if the cache is preserved after GC runs (when nothing
refers to the integers).
If the cache is not preserved, it’s no use.

My first idea was keeping the cache in a class variables like
@@prime_numbers and @@max_cached.
But I think it would be better if each object remembers its own state.

What do you think?

Sam

On Aug 7, 2006, at 2:40 PM, Sam K. wrote:

I want each integer to remember if it’s a prime number or not.
As the calculation uses cache of smaller prime numbers, it runs fast.
But I’m not sure if the cache is preserved after GC runs (when nothing
refers to the integers).
If the cache is not preserved, it’s no use.

IIRC an Integer’s instance variables are eternal due to various
implementation details.


Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

On 8/7/06, Eric H. [email protected] wrote:

IIRC an Integer’s instance variables are eternal due to various
implementation details.

Specifically due to the fact that integers are immediate values in ruby.
(Thus, are never collected)

So, attr_accessor prime would probably due the trick.

On 8/7/06, Gregory B. [email protected] wrote:

So, attr_accessor prime would probably due the trick.

err, typo there, and here is an example of what i mean.

bash-3.1$ irb

class Integer; attr_accessor :prime; end
=> nil
1.prime = true
=> true
2.prime = true
=> true
3.prime = true
=> true
5.prime = true
=> true
7.prime = true
=> true
(1…7).select { |n| n.prime }
=> [1, 2, 3, 5, 7]

might want to add a prime? method too.

On 8/7/06, Sam K. [email protected] wrote:

This is good news for my purpose.
However, that creates another worry.

(1…100000).each {|i|…}

Looks like in this case, they are garbage collected?

at startup
bash-3.1$ pmap 7764 | grep “total”
total 4560K

after each
bash-3.1$ pmap 7764 | grep “total”
total 4560K

Now there are 100000 integers in the memory which won’t die.
Is it okay?

but after adding an accessor for x, and setting it to true:
(1…100000).each { |i| i.x = true }

bash-3.1$ pmap 7764 | grep “total”
total 16308K

Big increase, but still not that bad.

Gregory B. wrote:

On 8/7/06, Eric H. [email protected] wrote:

IIRC an Integer’s instance variables are eternal due to various
implementation details.

Specifically due to the fact that integers are immediate values in ruby.
(Thus, are never collected)

Thank you for the answer.
This is good news for my purpose.
However, that creates another worry.

(1…100000).each {|i|…}

Now there are 100000 integers in the memory which won’t die.
Is it okay?

Sam

On 8/7/06, Sam K. [email protected] wrote:

    @prime_cached = true

But I’m not sure if the cache is preserved after GC runs (when nothing
refers to the integers).
If the cache is not preserved, it’s no use.

My first idea was keeping the cache in a class variables like
@@prime_numbers and @@max_cached.
But I think it would be better if each object remembers its own state.

What do you think?

I’m pretty sure that your concern about GC is moot, but just as long
as you stay with in the range of Fixnums. Fixnums are ‘immediate’
objects, and never get collected. I Bignums are another matter.

For Fixnums your code works as is. The @prime_cached iv is not needed
however, here’s another way to do it:

class Integer
def prime?
return false if self < 2
return @is_prime unless @is_prime.nil?
(2…self**0.5).each do | i |
return (@is_prime = false) if i.prime? and self
% i == 0
end
@is_prime = true
end
end


Rick DeNatale

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/

On Aug 7, 2006, at 5:20 PM, Jeremy H. wrote:

On 2006-08-07, Sam K. [email protected] wrote:

(1…100000).each {|i|…}

Now there are 100000 integers in the memory which won’t die.

No there aren’t. Immediate values don’t allocate anything in memory.
[… an accurate description of class Fixnum’s implementation]

Also, since a Fixnum is immediate, it doesn’t “have” instance
variables because there’s no Object to store them in. Instead they
are stored somewhere else. (Where isn’t terribly important.)

The instance variables will consume memory, of course.


Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

On 2006-08-07, Sam K. [email protected] wrote:

(1…100000).each {|i|…}

Now there are 100000 integers in the memory which won’t die.

No there aren’t. Immediate values don’t allocate anything in memory.
They aren’t pointers (even though under the hood Ruby coerces them to
the same type as non-immediate values that are pointers). Immediate
values aren’t garbage collected because there is nothing to garbage
collect. They don’t point to anything. What is there to collect?

Think of C. Does “long i ; i = 0 ; i = 1 ; i = 2 ; i = 3” consume any
more memory than “long i ; i = 0”? No, because the only memory
allocated is for the long variable “i”. The values 0, 1, 2, 3, are
just constants that are copied (one after the other) into that single
previously allocated space. Ruby’s immediate values are just like C
longs (in fact, under the hood, they are just C longs). Creating
them doesn’t consume memory, it just copies them into a pre-existing
chunk of memory that was already allocated by the Ruby interpreter.

If you create lots of references to immediate values, eg. by writing
" a = (1…100000).collect {|i| i } ", then that will consume memory.
But that memory isn’t being used to create immediate values, it’s
being used to store those values inside an object. Once that object
is no longer referenced the memory is available to be recycled by the
garbage collector. All memory allocation/deallocation is associated
with the non-immediate object that holds those references. The
immediate values themselves allocate no memory at all.

Regards,

Jeremy H.

Hi Jeremy,

Jeremy H. wrote:

On 2006-08-07, Sam K. [email protected] wrote:

(1…100000).each {|i|…}

Now there are 100000 integers in the memory which won’t die.

No there aren’t. Immediate values don’t allocate anything in memory.
They aren’t pointers (even though under the hood Ruby coerces them to
the same type as non-immediate values that are pointers). Immediate
values aren’t garbage collected because there is nothing to garbage
collect. They don’t point to anything. What is there to collect?

Think of C. Does “long i ; i = 0 ; i = 1 ; i = 2 ; i = 3” consume any
more memory than “long i ; i = 0”? No, because the only memory
allocated is for the long variable “i”. The values 0, 1, 2, 3, are
just constants that are copied (one after the other) into that single
previously allocated space. Ruby’s immediate values are just like C
longs (in fact, under the hood, they are just C longs). Creating
them doesn’t consume memory, it just copies them into a pre-existing
chunk of memory that was already allocated by the Ruby interpreter.

I understand what you said.
But the integers that I created have additional information.
So not that simple.
Can you read the code I wrote and reconsider such a case?

Thank you.

Sam

On Aug 7, 2006, at 5:40 PM, Sam K. wrote:

Immediate
them doesn’t consume memory, it just copies them into a pre-existing
chunk of memory that was already allocated by the Ruby interpreter.

I understand what you said.
But the integers that I created have additional information.
So not that simple.
Can you read the code I wrote and reconsider such a case?

It will work. The instance variables are stored elsewhere.


Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

On 8/8/06, Jeremy H. [email protected] wrote:

On 2006-08-08, Eric H. [email protected] wrote:

Also, since a Fixnum is immediate, it doesn’t “have” instance
variables because there’s no Object to store them in. Instead they
are stored somewhere else. (Where isn’t terribly important.)

Thanks for pointing that out. I had never thought to wonder where
immediate objects put their instance variables. Live and learn!

I hadn’t either, and it once again impressed me with Ruby.

About 20 years ago there was a raging discussion between advocates of
REALLY dynamic OO languages like self, and more traditional dynamic OO
languages like Smalltalk.

Dave Ungar, who did most of if not all of the implementation of
Berkley’s Smalltalk, and wrote his PhD dissertation on analysing it’s
performance, and then went on to develop self, used to love to ask
people who had done Smalltalk implementations to dynamically add an
instance variable to Object, something which invariably crashed, or
inf-looped whatever Smalltalk VM it was tried on.

Ruby not only can do that, but it can add instance variables to
instances.

Nice job, Matz!

On 2006-08-08, Eric H. [email protected] wrote:

Also, since a Fixnum is immediate, it doesn’t “have” instance
variables because there’s no Object to store them in. Instead they
are stored somewhere else. (Where isn’t terribly important.)

Thanks for pointing that out. I had never thought to wonder where
immediate objects put their instance variables. Live and learn!

Jeremy H.