30 Days of Tech: Day 26 - Fixnum#object_id

In Ruby every object has an object_id that uniquely identifies that object in that particular instance of the Ruby process. Ruby also treats integers as objects—they are instances of Fixnum. For efficiency reasons, though, Ruby implements integers internally as simple values. That is, it doesn’t allocate heap memory for every integer you use, it just passes the value around instead. So how does Ruby generate object ids for all these integers?

You may have never noticed, but all the object ids that you usually end up seeing are even.


  irb(main):011:0> Object.object_id
  => 110230
  irb(main):012:0> Object.new.object_id
  => 191490
  irb(main):013:0> nil.object_id
  => 4
  irb(main):014:0> "a_string".object_id
  => 177360

This is because Ruby is reserving all the odd numbers to be object_ids for Fixnums.


  irb(main):015:0> 1.object_id
  => 3
  irb(main):016:0> 2.object_id
  => 5
  irb(main):017:0> 3.object_id
  => 7
  irb(main):018:0> 4.object_id
  => 9

Not only are they reserved, they’re calculated using a simple formula! This allows Ruby to easily get back to the value from the id if you should ever ask for it.


  irb(main):022:0> ObjectSpace._id2ref(9)  
  => 4

And now if you ever see an odd (as in n % 2 = 1, not strange) object_id in some Ruby output somewhere, you’ll know immediately what the value of that object is!