Why Was the Object_Id for True and Nil Changed in Ruby2.0

Why was the object_id for true and nil changed in ruby2.0?

A look at the Ruby source where these values are defined suggests that this has something to do with “flonums” (also see the commit where this was introduced). A search for ”flonum” came up with a message on the Ruby mailing list discussing it.

This is a technique for speeding up floating point calculations on 64 bit machines by using immediate values for some floating point vales, similar to using Fixnums for integers. The pattern for Flonums is ...xxxx xx10 (i.e. the last two bits are 10, where for fixnums the last bit is 1). The object_ids of other immediate values have been changed to accomodate this change.

You can see this change by looking at the object_ids of floats in Ruby 1.9.3 and 2.0.0.

In 1.9.3 different floats with the same value are different objects:

1.9.3p385 :001 > s = 10.234
=> 10.234
1.9.3p385 :002 > t = 10.234
=> 10.234
1.9.3p385 :003 > s.object_id
=> 2160496240
1.9.3p385 :004 > t.object_id
=> 2160508080

In 2.0.0 they are the same:

2.0.0p0 :001 > s = 10.234
=> 10.234
2.0.0p0 :002 > t = 10.234
=> 10.234
2.0.0p0 :003 > s.object_id
=> 82118635605473626
2.0.0p0 :004 > t.object_id
=> 82118635605473626

Why do Ruby object_ids for true, false, and nil seem to differ in Windows vs. Ubuntu?

As the accepted answer on the question you linked to says, 0, 20, and 8 are the Object IDs that are used when using flonums on YARV.

So, obviously, your Windows implementation is not using flonums. The most likely reason is that either you are not using YARV (e.g. using JRuby or Rubinius), or you are using YARV, but a 32 bit version.

Note: Object IDs are a private internal implementation detail of the particular Ruby implementation. The version of Ruby you are using is completely irrelevant. What is relevant is which implementation you are using, which version, which commandline options, how you compiled it, what your environment is and so on. It has nothing to do with the language.

Note also: you should never ever rely on the specific value of Object IDs. Object IDs guarantee two things, and only these two things:

  1. An object does not change its Object ID during its lifetime.
  2. No two objects have the same Object ID at the same time.

Here are some things that are not guaranteed:

  • It is not guaranteed that an object will have the same Object ID during different runs of the program.
  • It is not guaranteed that an Object ID is unique during the runtime of the program, it may be re-used for different objects as long as those objects don't live at the same time.
  • It is not guaranteed that the Object ID will follow a certain pattern, e.g. that it is always the memory address of the object (not true on JRuby, for example) or that it is always a specific value (not true for nil and false, as you have just discovered), or that it is always related to the object's value in some way (due to the specific way that YARV optimizes Integers, the Object ID for small integers will always be 2n+1, but that is only true for small integers (where the definition of "small" depends on whether you run a 64 bit or 32 bit version of YARV) and it is only an implementation detail that may change at any moment without notice).

In Ruby why does nil.id return 4?

This is because nil is an object created when the language initializes, and that object's id happens to always be 4.

For more information about why the id happens to be 4, see this blog post.

object_id of keys (and some other objects) are always the same. Why is that?

So i searched over the internet and found out this article http://threebrothers.org/brendan/blog/memory-and-ruby-symbols/ . I come to know that ruby process maintains a symbol table which has one entry per symbol as long as the process exists, so whenever a new symbol is created ruby do a search in that symbol table and if not exists it creates a new one to the last entry just like the entries in database tables.

More sources that can help:

Id2sym & symbol.object_id

How does object_id assignment work?

In MRI the object_id of an object is the same as the VALUE that represents the object on the C level. For most kinds of objects this VALUE is a pointer to a location in memory where the actual object data is stored. Obviously this will be different during multiple runs because it only depends on where the system decided to allocate the memory, not on any property of the object itself.

However for performance reasons true, false, nil and Fixnums are handled specially. For these objects there isn't actually a struct with the object's data in memory. All of the object's data is encoded in the VALUE itself. As you already figured out the values for false, true, nil and any Fixnum i, are 0, 2, 4 and i*2+1 respectively.

The reason that this works is that on any systems that MRI runs on, 0, 2, 4 and i*2+1 are never valid addresses for an object on the heap, so there's no overlap with pointers to object data.

Difference on working of object_id method with Fixnum object and String object

Fixnums are immutable objects in Ruby. There is exactly one instance created and you work with that object "directly". i.e references are not used unlike other regular objects. So They have a fixed object_id. This is ok because you have only one instance of the object.

But when you write "hello", a new string object is created. And in the same script, if you give another "hello", even though they have same content, a new object is created. Hence the different object_ids.

Fixed Object Id for System Objects and Small Integers in Ruby

The following two links explain the concept behind Ruby's object IDs:

http://www.oreillynet.com/ruby/blog/2006/01/the_ruby_value_1.html
http://www.oreillynet.com/ruby/blog/2006/02/ruby_values_and_object_ids.html

The object ID is calculated from the objects value plus some additional information. From that calculation you can derive the values you are seeing in your examples.



Related Topics



Leave a reply



Submit