Why does Ruby tend to assign object identifiers in descending order?

I noticed that objects have their identifiers given in the opposite order. The earlier an object is created, the larger its object identifier. I would think that they would be assigned in ascending order, and not vice versa.

For example:

obj1 = Object.new obj2 = Object.new obj3 = Object.new p obj1.object_id # => 4806560 p obj2.object_id # => 4806540 p obj3.object_id # => 4806520 

Why are they assigned in this way, and why is there a step 20, not 1 in the code launched by the Ruby interpreter, but a much greater difference between the object identifiers for the code executed by Ruby irb?

+8
ruby object-identity irb
source share
4 answers

Manual work on many details, a ruby ​​allocates a piece of heap to place objects in:

 1 | 2 | 3 | 4 | 5 

Then it moves them in order and adds them to the linked list of free objects. This makes them have the reverse order in the linked list:

 freelist β†’ NULL freelist β†’ 1 β†’ NULL freelist β†’ 2 β†’ 1 β†’ NULL freelist β†’ 3 β†’ 2 β†’ 1 β†’ NULL freelist β†’ 4 β†’ 3 β†’ 2 β†’ 1 β†’ NULL freelist β†’ 5 β†’ 4 β†’ 3 β†’ 2 β†’ 1 β†’ NULL 

When distributing an object, ruby ​​uses the first element in the linked list:

 object = freelist freelist = object.next_free 

So, now the freelist looks like this:

 freelist β†’ 4 β†’ 3 β†’ 2 β†’ 1 β†’ NULL 

and further selected objects will be displayed in reverse order through small selections.

When ruby ​​needs to allocate a new piece of the heap to store more objects, you will see how object_id starts, and then run it again.

+14
source share

The Ruby interpreter is a C program; you are probably looking at the corresponding memory addresses of objects.

+2
source share

For what it's worth, you can see a completely different progression in different implementations; each selects its objects differently, with buckets of different sizes.

MRI 1.9.3

 objs = [Object.new, Object.new, Object.new] objs.each {|o| puts o.object_id} # 70257700803740 # 70257700803700 # 70257700803680 

Juby

 objs = [Object.new, Object.new, Object.new] objs.each {|o| puts o.object_id} # 2048 # 2050 # 2052 

RBX

 objs = [Object.new, Object.new, Object.new] objs.each {|o| puts o.object_id} # 3920 # 3924 # 3928 
+2
source share

I just started a log of object identifiers, and it seemed that although everything went in order, garbage collection seemed to make things move toward each other once in a while. I have seen jumping from like 20 to 80 , so it seems almost random. But with the number of internal objects that Ruby supports, the orders of id objects do not depend on anything. It may also be that Ruby runs at the top of the local int or short platform to provide an easy test to complete ( if(current_id==0) { problem } ). From what I saw from our different numbers, it seems completely different and indefinable. It (almost) looks like Ruby can even use a pointer to an object, because it is guaranteed to be unique and explains the huge spaces (20 bytes) between the objects. When I look at the value returned by object_id and look at it next to my own pointer size of my system (64-bit Intel).

I just ran a test C ++ program on the same system that printed a pointer to an int . The pointer (in decimal) was 140734848324996 , and the Ruby object identifier was 70118105405380 . The numbers do not have much in common, but they are both in the same range and look like pointers.

Of course, if someone delves into the Ruby source and finds out, this will be a definite answer. I'm trying to.

0
source share

All Articles